input: checked is not applying properties

3

I'm developing a responsive menu using css3 (I can not use JS), and I'm having a problem that's keeping me from moving forward, the problem is this:

input:checked ~ nav {
  display: none;
}

But the property is not applied to the nav when the input is marked.

Example of problem code in a code:

* {
  margin: 0;
  padding: 0;
  list-style: none;
}

input:checked ~ nav {
  display: none;
}
<body>
  <header>
    <div class="menu">
      <input type="checkbox" />
    </div>
    <nav>
      <ul>
        <li><a href="#">INICIO</a></li>
        <li><a href="#">SOBRE</a></li>
        <li><a href="#">CONTATOS</a></li>
        <li><a href="#">FALE CONOSCO</a></li>
        <li><a href="#">PROJETOS</a></li>
      </ul>
    </nav>
  </header>
  
</body>
    
asked by anonymous 17.11.2016 / 22:54

1 answer

5

The problem is that the ~ selector refers to an element that is preceded by another within the same "parent" of the file tree structure, not the case of your HTML.

From W3C documentation :

  

8.3.2. General sibling combinator

     

The general sibling combinator is made of the "tilde" (U + 007E, ~) character that separates two sequences of simple selectors. The elements represented by the two sequences share the same parent in the document tree and the element represented by the first sequence precedes (not necessarily immediately) the element represented by the second one. p>

(emphasis added)

That in summary is this:

  

The "generic sibling" combiner is the "tilde" ( ~ ), which separates two simple selector sequences. The elements have a parent in common in the document tree, and the first of the elements precedes the second, not necessarily immediately.

In your case, the "father" of the elements is different, only the "grandfather" is the same.

There are many ways to work around, the best depends on the overall code. The important thing is to understand how CSS selectors work.


Solution examples:

A solution would be for nav within div :

* {
  margin: 0;
  padding: 0;
  list-style: none;
}

input:checked ~ nav {
  display: none;
}
<body>
  <header>
    <div class="menu">
      <input type="checkbox" />
      <nav>
        <ul>
          <li><a href="#">INICIO</a></li>
          <li><a href="#">SOBRE</a></li>
          <li><a href="#">CONTATOS</a></li>
          <li><a href="#">FALE CONOSCO</a></li>
          <li><a href="#">PROJETOS</a></li>
        </ul>
      </nav>
    </div>
  </header>
</body>

Another would be to take input of div :

* {
  margin: 0;
  padding: 0;
  list-style: none;
}

input:checked ~ nav {
  display: none;
}
<body>
  <header>
    <input type="checkbox" />
    <nav>
      <ul>
        <li><a href="#">INICIO</a></li>
        <li><a href="#">SOBRE</a></li>
        <li><a href="#">CONTATOS</a></li>
        <li><a href="#">FALE CONOSCO</a></li>
        <li><a href="#">PROJETOS</a></li>
      </ul>
    </nav>
  </header>
</body>


But if you really need an element inside the div:

You can use a label as a "checkbox" remote control:

* {
  margin: 0;
  padding: 0;
  list-style: none;
}

#toggle,
input:checked ~ nav {
  display: none;
}
<body>
  <header>
    <div class="menu">
      <label for="toggle">[clique aqui]</label>
    </div>
    <input id="toggle" type="checkbox" />
    <nav>
      <ul>
        <li><a href="#">INICIO</a></li>
        <li><a href="#">SOBRE</a></li>
        <li><a href="#">CONTATOS</a></li>
        <li><a href="#">FALE CONOSCO</a></li>
        <li><a href="#">PROJETOS</a></li>
      </ul>
    </nav>
  </header>
  
</body>
    
17.11.2016 / 23:05