Why are my hover styles applying to children elements? - css

I have read what MDN says about the child combinator:
The child combinator (>) is placed between two CSS selectors. It matches only those elements matched by the second selector that are the children of elements matched by the first. Elements matched by the second selector must be the immediate children of the elements matched by the first selector.
What I don't understand is why the other two <li> elements are red, too.
.list > li:hover{
color:red
}
<ul class="list">
<li>I should be red
<ul>
<li>Why I am red too?</li>
<li>Why I am red too?</li>
</ul>
</li>
</ul>

With .list > li you are also including all the children of the parent list (which includes the second ul)
One way of overriding that is by explicitly setting the properties of the second list:
https://jsfiddle.net/6yeh6ggL/4/:
.list li a:hover{
color:red
}
.list ul li a:hover{
color:black
}

Just to help clarify a little.
Your selector is finding the li item you want which is the first one (it is only finding that one). The reason all the li's turn red is because color is set to the first li which is inherited by its children and in the case above those li's are its children.

Related

Good practice on selecting a list menu

Considering this markup:
<div id="container">
<div id="mainmenu">
<ul>
<li> <h1>My Dashboard</h1></li><br>
<li> <h1>About</h1></li><br>
<li> <h1>Contact</h1></li><br>
<li> <h1>Setttings</h1></li><br>
<li> <h1>Log Out</h1></li><br>
</ul>
</div>
</div>
Selecting this way is a valid thing? I am having issues with some properties.
#container ul li{
display: inline-block;
}
#mainmenu ul li a{}
#mainmenu ul li a:hover{}
full sample:
https://jsfiddle.net/jhr1q1q4/
I'm somewhat unsure what you're asking...
Strictly speaking, the selectors you provided are valid and would select the <a> elements within your #mainmenu element.
But I would ask: is the ul li part of the selectors necessary? You could rewrite both of them as
#mainmenu a {}
#mainmenu a:hover {}
and they would work the same and require less parsing. If you wanted to only select <a> elements that are descendants of <li> elements, you could keep the li in your selector; however, the ul is not necessary -- it is implied your <li> elements will be children of a <ul> (assuming you're writing valid HTML).
Another note: <a> elements are inline, meaning they're meant to act at the text level. <h1> elements, on the other hand, are block-level elements, and thus do not belong inside <a> elements. In fact, you usually shouldn't have more than one <h1> on a page, let alone be using <h1>'s to mark up menu items. If you want your menu items to be big like headers, use your CSS rules to style them that way.
I am having issues with some properties.
What properties are causing trouble?

CSS multiple descendant selectors

I want to write a horizontal tag list as navigator. I read some css files online, and find the following (desendant?) selector style in a single css file:
nav ul li a { ...}
nav a {...}
nav ul li {...}
I know the for 2, nav a means select all the "a" elements under nav class. But what about 1. and 3.?
Does 3. means select all the "li" insinde "ul", and the "ul" should also inside "nav"? It seems to me that 1 and 2. will have similar effect. But I cannot find an answer online.
The first means that it will apply to all <a> elements inside a <li> which is inside <ul> which is within a <nav>. In other words, it will style code that looks like this:
<nav>
<ul>
<li>
<a>...</a>
</li>
</ul>
</nav>
The reason that selector 1 and selector 2 will apply to the same elements is because if you notice <nav><ul><li><a>...</a></li></ul></nav>, the <a> is both times inside the <nav><ul>...</ul></nav>. The first selector is just more restrictive than the second selector, but because everything inside a <ul> is always supposed to also be inside a <li> element, the selectors should always apply to the same elements.
The third selector will apply to <li> elements inside a <ul> which is inside a <nav>, just like you said. In other words:
<nav>
<ul>
<li>...</li>
</ul>
</nav>
Edit: As #Hughes suggested, something to note here is the concept of "specificity." When there are multiple rules that apply to the same object, there is often times a need to break ties. For instance, what happens if we have this code?
nav ul a { color: blue; }
nav ul li a { color: green; }
It's up to CSS to determine which font colour to apply to <nav><ul><li><a> ... </a></li></ul></nav>. In these cases, CSS chooses the rule which is more specific when describing which elements it applies to. In this example, the <a> would be coloured green, because the nav ul li a rule is more specific when describing the elements that the rule should apply to (just think of the English definition for the word "specific"). Thus while both selector 1 and selector 2 from the question should apply to the same objects, if they ever both provide the same CSS property, the value in selector 1 would be chosen over the value in selector 2.

Combined CSS declaration in wordpress

In WordPress, it uses li to declare the menu item, what is the difference between two CSS declaration #navigator > li and #navigator li?
Actually, this is not In WordPress, but is a CSS selector behavior:
The white space is a Descendant Selector that, by definition
matches only those elements matching the second selector for which there is an ancestor element matching the first selector. Descendant selectors are similar to child selectors, but they do not require that the relationship between matched elements be strictly parent-child.
In your case, #navigator li will match all li at any nested level inside #navigator.
Example:
<ul id="#navigator">
<li> <!-- this is selected -->
<div>
<ul>
<li> <!-- this is selected -->
On the other hand
The > is a Child Selector, that:
matches only those elements matched by the second selector that are direct children of elements matched by the first.
In your case, #navigator > li will match only li that are direct childs of #navigator.
Example:
<ul id="#navigator">
<li> <!-- only this is selected -->
<div>
<ul>
<li>
The difference between those 2 is that the > selector (#navigator > li) means the immediate child and the #navigator li means all the li that have as ancestor the #navigator.

:first-child targeting all child elements

I have a unordered list with id of "navigation" and a few child list-item elements.
I am trying to select just the first item with :first-child but it is applying the CSS I use with this to all other list items.
ul#navigation li:first-child{
background:#fff;
}
So, to reiterate: this is giving every list-item a white background. I just want to select the first element. What is going wrong?
According to the comments, your problem is that your markup looks like this:
<ul id="navigation">
<a href="http://google.com">
<li>Google</li>
</a>
</ul>
Note how every li will be a :first-child under this model. I would suggest you go with the more appropriate structure of nesting your anchor within your list item. If you want the anchor to fill up the list item, set its display to block:
<ul id="navigation">
<li>Google</li>
</ul>
With the accompanying CSS:
#navigation a { display: block }
Once you have those structural changes in place, your selector should target the first list item:
/* > to target only immediate list items */
#navigation > li:first-child {
background: red;
}

