What is the difference between ul > li > a {...} and ul li a {...} in CSS?
Which one is more efficient and why?
">" is the child selector
"" is the descendant selector
The difference is that a descendant can be a child of the element, or a child of a child of the element or a child of a child of a child ad inifinitum.
A child element is simply one that is directly contained within the parent element:
<foo> <!-- parent -->
<bar> <!-- child of foo, descendant of foo -->
<baz> <!-- descendant of foo -->
</baz>
</bar>
</foo>
for this example, foo * would match <bar> and <baz>, whereas foo > * would only match <bar>.
As for your second question:
Which one is more efficient and why?
I'm not actually going to answer this question as it's completely irrelevant to development. CSS rendering engines are so fast that there is almost never* a reason to optimize CSS selectors beyond making them as short as possible.
Instead of worrying about micro-optimizations, focus on writing selectors that make sense for the case at hand. I often use > selectors when styling nested lists, because it's important to distinguish which level of the list is being styled.
* if it genuinely is an issue in rendering the page, you've probably got too many elements on the page, or too much CSS. Then you'll have to run some tests to see what the actual issue is.
ul>li selects all li that are a direct child of ul whereas ul li selects all li that are anywhere within (descending as deep as you like) a ul
For HTML:
<ul>
<li><span><a href='#'>Something</a></span></li>
<li><a href='#'>or Other</a></li>
</ul>
And CSS:
li a{ color: green; }
li>a{ color: red; }
The colour of Something will remain green but or Other will be red
Part 2, you should write the rule to be appropriate to the situation, I think the speed difference would be incredibly small, and probably overshadowed by the extra characters involved in writing more code, and definitely overshadowed by the time taken by the developer to think about it.
However, as a rule of thumb, the more specific you are with your rules, the faster the CSS engines can locate the DOM elements you want to apply it to, so I expect li>a is faster than li a as the DOM search can be cut short earlier. It also means that nested anchors are not styled with that rule, is that what you want? <~~ much more pertinent question.
ul > li > a selects only the direct children. In this case only the first level <a> of the first level <li> inside the <ul> will be selected.
ul li a on the other hand will select ALL <a>-s in ALL <li>-s in the unordered list
Example of ul > li
ul > li.bg {
background: red;
}
<ul>
<li class="bg">affected</li>
<li class="bg">affected</li>
<li>
<ol>
<li class="bg">NOT affected</li>
<li class="bg">NOT affected</li>
</ol>
</li>
</ul>
if you'd be using ul li - ALL of the li-s would be affected
UPDATE The order of more to less efficient CSS selectors goes thus:
ID, e.g.#header
Class, e.g. .promo
Type, e.g. div
Adjacent sibling, e.g. h2 + p
Child, e.g. li > ul
Descendant, e.g. ul a
Universal, i.e. *
Attribute, e.g. [type="text"]
Pseudo-classes/-elements, e.g. a:hover
So your better bet is to use the children selector instead of just descendant. However the difference on a regular page (without tens of thousands elements to go through) might be absolutely negligible.
1) for example HTML code:
<ul>
<li>
firstlink
<span><a href="#">second link</a>
</li>
</ul>
and css rules:
1) ul li a {color:red;}
2) ul > li > a {color:blue;}
">" - symbol mean that that will be searching only child selector (parentTag > childTag)
so first css rule will apply to all links (first and second)
and second rule will apply anly to first link
2) As for efficiency - I think second will be more fast - as in case with JavaScript selectors. This rule read from right to left, this mean that when rule will parse by browser, it get all links on page:
- in first case it will find all parent elements for each link on page and filter all links where exist parent tags "ul" and "li"
- in second case it will check only parent node of link if it is "li" tag then -> check if parent tag of "li" is "ul"
some thing like this.
Hope I describe all properly for you
Here > a to specifiy the color for root of li.active.menu-item
#primary-menu > li.active.menu-item > a
#primary-menu>li.active.menu-item>a {
color: #c19b66;
}
<ul id="primary-menu">
<li class="active menu-item"><a>Coffee</a>
<ul id="sub-menu">
<li class="active menu-item"><a>aaa</a></li>
<li class="menu-item"><a>bbb</a></li>
<li class="menu-item"><a>ccc</a></li>
</ul>
</li>
<li class="menu-item"><a>Tea</a></li>
<li class="menu-item"><a>Coca Cola</a></li>
</ul>
to answer to your second question - performance IS affected - if you are using those selectors with a single (no nested) ul:
<ul>
<li>jjj</li>
<li>jjj</li>
<li>jjj</li>
</ul>
the child selector ul > li is more performant than ul li because it is more specific. the browser traverse the dom "right to left", so when it finds a li it then looks for a any ul as a parent in the case of a child selector, while it has to traverse the whole dom tree to find any ul ancestors in case of the descendant selector
Related
I have defined two <ul> classes, px_p and px_s. Now I want to style all <li> elements that are contained within either <ul class="px_p"> or <ul class="px_s"> elements.
I had thought that ul.px_p, ul.px_s li {} would work, but no dice. I tried ul.px_p li, ul.px_s li {} as well.
The issue is that the <li> styling is
ul.px_p, ul.px_s li {
margin: 0.1em;
}
and .1em is being applied to the whole <ul> element, as well as the nested <li> elements. I just want the <li> elements, as the <ul> has a much larger bottom margin to graphically separate it from the following elements. The difference between px_p and px_s is _p is Primary, and has a bullet, while _s is secondary and has no bullet, it just indents more.
The selector should be like this:
ul.px_p > li,
ul.px_s > li {
...
}
Using the > selector will only match li elements whose parent elements are ul.px_p or ul.px_s.
This is important, given that ul.px_p li will match any descendednt li element ul.px_s. This will include nested elements which the style should not apply to.
As an side note, sometimes when working in browsers, a cached version of CSS is used and changes you have made may not be reflected. Force a full refresh of the browser page which should reload the full content using CTRL+F5.
If I have a list:
<ul>
<li>item</li>
<li class="selected">item</li>
<li>item</li>
<li>item</li>
</ul>
Is it possible to select the 3rd and 4th items in this list via CSS? And more generally, all items that come after/before the .selected item?
To select the succeeding elements, you would use the general sibling combinator, ~.
Despite not being able to select the previous sibling elements, you could solve this by styling all the elements to begin with, and then overwriting the styling by selecting the succeeding elements.
EXAMPLE HERE
This will set the color of all the elements (except .selected) to red. It will then overwrite that styling and make the succeeding elements blue.
ul li:not(.selected) {
color:red;
}
ul .selected ~ li {
color:blue;
}
Since :not() isn't supported in IE8, you could also use the following:
EXAMPLE HERE
ul li {
color:red;
}
.selected {
color:black;
}
ul .selected ~ li {
color:blue;
}
There is a selector that matches elements preceded by another and this selector is a tilde ~.
So, you can simply match all elements after .selected using:
.selected ~ LI
JSFiddle example.
For futher details, visit spec.
I'm trying to apply a style to ONLY the very first child of an element. I'm using :first-child in the css to achieve this, but it looks like it's not the behaviour I'm looking for.
Take the following markup as example:
<ul class="myUl">
<ul class="mySubUl">
<li>foo0</li>
<li>foo1</li>
</ul>
<ul class="mySubUl">
<li>foo2</li>
<li>foo3</li>
</ul>
</ul>
======================
<ul class="myUl">
<li>foo0</li>
<li>foo1</li>
<ul class="mySubUl">
<li>foo2</li>
<li>foo3</li>
</ul>
</ul>
and this simple CSS:
ul.myUl li:first-child {
color: red;
}
Live fiddle: http://jsfiddle.net/bsSDh/1/
This applies not only to the first child of the ul.myUl elements, but also to the first child of ul.subUl. I would have expected this behaviour if the CSS selector was ul li:first-child (which works), but since I'm adding a class to the selector I'm expecting to apply that style only to the very first child.
Why does the style applies not only to the first child? Am I missing something about first-child specs or using the selector in the wrong way?
I think you need an additional child selector element like this:
ul.myUl > li:first-child {
color: red;
}
Example Fiddle
Your selector selects any <li> below ul.myUL, that is a first child. As this references only to the immediate parent and not any other ancestor, all those other <li> match as well.
EDIT
After your comment, I assume, that you will need a somehow complexer selector like this:
ul.myUl > li:first-child,
ul.myUl > ul:first-child > li:first-child {
color: red;
}
The selector
ul.myUl li:first-child
selects any li:first-child below any ul.myUl (i.e. first child of any parent inside the ul). Instead you might want to select a direct child via
ul.myUl > li:first-child
or even
ul.myUl > ul.subUl:first-child > li:first-child
Pay attention to the differences between the Child Combinator (a direct child) and the Descendant Combinator (any element contained).
You should use this two selectors to achieve the result wanted on the two known cases:
ul.myUl > ul:first-child > li:first-child {
color: red;
}
ul.myUl > li:first-child {
color: red;
}
Running Demo
I have a simple menu styled with css.
<ul>
<li> 1 </li>
<li> 2 </li>
<li> 3 </li>
<li> 4 </li>
</ul>
Is it possible to apply specific style to li element, containing a with active class.
I've tryed something like this:
#container > ul > li a.active < li {
custom: style;
}
Not possible with CSS. Though this can be achieved with scripting.
Similar question here.
Apply CSS styles to an element depending on its child elements
No, selectors can't match in reverse. In such circumstances the best approach is to simplify the matter.
A elements can be styled as block level elements, so simply push down whatever styles you had on the parent LI to the A elements. You already have your specific selector a.active, that should be distinct enough that you can style them appropriately.
#container ul li a.active{ yourstyle:styleproperties;}
or I think you may want to do like this
#container ul li a:active{ yourstyle:styleproperties;}
if you want dynamically add class to element you can use javascript and jquery
http://api.jquery.com/addClass/
$("#container ul li a").addClass("active");
and for parent(this class will be added for li element which is parent to a.active element)
$('#container ul li a.active').parent().addClass("active");
there is already similar topic Target outer div based on class of inner a
Try this:
ul li a.active{ color:green;}
http://jsfiddle.net/Vloxxity/VZgQx/
Edit:
i've read your comment,
this is only possible if you mark the li with a active class.
Well, I finally decided to totally drop IE6. It's great. First big benefit which comes with this decision is child selectors. So I started to use them for my nested drop-down menus for the first time and expected it to be a breeze. But... here's the code:
<style>
body {
color:#000;
}
ul.top > li {
color:red;
}
<ul class="top">
<li>top li</li>
<li>
<ul class="sub">
<li>sub li</li>
<li>sub li</li>
</ul>
</li>
</ul>
What I expected here, that only immediate children of .top unordered list are colored red and all the rest are black. Isn't it a logical thing to expect? But they all actually get red...
try
ul.top > li {
color:red;
}
ul.sub > li {
color:black;
}
??
Tim gave you the solution. The explanation for this behaviour is that though color: red; is only applied to the top-level lis, the color is inherited by their descendants. Check CSS Inheritance at Dorward Online for an in-depth explanation.
Well you see the red color is applied to both the first and the second element in the list .top, now the second element does not have any style information for color applied, so therefore it uses the style of the parent witch has the color red.
Unfortunately the child selector causing all the li to inherit the class. So you'll need to define another child ul.sub > li{