tdammon
tdammon

Reputation: 589

HTML why is my nested class a sibling and not a child

I'm sure there are similar questions out there but I haven't been able to find a conclusive answer. I have an HTML script with nested divs:

<ul id="navbar">
  <li><a href='#' class='dropdown'>Rules</a>
    <div class='rules'>
      <ul>
        <li>Rules Explanation Here</li>
      </ul>
    </div>
  </li>
</ul>

I believe that the div class 'rules' is a child of the class 'dropdown'. However when I was working on my css file, I couldn't get a hovering action on the dropdown class to effect my rules class unless I used the ~ connector.

This works in my CSS file:

.dropdown:hover ~ .rules{
    opacity: 1;
}

But this does not work:

.dropdown:hover .rules{
    opacity: 1;
}

As I understand it the ~ should only work if the classes are siblings which I do not believe they are.

Could someone explain why these classes are siblings here or link me to an easy to understand explaination.

Upvotes: 0

Views: 82

Answers (5)

Victoria Ruiz
Victoria Ruiz

Reputation: 5013

Here's a fully indented version of your code, which I think will help you visualize the answer better:

<ul id="navbar">
  <li>
    <a href='#' class='dropdown'>Rules</a>
    <div class='rules'>
      <ul>
        <li>Rules Explanation Here</li>
        <li>Second list item</li>
      </ul>
    </div>
  </li>
</ul>

First of all, let's explain the difference between the concepts:

  • parents and children are in different levels. The li is a child of the ul. ul is the parent.
  • siblings are children of the same parent, and are always at the same level. The innermost ul has 2 children li (in my example, not yours). And those children li are siblings.

So what happens with .dropdown and .rules? They are both children of the same li element. Notice that the a.dropdown is opened and closed before .rules starts. So they are children of the same parent, and as in real life, that makes them siblings.

Upvotes: 2

Ashraful Alam
Ashraful Alam

Reputation: 361

You can try this.

ul#navbar {
  list-style: none;
  background-color: lightblue;
  margin: 0;
  padding: 0;
  display: inline-block;
}
ul#navbar li {
  position: relative;
  float: left;
}
ul#navbar li a {
  display: inline-block;
  padding: 10px 20px;
  text-decoration: none;
  text-align: center;
  color: #fff;
}
div.rules {
  display: none;
  min-width: 200px;
  position: absolute;
  left: 0;
  top: 102%;
  background: lightblue;
  
}
div.rules ul {
  margin: 0;
  padding: 0;
  list-style: none;
}
div.rules li {
  float: none;
}
div.rules ul li a {
  padding: 10px;
  text-align: center;
  color: #fff;
}
.dropdown:hover > .rules {
  display: block;
}
<ul id="navbar">
  <li class='dropdown'><a href='#' >Rules</a>
    <div class='rules'>
      <ul>
        <li><a href="#" >Rules Explanation Here</a></li>
      </ul>
    </div>
  </li>
</ul>

Upvotes: 0

Victoria Le
Victoria Le

Reputation: 940

.parent{
  padding: 20px;
  background:tomato
  }
.dropdown{
  background: yellow
 }
 .rules{
 padding: 15px;
 background: green
 }
 .grandchildren{
 background: blue
 }
  <ul id="navbar">
      <li class="parent">
        <a href='#' class='dropdown'>Dropdown - children 1</a>
        <div class='rules'>
          Rules - Children 2
          <ul class="grandchildren">
            <li>Rules Explanation Here</li>
          </ul>
        </div>
      </li>
    </ul>

It is a sibling combinator case where the logic takes place within the same parent element, both .dropdown and .rules are children of li which makes them siblings. General sibling combinator doesn't need to immediately succeed the first element but can appear anywhere after. For more info, check out >> https://css-tricks.com/child-and-sibling-selectors/

Upvotes: 0

dippas
dippas

Reputation: 60563

Its correct, because .rules is child of the li but not the a.dropdown that you have as well as child of the li, therefore 2 children make them siblings

Snippet with .rules as sibling

.dropdown+.rules {
  border: red solid/* only affect the first sibling */
}

.dropdown~.rules {
  background: yellow/* afects all siblings */
}
<ul id="navbar">
  <li><a href='#' class='dropdown'>Rules</a>
    <div class='rules'>
      <ul>
        <li>Rules Explanation Here</li>
      </ul>
    </div>
    <div class='rules'>
      <ul>
        <li>Rules Explanation Here</li>
      </ul>
    </div>
  </li>
</ul>

Snippet with .rules as child

.dropdown .rules {
  border: red solid;
  background: yellow
}
<ul id="navbar">
  <li><a href='#' class='dropdown'>Rules
    <div class='rules'>
      <ul>
        <li>Rules Explanation Here</li>
      </ul>
    </div>
    </a>
  </li>
</ul>

Upvotes: 1

Lazar Nikolic
Lazar Nikolic

Reputation: 4394

It is because your class .dropdown is a clas of a tag and inside a tag you only have text "Rules". Element that has class .rules is nested inside li element not a. To achieve what you want, do this

<li class='dropdown'>
  <a href='#'>Rules</a>
    <div class='rules'>
      <ul>
        <li>Rules Explanation Here</li>
      </ul>
    </div>
</li>

With css that you wrote without ~ sign.

Upvotes: 0

Related Questions