Make a responsive navigation with html, css, and javascript for your Portfolio Website
In the world of web development, creating a visually appealing and responsive portfolio website is a key step to showcasing your skills and projects. In this article, we’ll guide you through creating a responsive navigation and hero section for your portfolio website. We’ll also add a theme toggle, allowing users to switch between dark and light modes. This project combines HTML, CSS, and vanilla JavaScript to provide a dynamic and interactive user experience.
Before starting this Responsive Navigation and Hero Page project, I encourage you to take a moment to watch this video to get a better sense of what it looks like.
Step 1: Setting Up Your Project
Before diving into the code, let’s set up our project:
Create a new folder for your project and give it a meaningful name.
Inside this folder, create the following files:
- ‘
index.html'
for your main HTML file. - ‘
style.css'
for your CSS code. - ‘
index.js'
for your JavaScript code.
Copy and Paste the following HTML, CSS and JavaScript file into your Project.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--UNICONS-->
<link rel="stylesheet" href="https://unicons.iconscout.com/release/v4.0.0/css/line.css">
<!--Fontawasome-->
<script src="https://kit.fontawesome.com/2efc16a506.js" crossorigin="anonymous"></script>
<link rel="stylesheet" href="styles.css">
<title>Responsive Navigation</title>
</head>
<body>
<!--============================================
====================== HEADER =============
=============================================-->
<header class="header" id="header">
<nav class="nav container">
<a href="#" class="nav__logo">pbc | webdev</a>
<div class="nav__menu" id="nav-menu">
<ul class="nav__list grid">
<li class="nav__item">
<a href="#home" class="nav__link active-link">
<i class="uil uil-estate nav__icon"></i> Home
</a>
</li>
<li class="nav__item">
<a href="#about" class="nav__link">
<i class="uil uil-user nav__icon"></i> About
</a>
</li>
<li class="nav__item">
<a href="#skills" class="nav__link">
<i class="uil uil-file-alt nav__icon"></i> Skills
</a>
</li>
<li class="nav__item">
<a href="#services" class="nav__link">
<i class="uil uil-briefcase nav__icon"></i> Services
</a>
</li>
<li class="nav__item">
<a href="#portfolio" class="nav__link">
<i class="uil uil-scenery nav__icon"></i> Portfolio
</a>
</li>
<li class="nav__item">
<a href="#contact" class="nav__link">
<i class="uil uil-message nav__icon"></i> Contact
</a>
</li>
</ul>
<i class="uil uil-times nav__close" id="nav-close"></i>
</div>
<div class="nav__btns">
<!--Theme change button-->
<i class="uil uil-moon change-theme" id="theme-button"></i>
<div class="nav__toggle" id="nav-toggle">
<i class="uil uil-apps"></i>
</div>
</div>
</nav>
</header>
<!--=============== MAIN ==================-->
<main class="main">
<!--//////////////////////////////////////////
================= HOME==================
/////////////////////////////////////////-->
<section class="home section" id="home">
<div class="home__container container grid">
<div class="home__content grid">
<div class="home__social">
<a href="https://www.linkedin.com/in/prem-bahadur-chand/" target="_blank"
class="home__social-icon">
<i class="uil uil-linkedin-alt"></i>
</a>
<a href="https://twitter.com/" target="_blank" class="home__social-icon">
<i class="uil uil-twitter-alt"></i>
</a>
<a href="https://github.com/merpssirk" target="_blank" class="home__social-icon">
<i class="uil uil-github-alt"></i>
</a>
</div>
<div class="home__img">
<svg class="home__blob" viewBox="0 0 200 187" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<mask id="mask0" mask-type="alpha">
<path d="M190.312 36.4879C206.582 62.1187 201.309 102.826 182.328 134.186C163.346 165.547
130.807 187.559 100.226 186.353C69.6454 185.297 41.0228 161.023 21.7403 129.362C2.45775
97.8511 -7.48481 59.1033 6.67581 34.5279C20.9871 10.1032 59.7028 -0.149132 97.9666
0.00163737C136.23 0.303176 174.193 10.857 190.312 36.4879Z" />
</mask>
<g mask="url(#mask0)">
<path d="M190.312 36.4879C206.582 62.1187 201.309 102.826 182.328 134.186C163.346
165.547 130.807 187.559 100.226 186.353C69.6454 185.297 41.0228 161.023 21.7403
129.362C2.45775 97.8511 -7.48481 59.1033 6.67581 34.5279C20.9871 10.1032 59.7028
-0.149132 97.9666 0.00163737C136.23 0.303176 174.193 10.857 190.312 36.4879Z" />
<image class="home__blob-img" x="3" y="5" xlink:href="./image/prem-bahadur-chand.png" />
</g>
</svg>
</div>
<div class="home__data">
<h1 class="home__title">
Hi, I'am [Put your name here]
</h1>
<h3 class="home__subtitle">
Full-Stack Web Developer <span class="home__mern">(MERN Stack)</span>
</h3>
<p class="home__description">
The website takes a long time to build. There are a lot of things that have to happen before
it can go live. Good things take time to create and any good designer or developer is going
to take their time so they deliver you something that both them and you can be proud of.
</p>
<p class="home__description">
I enjoy taking complex problems and turning them into simple and beautiful interface
designs. I also love the logic and structure of coding and always strive to write elegant
and efficient code. Whether it be HTML, CSS, SASS, Bootstrap, React, JS or WordPress.
</p>
</div>
</div>
<div class="home__scroll">
<a href="#about" class="home__scroll-button button--flex">
<i class="uil uil-mouse-alt home__scroll-mouse"></i>
<span class="home_scroll-name">Scroll Down</span>
<i class="uil uil-arrow-down home__scroll-arrow"></i>
</a>
</div>
</div>
</section>
</main>
<!--==================== MAIN JS ================-->
<script src="script.js"></script>
</body>
</html>
CSS
/*
////////////////////////////////////////////////
=================CSS VARIABLES===============
///////////////////////////////////////////////
*/
:root {
--header-height: 3rem;
/*========== Colors ==========*/
/* Change favorite color */
--hue-color: 10;
/* HSL color mode */
--first-color: hsl(var(--hue-color), 56%, 52%);
--text-color-light: hsl(var(--hue-color), 8%, 65%);
--input-color: hsl(var(--hue-color), 70%, 96%);
--body-color: hsl(var(--hue-color), 60%, 99%);
/*========== Font and typography ==========*/
--body-font: "Poppins", sans-serif;
--h1-font-size: 1.5rem;
--h3-font-size: 1.125rem;
--normal-font-size: 0.938rem;
--small-font-size: 0.813rem;
--smaller-font-size: 0.75rem;
/*========== Font weight ==========*/
--font-medium: 500;
--font-semi-bold: 600;
/*========== Margines Bottom ==========*/
--mb-0-5: 0.5rem;
--mb-0-75: 0.75rem;
--mb-1: 1rem;
--mb-1-5: 1.5rem;
--mb-2: 2rem;
--mb-2-5: 2.5rem;
--mb-3: 3rem;
}
/* ////////////////////////////////////////////////
/////////////Font size for large devices//////////
////////////////////////////////////////////////////
*/
@media screen and (min-width: 968px) {
:root {
--big-font-size: 3rem;
--h1-font-size: 2.25rem;
--h3-font-size: 1.25rem;
--normal-font-size: 1rem;
--small-font-size: 0.875rem;
--smaller-font-size: 0.813rem;
}
}
/*
///////////////////////////////////////////
========== Variables Dark theme ==========
///////////////////////////////////////////
*/
body.dark-theme {
/* HSL color mode */
--first-color-second: hsl(var(--hue-color), 30%, 8%);
--title-color: hsl(var(--hue-color), 8%, 95%);
--text-color: hsl(var(--hue-color), 8%, 75%);
--input-color: hsl(var(--hue-color), 29%, 16%);
--body-color: hsl(var(--hue-color), 28%, 12%);
--container-color: hsl(var(--hue-color), 29%, 16%);
--scroll-bar-color: hsl(var(--hue-color), 12%, 48%);
--scroll-thumb-color: hsl(var(--hue-color), 12%, 36%);
}
/*
//////////////////////////////////////////
========== Button Dark/Light ==========
/////////////////////////////////////////
*/
.nav__btns {
display: flex;
align-items: center;
}
.change-theme {
font-size: 1.25rem;
color: var(--text-color);
margin-right: var(--mb-1);
cursor: pointer;
}
.change-theme:hover {
color: var(--first-color);
}
/*
//////////////////////////////////////////////
==================== BASE ====================
//////////////////////////////////////////////
*/
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
html {
scroll-behavior: smooth;
}
body {
margin: 0 0 var(--header-height) 0;
font-family: var(--body-font);
font-size: var(--normal-font-size);
background-color: var(--body-color);
color: black;
}
ul {
list-style: none;
}
a {
text-decoration: none;
}
/*
//////////////////////////////////////////////
==================== NAVIGATION ==============
//////////////////////////////////////////////
*/
.container {
max-width: 768px;
margin-left: var(--mb-1-5);
margin-right: var(--mb-1-5);
}
.grid {
display: grid;
gap: 1.5rem;
}
.header {
width: 100%;
position: fixed;
bottom: 0;
left: 0;
z-index: var(--z-fixed);
background-color: var(--body-color);
}
.nav {
max-width: 968px;
height: var(--header-height);
display: flex;
justify-content: space-between;
align-items: center;
}
.nav__logo,
.nav__toggle {
color: var(--text-color);
font-weight: var(--font-medium);
}
.nav__logo:hover {
color: var(--first-color);
}
.nav__toggle {
font-size: 1.1rem;
cursor: pointer;
}
.nav__toggle:hover {
color: var(--first-color);
}
@media screen and (max-width: 767px) {
.nav__menu {
position: fixed;
bottom: -100%;
left: 0;
width: 100%;
background-color: white;
padding: 2rem 1.5rem 4rem;
box-shadow: 0 -1px 4px rgba(0, 0, 0, 0.15);
border-radius: 1.5rem 1.5rem 0 0;
transition: 0.3s;
}
}
.nav__list {
grid-template-columns: repeat(3, 1fr);
gap: 2rem;
}
.nav__link {
display: flex;
flex-direction: column;
align-items: center;
font-size: var(--small-font-size);
color: var(--text-color);
font-weight: var(--font-medium);
}
.nav__link:hover {
color: var(--first-color);
}
.nav__icon {
font-size: 1.2rem;
}
.nav__close {
position: absolute;
right: 1.3rem;
bottom: 0.5rem;
font-size: 1.5rem;
cursor: pointer;
color: var(--text-color);
}
.nav__close:hover {
color: var(--first-color);
}
/* show menu */
.show-menu {
bottom: 0;
}
/* Active link */
.active-link {
color: var(--first-color);
}
/* Change background header */
.scroll-header {
box-shadow: 0 -1px 4px rgba(10, 10, 10, 0.7);
}
/*
////////////////////////////////////////////////
==================== HOME ====================
////////////////////////////////////////////////
*/
.home__container {
gap: 1rem;
}
.home__content {
grid-template-columns: 0.5fr 3fr;
padding-top: 3.5rem;
align-items: center;
}
.home__social {
display: grid;
grid-template-columns: max-content;
row-gap: 1rem;
}
.home__social-icon {
font-size: 1.25rem;
color: var(--first-color);
}
.home__social-icon:hover {
color: #333333;
}
.home__blob {
width: 200px;
fill: var(--first-color);
}
.home__blob-img {
width: 185px;
}
.home__data {
grid-column: 1/3;
}
.home__title {
font-size: var(--h1-font-size);
color: var(--text-color);
}
.home__subtitle {
font-size: var(--h3-font-size);
color: var(--text-color-light);
font-weight: var(--font-medium);
margin-bottom: var(--mb-0-75);
margin-top: var(--mb-0-5);
}
.home__description {
margin-bottom: var(--mb-2);
color: var(--text-color-light);
line-height: 25px;
}
.home__mern {
font-size: 16px;
}
.home__scroll {
/*display: none;*/
}
.home__scroll-button {
color: #808080;
transition: 0.3s;
}
.home__scroll-button:hover {
transform: translateY(0.25rem);
}
.home__scroll-mouse {
font-size: 2rem;
}
.home_scroll-name {
font-size: var(--small-font-size);
color: var(--first-color);
font-weight: var(--font-medium);
margin-right: var(--mb-0-25);
}
.home__scroll-arrow {
font-size: 1.25rem;
}
/*
////////////////////////////////////////////////////////
==================== MEDIA QUERIES ====================
//////////////////////////////////////////////////////
*/
/* For small devices
*/
@media screen and (max-width: 350px) {
.container {
margin-left: var(--mb-1);
margin-right: var(--mb-1);
}
.nav__menu {
padding: 2rem 0.25rem 4rem;
}
.nav__list {
column-gap: 0;
}
.home__content {
grid-template-columns: 0.25fr 3fr;
}
.home__blob {
width: 180px;
}
}
/*
////////////////////////////////////////////
///////////// For medium devices///////////
//////////////////////////////////////////
*/
@media screen and (min-width: 568px) {
.home__content {
grid-template-columns: max-content 1fr 1fr;
}
.home__data {
grid-column: initial;
}
.home__img {
order: 1;
justify-self: center;
}
}
@media screen and (min-width: 768px) {
.container {
margin-left: auto;
margin-right: auto;
margin-top: 1rem;
margin-bottom: 1rem;
}
body {
margin: 0;
}
.section {
padding: 6rem 0 2rem;
}
.section__subtitle {
margin-bottom: 4rem;
}
.header {
top: 0;
bottom: initial;
}
.header,
.main,
.footer__container {
padding: 0 1rem;
}
.nav {
height: calc(var(--header-height)+ 1.5rem);
column-gap: 1rem;
}
.nav__icon,
.nav__close,
.nav__toggle {
display: none;
}
.nav__list {
display: flex;
column-gap: 2rem;
}
.nav__menu {
margin-left: auto;
}
.change-theme {
margin: 0;
}
.home__container {
row-gap: 5rem;
}
.home__content {
padding-top: 5.5rem;
column-gap: 2rem;
}
.home__blob {
width: 270px;
}
.home__scroll {
display: block;
}
.home__scroll-button {
margin-left: 3rem;
}
.change-theme {
margin: 0;
}
}
/*
/////////////////////////////////////////////////
////////////////For large devices////////////////
//////////////////////////////////////////////////
*/
@media screen and (min-width: 1024px) {
.header,
.main {
padding: 0;
}
.home__blob {
width: 320px;
}
.home__social {
transform: translateX(-6rem);
}
}
JAVASCRIPT
/*==================== MENU SHOW Y HIDDEN ====================*/
const navMenu = document.getElementById('nav-menu'),
navToggle = document.getElementById('nav-toggle'),
navClose = document.getElementById('nav-close');
/*===== MENU SHOW =====*/
/* Validate if constant exists */
if(navToggle){
navToggle.addEventListener('click', ()=>{
navMenu.classList.add('show-menu')
})
}
/*===== MENU HIDDEN =====*/
/* Validate if constant exists */
if(navClose) {
navClose.addEventListener('click', ()=>{
navMenu.classList.remove('show-menu')
})
}
/*==================== REMOVE MENU MOBILE ====================*/
const navLink = document.querySelectorAll('.nav__link')
function linkAction(){
const navMenu = document.getElementById('nav-menu')
// When we click on each nav__link, we remove the show-menu class
navMenu.classList.remove('show-menu')
}
navLink.forEach(n => n.addEventListener('click', linkAction))
/*==================== CHANGE BACKGROUND HEADER ====================*/
function scrollHeader(){
const nav = document.getElementById('header')
// When the scroll is greater than 200 viewport height, add the scroll-header class to the header tag
if(this.scrollY >= 80) nav.classList.add('scroll-header'); else nav.classList.remove('scroll-header')
}
window.addEventListener('scroll', scrollHeader)
/*==================== SHOW SCROLL UP ====================*/
function scrollUp(){
const scrollUp = document.getElementById('scroll-up');
// When the scroll is higher than 560 viewport height, add the show-scroll class to the a tag with the scroll-top class
if(this.scrollY >= 560) scrollUp.classList.add('show-scroll'); else scrollUp.classList.remove('show-scroll')
}
window.addEventListener('scroll', scrollUp)
/*==================== DARK LIGHT THEME ====================*/
const themeButton = document.getElementById('theme-button')
const darkTheme = 'dark-theme'
const iconTheme = 'uil-sun'
// Previously selected topic (if user selected)
const selectedTheme = localStorage.getItem('selected-theme')
const selectedIcon = localStorage.getItem('selected-icon')
// We obtain the current theme that the interface has by validating the dark-theme class
const getCurrentTheme = () => document.body.classList.contains(darkTheme) ? 'dark' : 'light'
const getCurrentIcon = () => themeButton.classList.contains(iconTheme) ? 'uil-moon' : 'uil-sun'
// We validate if the user previously chose a topic
if (selectedTheme) {
// If the validation is fulfilled, we ask what the issue was to know if we activated or deactivated the dark
document.body.classList[selectedTheme === 'dark' ? 'add' : 'remove'](darkTheme)
themeButton.classList[selectedIcon === 'uil-moon' ? 'add' : 'remove'](iconTheme)
}
// Activate / deactivate the theme manually with the button
themeButton.addEventListener('click', () => {
// Add or remove the dark / icon theme
document.body.classList.toggle(darkTheme)
themeButton.classList.toggle(iconTheme)
// We save the theme and the current icon that the user choose
localStorage.setItem('selected-theme', getCurrentTheme())
localStorage.setItem('selected-icon', getCurrentIcon())
})
Conclusion: Learning the Basics
This simple project demonstrates how HTML, CSS, and JavaScript can work together to create a responsive and interactive portfolio website. Aspiring developers should understand the fundamentals of these languages, as they form the foundation of web development.
By practicing and experimenting with different styles, colors, and layouts, you can gain valuable experience. Challenge yourself to add new sections or features to your portfolio site to further improve your skills. The more you practice, the more exciting and rewarding web development becomes. Keep learning and keep practicing – your journey as a web developer has just begun!