Search code examples
javascriptcssreactjsfrontend

Hamburger menu isn't sliding


I want make hamburger menu <HamburgerMenu className="Hamburger-Menu" id="HamMenu" style={styles}/> slide on clicking hamburger icon(checkbox) <Hamburger id="ham-icon"/> using #ham-icon input[type="checkbox"]:checked + .Hamburger-Menu in css but isn't working

Header.jsx:


import React, { useState, useEffect } from "react"
import Logo from "./icons/Logo.jsx"
import Hamburger from './icons/Hamburger.jsx'
import HamburgerMenu from './HamburgerMenu.jsx'

function Header(){
    const [headerHeight, setHeaderHeight] = useState()
    const [windowWidth, setWindowWidth] = useState(window.innerWidth)

    useEffect(() => {
            const HamMenu = document.getElementById("HamMenu")
            const Header = document.getElementById("top-bar")

            const HamMenuRect = HamMenu.getBoundingClientRect()
            const HeaderRect = Header.getBoundingClientRect()
            
            setHeaderHeight(HeaderRect.height)
            console.log(HeaderRect.height)
            
        }, []
    )
    
    const styles = {
        '--Header-Height' : headerHeight + 'px', 
        '--Window-Width+5' : windowWidth+5 + 'px',
    }

    return(
        <div className="Header" id="top-bar">

            <Logo fill='black' width='70px' height='70px'/>
        
            <div className="button-container">
                <button> Products </button>
                <button> Services </button>
                <button> Company </button>
                <button> Pricing </button>
            </div>
        
            <div>
                <Hamburger id="ham-icon"/>
                <HamburgerMenu className="Hamburger-Menu" id="HamMenu" style={styles}/>
            </div>

        </div>
    )
    
}

export default Header

Hamburger.jsx(checkbox):

import React from "react";
import styles from './Hamburger.module.css'

function Hamburger({...props}){
  return (
      <label className={styles.burger} {...props} htmlFor="burger">
        <input type="checkbox" id="burger"/>
        <span />
        <span />
        <span />
      </label>
  );
};

export default Hamburger;

HamburgerMenu.jsx:


import { useEffect } from "react"

function HamburgerMenu({HamburgerMenu, ...props}){
    
    return(
        <div className={HamburgerMenu} {...props}>
            <ul>
                <li>Portfolio</li>
                <li>Blog</li>
                <li>About</li>
                <li>Login</li>
                <li>Language: EN</li>
            </ul>
        </div>
    )
}

export default HamburgerMenu

Index.css:


*{
    padding: 0;
    margin: 0;
    font-family: Arial, Helvetica, sans-serif;
}

body{
    overflow-x: hidden;
}

/* Header.jsx */
.Header{
    display: flex;
    justify-content: space-between;
    align-items: center;
    
    background-color: rgb(0, 186, 114);
    width: 100%;
    box-sizing: border-box;
    padding: 8px 50px;
}

.button-container{
    display: flex;
    justify-content: center;
    gap: 50px;

    width: 100%;
}

.button-container button{
    padding: 8px 12px;
    font-size: 22px;
    border: none;
    border-radius: 5px;
    background-color: rgba(255, 255, 255, 0);
    color: white;
    cursor: pointer;
}

.button-container button:hover{
    background-color: hsla(0, 0%, 0%, 0.3);
}

.button-container button:active{
    background-color: hsla(0, 0%, 0%, 0.2);
}


.Hamburger-Menu{
    position: absolute;
    background-color: hsl(0, 0%, 89%);
    top: var(--Header-Height);    /* from Header.jsx */
    left: 100vw;
    
    border: 5px solid hsl(0, 0%, 80%);
    border-radius: 5px;
    margin-top: 10px;
    padding: 40px 20px;
    transition: all 0.5s ease-in;
}

.Hamburger-Menu ul{
    list-style-type: none;
    white-space: nowrap;
}

#ham-icon input[type="checkbox"]:checked + .Hamburger-Menu{
    right: 0vw;
}

Solution

  • Your checkbox is not a sibling of the .Hamburger-Menu element (because it is contained inside the label element), so the adjacent or general sibling selector won't work in this scenario.

    Try instead :has():

    .Header:has(#burger:checked) .Hamburger-Menu {
       ...
    }
    

    or if you want to still use the adjacent sibling selector

    label:has(#burger:checked) + .Hamburger-Menu {
       ...
    }