CSS multiple descendant selectors - css

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.

Related

Why are my hover styles applying to children elements?

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.

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?

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.

How to get only the last ul of specific id on page via CSS :last-child property?

My page generates two ULs of the same ID and I would like to remove the last one via CSS (display: none). I was trying with :last-child property but no luck at all. I either made both of them disappear or none of them.
Example:
<div id="content">
<ul id="some-ul">
<li>...</li>
<li>...</li>
</ul>
<ul id="some-ul">
<li>...</li>
<li>...</li>
</ul>
</div>
I would like to apply display: none only for the last ul#some-ul inside my #content.
It could be done like so:
#content ul:last-child {
display:none;
}
Note that last-child is only supported in IE9+. As mentioned by #Jop, you should set a class on the last child element to get around this for older versions of IE.
jsFiddle here.
Also, remember that ID's should always be unique.
Completely generic way to do this, that relies on no classes or ID's
div ul:last-of-type li:last-child {
display:none;
}
So basically, the div is the parent item that contains the list items - it could have a class or ID if you want.
Within that, you have your ul tags - the last-of-type does the magic, finding the last ul within the parent div. You then simply use last child on the li.
Here's the fiddle:
http://jsfiddle.net/Kx8SN/

CSS Unordered List: Why Does One Technique Work But Another Doesn't Work?

I have a basic unordered list in HTML/CSS as follows...
<div class="floatleft">
<ul class="help">
<li>item</li>
<li>item</li>
<li>item</li>
</ul>
</div>
I'm trying to do some custom stuff (image bullets, margin, padding, etc.) Since I assigned a class to the list block, I thought I could make my CSS declarations like the first two lines below. But that doesn't work. When I do it like in the two lines below that, it works fine. I'm not understanding what the difference is.
.help ul { declarations } /* Doesn't work */
.help li { declarations } /* Doesn't work */
ul.help { declarations } /* Works! */
li.help { declarations } /* Works! */
Can anyone enlighten me? Thanks.
The "doesn't work" requires the <ul> to be a child (direct or non-direct) of any element of class help
So if the div was:
<div class="floatleft help">
It would work.
.help ul is targeting <ul> descendants of elements with the 'help' class:
Example: (won't work)
<div class="help">
<ul>
ul.help targets <ul> elements with the help class.
Example: (will work)
<ul class="help">
.help li should work as that is targeting <li> descendants of elements with the 'help' class, which is what you have.
Example: (will work)
<ul class="help>
<li>
li.help shouldn't work because that will target <li> elements with the 'help' class, which you don't have in your markup.
Example: (won't work)
<ul>
<li class="help">
Read up on how descendant selectors and the cascade (the 'C' in CSS) works.
The space character pretty much means "now let's look at the children".
So when you have .help ul you are saying "grab all things with a class of help" then "grab all ul children within those things".
However, "ul.help" says "grab all things that BOTH have a class of help and are a ul".
The problem is that the selector .help ul applies to a ul tag that is a child of an element with the class help. The corresponding markup for this would look something like this, where the div tag could be any element, and not necessarily the immediate parent of the ul tag.
<div class="help">
<ul>
....
</ul>
</div>
In your case, you have a ul tag with the class help, which is exactly what ul.help selects.
For a comprehensive reference on CSS selectors, see the W3C page.
To expand on Matt's answer:
.help ul Means "a ul element contained (however deeply nested) within an element with the class 'help'"
ul.help Means "a ul element with the class 'help'"
For reference
ul .help Means "an element with the class 'help' contained (however deeply nested) within an element with a ul element"
On the last line li.help shouldn't work either because you're addressing all li's with a class of 'help' of which you have none.
What 'works' might also depend on which element you're trying to apply the styles to. You might want to check some HTML reference guides as to what elements to apply your list settings to. Generally your overall bullet settings are done on the ul but some spacing is also applied to the li's in some browsers.

Resources