How could I turn this navbar I made using CSS into Hamburger menu for mobile ? It needs to be responsive. I first tried using bootstrap but I'd like it to use CSS
Then, you can assign a class to ul
and populate it as follows:
.list {
display: grid;
grid-auto-flow: column;
list-style-type: none;
column-gap: 20px;
padding: 0;
}
Here you're telling to <ul>
element that all the <li>
elements inside of it, should compose a grid of n columns as many <li>
elements and that you want 20px of space between each of them. The property column-gap
works only if you set display: grid
. The padding should always be 0 or the browser will add some padding by default. You don't want it so you specify 0.
Now, you can use a powerful combo to set the width of the list items by creating a class and assigning it to your <li>
elements:
.listItem {
width: min-content;
white-space: nowrap;
}
Here you're just telling to the list items that their width should be automatic, based on the words length. With white-space: nowrap
you're telling to the list items that you never want the text to start a new line after a space. For example, "GUIDES ET ASTUCES" will always be placed on a single line. At the same time you're also setting the width for each column of the grid created before.
Now, create a button and wrap it together with the logo in a new div:
<div >
<img src="images/GameStar-Blanc.png" alt="logo" >
<button >Menu</button>
</div>
Basically, this will be your mobile header with the logo on the left and the button on the right. The menu will be placed below.
Create a global CSS rule and tell the button you never want to display it:
.hamburger {
display: none;
}
Now for the mobile menu, you should change the appearance of the <nav>
container and all its child element that you want to change. From now on your code should be wrapped around a media query, place the media queries at the bottom of your CSS file or at least, below the rules defined before:
@media screen and (max-width: 800px) {
// CSS code
}
Create another CSS rule targeting all the devices with a max resolution of 800px:
@media screen and (max-width: 800px) {
.hamburger {
display: block;
}
}
In short, you just said: "The menu button should always be hidden, but when a device has a width from 0 to 800px, I want to display it.
Now create another rule inside the media query @media screen and (max-width: 800px)
and do the same you did for the header:
.mobileHeader {
width: 100%;
display: flex;
justify-content: space-between;
}
Basically you want that a certain width, the header is something like:
Now you should have two elements inside your <header>
, <div>
and <nav>
, let's create a rule and tell the header that you would like to display those elements one below the other:
.header {
flex-direction: column;
padding: 20px;
}
Basically it is just like grid-auto-flow: row
for grids.
Now do the same for the list, this time you want the opposite, you want that all the items will compose a grid with n rows and just one column:
.list {
grid-auto-flow: row;
list-style-type: none;
row-gap: 40px;
column-gap: 0;
justify-items: center;
}
With justify-items: center
you're instructing the list to center the list items. It works only with display: grid
, since you set display: grid
in a global rule, you don't need to write it again as long as you don't need to change it.
Now assign a class to your <nav>
and enter another rule in the media query:
.menu {
display: none;
}
Since your menu should be hidden when an user visits the website on mobile, it should be set on display: none
by default.
Now, set a rule to target only devices with a width of 801 px and more with (min-width: 801px)
:
@media screen and (min-width: 801px) {
.menu {
display: block !important;
}
}
No matter what, you always want the menu to be displayed for devices which have a resolution wider than 800px.
Now, if you shrink your window the mobile menu should be vanished and here you need a bit of JS to open and close it, I am not going into the details since your question is totally related to CSS and I will only confuse you by going deeper but you will find everything in the pen I made for you.
https://codepen.io/alienopolis/pen/NWapXWZ
Finally, I would recommend you to take this free tutorial which covers everything you need to know about responsive design with CSS:
https://www.freecodecamp.org/news/css-flexbox-and-grid-tutorial/
HTML
<header >
<div >
<img src="images/GameStar-Blanc.png" alt="logo" >
<button onclick={openMenu()} >Menu</button>
</div>
<nav >
<ul >
<li ><a href="#">A LA UNE </a></li>
<li><a href="#">L'ACTUALITE</a></li>
<li><a href="#">GUIDES ET ASTUCES</a></li>
<li><a href="#">PROCHAINEMENT</a></li>
</ul>
</nav>
</header>
CSS
body {
width: 90%;
height: 800px;
}
.header {
display: flex;
width: 100%;
justify-content: space-between;
background: #583760;
align-items: center;
padding: 20px 60px;
}
.logo {
color: white;
}
.list {
display: grid;
grid-auto-flow: column;
list-style-type: none;
column-gap: 40px;
}
.listItem {
width: min-content;
white-space: nowrap;
}
nav a {
color: white;
font-weight: bold;
text-decoration: none;
text-transform: uppercase;
}
nav a:hover {
color: black;
}
.hamburger {
display: none;
}
@media screen and (min-width: 801px) {
.menu {
display: block !important;
}
}
@media screen and (max-width: 800px) {
.header {
flex-direction: column;
padding: 20px;
}
.mobileHeader {
width: 100%;
display: flex;
justify-content: space-between;
}
.hamburger {
display: block;
}
.menu {
display: none;
}
.list {
grid-auto-flow: row;
list-style-type: none;
row-gap: 40px;
column-gap: 0;
justify-items: center;
}
}
JS
const menu = document.querySelector(".menu");
let open;
function openMenu() {
if (open) {
menu.style.display = "none";
open = false;
} else if (!open) {
menu.style.display = "block";
open = true;
}
}