navigation bar list width

I am creating a navigation bar right now and I want the width of the main elements on the navigation to be auto, but sub elements to all be a fixed width. The way the list is made is as such:
<li>Main Element
<ul>
<li> Sub Element </li>
<li> Sub Element </li>
<li> Sub Element </li>
</ul>
</li>
This is repeated for each main menu item and its submenu items.
The issue I am having is I want to css for the sub elements to be 100px in width, but the main elements to be equal to the text size plus 10px of padding on both the left and right. It appears I can not change one without changing both, even after attempting to make classes to separate them. I have also tried editting ul li and li ul styles in my external style sheet. Thank you in advance for all help.
ul li affects all li's at any level under an ul. ul > li only affects the li's that are direct children of an ul. It's called a child combinator: http://www.w3.org/TR/css3-selectors/#child-combinators
You must use it if you are to make it happen without using classes (using classes would actually be the better way imo - http://www.jsfiddle.net/joplomacedo/xeWA4 )
The trick is applying the styles you want applied on the main menu items under ul > li and then override them at ul ul > li. Here's a fiddle - http://jsfiddle.net/joplomacedo/xeWA4/3/
EDIT:
You actually don't need to use the child combinator at all. Child combinators came to my mind
when I first read your question, and I kind of never questioned their use. So, ul li overridden by ul ul li works perfectly as well - and keeps it simpler.

Resources