With the following HTML, does my CSS display as I have stipulated below?
HTML:
<ul>
<li>1</li>
<li>2</li>
<ul>
<li>3</li>
</ul>
<li>4</li>
</ul>
CSS:
ul + li /* 1 and 3 */
ul > li /* 1, 2 and 3 */
ul ~ li /* 1, 2, 3 and 4 */
Equally important, where did I go wrong?
There's quite a lot going on here so I'm going to try to break it down for you one by one. This will be long, but bear with me.
Let's make the indentation a little more consistent so we can see what's going on with the HTML:
<ul>
<li>1</li>
<li>2</li>
<ul>
<li>3</li>
</ul>
<li>4</li>
</ul>
When you open the first ul, and start adding lis to it, those li elements are children of the first ul. They appear inside it, or more precisely, between its start tag <ul> and its end tag </ul>.
By the time you open the second ul, you've already closed the second li with its own end tag. The second ul is not a child of that li because it appears after its end tag </li>. So the second ul — the inner one if you will — is a sibling of the second li, and therefore a child of the first (outer) ul. The fourth li, similarly, is a sibling of the second ul, and also a child of the first ul.
The third li is a child of the second (inner) ul. It is neither a child nor a sibling of any of the other elements. It is a grandchild of the first (outer) ul, but it doesn't matter for the sake of answering your question.
If the markup appears visually similar to a family tree, it should make sense to you. In a family tree, children appear under a parent. (Only, in a family tree, there are typically two parents; in HTML, every child has only one parent.) Children that are siblings of one another appear side by side, connected to the same parent. This markup is structured similarly, except the children are listed top to bottom instead of left to right. But they're still "side by side", logically speaking.
Recall what the following selectors do:
ul + li matches a li that's a sibling appearing immediately after a ul.
ul > li matches a li that's a child of a ul.
ul ~ li matches a li that comes after a ul as a sibling, but unlike with + it doesn't have to appear immediately after, as long as they're between the same set of opening and closing tags (this is called "having the same parent element"). Any ul + li is automatically also a ul ~ li.
Here's the markup again with some annotations:
<ul>
<li>1</li> <!-- ul > li -->
<li>2</li> <!-- ul > li -->
<ul>
<li>3</li> <!-- ul > li -->
</ul>
<li>4</li> <!-- ul > li, ul + li, ul ~ li -->
</ul>
Indeed, none of the first three li elements are siblings of any ul. Only the very last one is, and it matches both sibling selectors.
So how do you make the inner ul a child of the second li? You do this by moving the </li> so that it appears after the </ul> like so:
<ul>
<li>1</li> <!-- ul > li -->
<li>2 <!-- ul > li -->
<ul>
<li>3</li> <!-- ul > li -->
</ul>
</li>
<li>4</li> <!-- ul > li, ul + li, ul ~ li -->
</ul>
Critically, the inner ul will now match a different selector: li > ul. Additionally, your markup will now validate, as you are never allowed to have a ul as a child of another ul in the first place.
Finally, some of your stipulations require more complex selectors as they match pretty specifically. I'll walk you through each one:
To match 1 and 3, use ul > li:first-child. This is because 1 and 3 are the first children of their respective parent uls. You can usually tell if an element is the first child of another because its start tag is the first thing that appears after the parent's start tag, ignoring any text or whitespace.
To match 1, 2 and 3, use ul > li:first-child, ul > li:nth-child(2). The additional :nth-child(2) targets item 2 specifically.
To match 1, 2, 3 and 4, using ul > li is enough, since you're just matching them all. You can probably get away with just li if you only have ul in your markup, but this is unlikely to be the case so I'm erring on the side of being more specific than necessary, rather than not being specific enough.
It's a lot to take in, so let me know if any of this is confusing or overwhelming and I'll try to address your concerns.
Related
How can i select the"Automobiles" text and the unordered list right after that.
Without changing the html code.
I tried selecting it with- nav ul li
also tried with- nav:first-child ul:first-child
<nav>
<ul>
<li>Automobiles
<ul>
<li>812Superfast</li>
<li>GTC4Lusso</li>
<li>488GTB</li>
<li>488Spider</li>
</ul>
</li>
</ul>
Just separately define them them:
nav ul li, nav ul li ul {
...
}
Just for information: If you are able to modify the html code, you should use classes within the elements.
I have the following HTML:
<ol>
<li>A numbered bullet</li>
<ul>
<li>An un-numbered bullet</li>
<ul>
</ol>
But it shows like this:
1. A numbered bullet
1. An un-numbered bullet
When I do an "inspect element", it shows the ul li styles crossed out and overriden by ol li. Why?
it shows the ul li styles crossed out and overriden by ol li.
Since the ul is inside the ol, the li is a descendant of both the list elements, so both selectors will apply.
The two selectors have equal specificity, so they are applied in order.
You have defined the ol li styles after the ul li styles in the stylesheet, so they override the earlier ones.
You could use a more specific selector to target the deeper list:
ol ul li { }
Or you could use a child combinator instead of a descendant combinator:
ol > li {}
ul > li {}
(Note that it is invalid HTML to have a ul as a child of a ol. The nested list should appear within a li.)
If you put your <ul> inside the <li> it will work:
<ol>
<li>First level element, ordered
<ul>
<li>Unordered list</li>
</ul>
</li>
</ol>
http://jsfiddle.net/6tGvA/
In your version, the unordered list isn't nested in the li item for proper indentation, thus the ul is ignored.
If I wanted to only insert a pseudo-element after a link only if the link is followed by another element say ul. How could I do this?
Example:
<ul>
<li>
blah<!-- insert -> here with CSS -->
<ul>
<li>More stuff</li>
</ul>
</li>
<li>
blah 2<!--Do nothing here-->
</li>
</ul>
CSS I wish could happen:
ul li a:after if(next:ul) {
content:"->";
}
I'm not trying to use JavaScript/jQuery. And I realize if conditions are not apart of css.
Is there a way to do this?
In general it is not possible to select elements based on their next sibling.
In your specific case, you can use ul li a:not(:last-child)::after, because it happens that your anchors that are not followed by an <ul> element are also the last child element.
You can simply use:
ul + li a:after { /* ...css code... */ }
Basically this means:
Match an a element contained in a li element that is immediately preceded by an ul element.
The + operator in CSS is called adjacent sibling combinator.
If you want to filter any element in the hierarchy/list of elements you can use the below approach.
ul li a:not(:nth-last-child(N))::after
Here N is any positive integer traversing from the end; 1 means the last element 2 means second last and so on. Instead of ul li use any selector here
For more information visit nth-last-child().
I am trying to make a drop down list by using nested Un ordered lists.
My case is i have an unordered list, which is having another unordered list inside of its li element. I had written hover for the first level li elements by using the child selector. My problem is while hovering the first level li element, the css for its hovering process is also get applied to its child li element. My question is why does the child selector selecting its descendants in my case..? and what should i do to avoid this in future.?
DEMO - Fiddle
Here is the solution below:
My question is why does the child selector selecting its descendants in my case..?
Because you have defined one part of the CSS by adding #ULHeaderMenuWrapperMenuCollection > li:hover
what should i do to avoid this in future.?
You have to protect the inheritance by adding #ULHeaderMenuWrapperMenuCollection > li:hover div ul li to your CSS. Here is the Working Solution.
#ULHeaderMenuWrapperMenuCollection > li:hover div ul li
{
color:black;
}
#ULHeaderMenuWrapperMenuCollection > li:hover div ul li:hover
{
color:orange;
}
Hope this helps.
Updated to fit to your original code
When you mouse is hover your sublist, it's still hover the main one.
I suggest you to put your <li> text in a <span> or a <a>, which makes your css simplest :
HTML
<ul id="ULHeaderMenuWrapperMenuCollection">
<li>
<span>Products</span>
<div id="DivProductsMenu">
<div id="DivProductsMenuUpper">
<ul>
<li><span>CIMS</span></li>
<li><span>VPRO</span></li>
<li><span>BIRIS</span></li>
</ul>
</div>
<div id="DivProductsMenuLower">
<ul>
<li><span>PATRON</span></li>
<li><span>DEAL</span></li>
<li><span>MEDIX</span></li>
</ul>
</div>
</div>
</li>
<li>
<span>Contact Us</span>
</li>
</ul>
CSS
#ULHeaderMenuWrapperMenuCollection li > span:hover {
color:orange;
}
JsFiddle
<ul>
<li>test</li>
<li>
<ul>
<li>another</li>
</ul>
</li>
</ul>
I only want to style the nested ul tag... is this possible? I know I can just give the ul an id or class, but I was wondering if there was another way (I think:first-child, last-child, nth-child, may be at play here?)?
ul ul that means any ul that's a child of another ul, no matter how many levels down it is.
If you want to target THAT level, specifically, you could go with ul > li > ul which would target uls that are direct children of lis that are direct children of uls.
Tidy.exe do not recognise the format
UL
LI
/LI
UL
/UL
/UL