Nesting child selectors in CSS - html

I have this HTML:
<div class="navbar">
<ul>
<li>Foo
<ul>
<li>Bar</li>
</ul>
</li>
</ul>
</div>
I want to apply CSS only to item "Foo." I do not want to tag every top-level <li> with a special class. My limited knowledge tells me I should be able to do this:
.navbar > ul > li {
text-transform: uppercase;
}
But the style gets applied to "Bar" as well when I do it like this. I thought that '>' specifies only immediate children, does it not work the same way when it's nested? Is what I'm trying to do even possible?

I thought that '>' specifies only immediate children, does it not work the same way when it's nested?
It does work the same way. Since you're anchoring the ul directly to .navbar with .navbar > ul, your selector does apply to li elements directly that particular ul only.
The problem is not with the selector; it's the fact that text-transform, like most text properties, is inherited by default. So even though you're applying the style only to immediate li elements, the nested ones receive it by inheritance.
You will need to reverse this manually on the nested elements:
.navbar > ul > li li {
text-transform: none;
}

Related

Need more clarification of the CSS syntax

In CSS block:
.navbar-custom .nav li a:hover{
outline:none;
background-color: rgba(255,255,255,0.2);
}
does this mean:
"The hover effect applies to the a tag in the navbar-custom's sub class nav list element?"
If no, please clarify.
Yes, you're interpreting it correctly. A space between selectors means that style will be applied to any descendants of the parent selector that match. So for .navbar-custom .nav li a:hover, any anchor elements that are descendants of list items that are descendants of elements in the nav class that are descendants of elements in the navbar-custom class would have that particular style applied on hover.
If you used a bracket instead of the space (i.e. .navbar-custom > .nav > li > a:hover then the style would only apply to direct descendants of each selector, rather than any descendants.
.navbar-custom .nav li a... Are the element selectors. This selector is applying style to the anchor tag within the other element listed in order.
for example
<div class="navbar-custom">
<ul class="nav">
<li>
link somewhere
</li>
<li>
link somewhere
</li>
<li>
link somewhere
</li>
</ul>
</div>

How could I use pseudo-element :after :before conditionally

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().

Block Desendants while selecting child elements

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

Should I define list-style on <li> or <ul> too?

Is there a good reason to override CSS list-style on both <ul> and <li> or just <li>?
Per w3.org you can define list-style-type on any element with display:list-item.
As far as I know, in modern browsers you can set any element to display: list-item so that - if you wanted to - you could correctly use the list-style-type property on any of them.
Example:
<!DOCTYPE html>
<html lang="en">
<head>
<title>12084892</title>
<meta charset="utf-8">
<style>
div span {
display:list-item;
list-style-type: disc;
list-style-position: inside;
}
</style>
</head>
<body>
<div>
<span>One</span>
<span>Two</span>
</div>
</body>
</html>
Trivia tidbit aside, what behavior are you looking to get? If you want different list items in the same list to have different bullets, then you'll need to define the list-style-type on the lis themselves. If you want all the lis within a given ul to have the same bullet, it's up to you. I typically define this on the ul, however. It is more intuitive to do it that way for me, personally.
If you look at the CSS spec, you'll see that property is intended to style "elements with display: list-item".
The property is inherited if not explicitly defined on the <li> elements, so you should stick to applying the style to only <li> elements.
If it's the same one, no. Just define it on whatever's convenient to you; <li>s will inherit the <ul>'s list-style unless explicitly overridden.
Inheritance transfer the 'list-style' values from ol and ul elements to li elements.
so i think you should apply the style to only li elements.
Even if list style is getting inherited from UL/OL, you should define css list-style to li only. And You can create different list styles with each other in one list. For example:
ul.test li {
list-style:disc;
margin:0 0 0 20px;
}
​ul li:first-child {
list-style:circle;
}​
You should normally set list-style on ul and ol elements only, because this avoids unexpected and undesired problems caused by cascading rules. See description of `list-style in CSS 2.1 spec.
For example, ol li { list-style: upper-roman; } may look safe, but consider this:
<ol>
<li>foo
<ul>
<li>bar
</ul>
</ol>
Now the inner li element, with “bar” content, will have the list style applied to it, because it too matches the selector ol li. (It is true that using the selector ol > li would avoid this, but it has browser compatibility issues.)
Setting ol { list-style: upper-roman; } instead avoids the issue, since now the inner li does not match, and it inherits list-style from its parent, ul (which has a suitable setting in browser default style sheet).
However, you need to set list-type directly on an li if you want one particular list item be styled differently from other items in the same list. In such cases, you will normally use an id selector or other selector that matches that specific element only, not any inner li elements.

CSS to effect "li" only if a child of a specific "ul"

I have a unordered list as so:
<ul id="vertical_menu">
<li>Home</li>
<li>Subitem 1</li>
<li>Subitem 2</li>
</ul>
Now, I need to add borders to the "list item" li elements only if it is a child of the ul with the id vertical_menu.
Any ideas on how to do this?
ul#vertical_menu > li
{
/* apply li styles here as needed */
border: 1px solid #000;
}
ul#vertical_menu describes a ul element with ID 'vertical_menu'. > li describes a direct child element of type li. Any styles you list here will apply directly to the li elements as you wanted.
If you require support for IE6, the child selector > will be an issue. One work around to this is to apply styling to single level li, and "reset" it on further nested li, such as:
ul#vertical_menu li
{
border: 1px solid #000;
}
ul#vertical_menu li li
{
border: none;
}
This will add border to the first level list items within the vertical_menu, and will remove the border from any further nested items. Again not necessary to consider with modern browsers - depends on requirements.
In HTML markup, element IDs should be unique, so realistically you also don't need to select by ul and can simply use #vertical_menu > li or #vertical_menu li. Including ul in the selector is very strict. To each his own..
This selector translates exactly to what you're asking:
ul#vertical_menu > li
If your markup is always going to have one level of li elements under that ul, and/or only the ID is only going to be assigned to ul and not some other type of element (which it should be, for site consistency), there are a number of other ways to select the same elements, for example:
ul#vertical_menu li /* Assumes only one level of <li> */
#vertical_menu > li /* Assumes only this <ul> has the ID */
#vertical_menu li /* Assumes both of the above */
These alternatives are useful if IE6 support is a requirement, as it doesn't support the > combinator, but they all depend one way or another on the structure of your HTML.
Try this:
ul#vertical_menu > li{
border:1px;
}
It's worth noting that using the > selector doesn't work in older versions of Internet Explorer (IE6, I believe), so if you're looking also to support that,
ul#vertical_menu li
will also work (but it will apply the border to every list item under #vertical_menu even if its a submenu.
just make
ul#vertical_menu li{
border:1px solid #CCC;
Remember to use ul as it will make the css specificity more clear and it will style only the li items which are under the ul.
hope it will work for you.
#vertical_menu > li { border: 1px solid black; }
Should work, but IE6 will need
#vertical_menu li { border: 1px solid black; }
Both answers are correct. While ul#vertical_menu li targets all lis from ul#vertical_menu, ul#vertical_menu > li targets only first line li descendents.
For example, using the last selector only the id=one li will be targeted:
<ul id="vertical_menu">
<li id="one"></li>
<another-element>
<li id="two"></li>
</another-element>
</ul>