Change CSS content on checked checkbox

39 views Asked by At

I have this header with a menu inside. I can open the menu when the checkbox is checked but I can't figure out how to solve that I want the CSS content to change from a hamburger menu to a close icon. For that I'm using ASCII.

So this code is wrong and I know it's the wrong selector, but I don't know how to fix it. I guess there is something that needs to change in the structure. Any help is appreciated!

.main-nav {
  position: relative;
  nav {
    a {
      display: block;
      border-bottom: 0.5px solid #000;
      padding: 1rem;
      text-decoration: none;
      color: #000;
      &:hover {
        background-color: #F7CC00;
      }
    }
  }
  label {
    cursor: pointer;
    font-size: 1.5rem;
    padding-right: 1rem;
    &:before {
      content: "\2630";
    }
  }
  #toggle {
    display: none;
    &:checked {
      +.menu {
        display: block;
      }
    }
  }
  .menu {
    display: none;
    position: absolute;
    top: 62px;
    right: 0;
    background-color: #fff;
    width: 100vw;
  }
}


/* This is where it goes wrong */

#toggle:checked~label:before {
  content: "\2716";
}
<header>
  <div class="container">
    <div class="logo">
      <a href="/"><img src="https://via.placeholder.com/40" alt="logo"></a>
    </div>
    
    <div class="main-nav">
      <label for="toggle"></label>
      <input type="checkbox" id="toggle" />
      
      <nav class="menu">
        <a href="#one" id="link1">Link</a>
        <a href="#two" id="link2">Link</a>
        <a href="#three" id="link3">Link</a>
        <a href="#four" id="link4">Link</a>
        <a href="#five" id="link5">Link</a>
        <a href="#six" id="link6">Link</a>
        <a href="#seven" id="link7">Link</a>
      </nav>
    </div>
  </div>
</header>

2

There are 2 answers

0
isherwood On BEST ANSWER

Just reverse the order of the checkbox and label so your sibling selector works. Note that I also updated the selector for the menu element.

.main-nav {
  position: relative;
  nav {
    a {
      display: block;
      border-bottom: 0.5px solid #000;
      padding: 1rem;
      text-decoration: none;
      color: #000;
      &:hover {
        background-color: #F7CC00;
      }
    }
  }
  label {
    cursor: pointer;
    font-size: 1.5rem;
    padding-right: 1rem;
    &::before {
      content: "\2630";
    }
  }
  #toggle {
    display: none;
    &:checked {
      ~.menu {
        display: block;
      }
    }
  }
  .menu {
    display: none;
    position: absolute;
    top: 62px;
    right: 0;
    background-color: #fff;
    width: 100vw;
  }
}


/* This is where it goes wrong */

#toggle:checked~label::before {
  content: "\2716";
}
<header>
  <div class="container">
    <div class="logo">
      <a href="/"><img src="https://via.placeholder.com/40" alt="logo"></a>
    </div>
    
    <div class="main-nav">
      <input type="checkbox" id="toggle" />
      <label for="toggle"></label>
      
      <nav class="menu">
        <a href="#one" id="link1">Link</a>
        <a href="#two" id="link2">Link</a>
        <a href="#three" id="link3">Link</a>
        <a href="#four" id="link4">Link</a>
        <a href="#five" id="link5">Link</a>
        <a href="#six" id="link6">Link</a>
        <a href="#seven" id="link7">Link</a>
      </nav>
    </div>
  </div>
</header>

1
Mehdi On

Just want to propose another solution and that allows you to keep your order in your HTML and this using the very useful :has css selector.

.main-nav {
  position: relative;
  nav {
    a {
      display: block;
      border-bottom: 0.5px solid #000;
      padding: 1rem;
      text-decoration: none;
      color: #000;
      &:hover {
        background-color: #F7CC00;
      }
    }
  }
  label {
    cursor: pointer;
    font-size: 1.5rem;
    padding-right: 1rem;
    &:before {
      content: "\2630";
    }
  }
  #toggle {
    display: none;
    &:checked {
      +.menu {
        display: block;
      }
    }
  }
  .menu {
    display: none;
    position: absolute;
    top: 62px;
    right: 0;
    background-color: #fff;
    width: 100vw;
  }
}


/* This is where it goes wrong */

.main-nav:has(#toggle:checked) label:before {
  content: "\2716";
}
    <header>
        <div class="container">
          <div class="logo">
            <a href="/"><img src="https://via.placeholder.com/40" alt="logo"></a>
          </div>
          
          <div class="main-nav">
            <label for="toggle"></label>
            <input type="checkbox" id="toggle" />
            
            <nav class="menu">
              <a href="#one" id="link1">Link</a>
              <a href="#two" id="link2">Link</a>
              <a href="#three" id="link3">Link</a>
              <a href="#four" id="link4">Link</a>
              <a href="#five" id="link5">Link</a>
              <a href="#six" id="link6">Link</a>
              <a href="#seven" id="link7">Link</a>
            </nav>
          </div>
        </div>
      </header>

using the very useful :has css selector