CSS3: Differences in child styling - css

I'm not sure if my question title accurately displays what I'm trying to ask, but this is pretty much my first exposure to CSS3 and have been exploring various projects people have done in order to gain some hands on experience.
In searching through these projects I cam across something I'm having some trouble understanding. What exactly is the difference between the following two lines:
#random_ID > ul > li > a { ... }
#random_ID ul li a { ... }
Are these just two ways of writing the same thing? Any help would be greatly appreciated!

The greater than symbol limits the lookup to just first-level descendants: children of the selector on the left. Without the symbol, it can be any descendent at any level.
So the first example, it's "random_ID with a child ul with a child li with a child a" and the second is "random_ID with any descendant ul with any descendent li with any descendent a"

> means "direct child". This will only style it if the element (one on the right of >) is a direct child of the parent (one on the left of >)
So say if I have the following layout:
<div>
<ul>
<li></li>
<li></li>
</ul>
</div>
div > li { background: red; } Would not work, because li is not a direct child of it, whereas div > ul > li> or div li would work.
It should be noted that not every browser supports the direct child tag, specifically older versions of internet explorer, so don't rely on it, or have some fallback if you do use it.

Related

CSS :nth-of-type() and :not() selector?

I have floated articles side by side that are 25% wide. I'm adding a clear:both after every fourth element. However I need to insert a graphical section-break inbetween the elements. And it has to be inside the <ul>. To be valid I wrapped the "section-break" (the first li item in the sample underneath) into a <li> as well.
<ul>
<li class="year"><h1>THIS IS A SECTION Break and 100% wide</h1></li>
<li>This is a article and only 25% wide</li>
<li>This is a article and only 25% wide</li>
<li>This is a article and only 25% wide</li>
<li>This is a article and only 25% wide</li>
</ul>
I want every fourth element to be a line break so I use …
ul li:nth-of-type(4n+1) { clear: both; }
However I want the li.year not to be affected by this behaviour so I tried this
ul li:not(.year):nth-of-type(4n+1) { clear: both; }
Right now the last <li> in my sample code above is floated into the next line but that shouldn't happen since the first <li> isn't one of the floated articles but contains a headline.
Is it possible to stack the :not and nth-of-type() selector onto each other?
The selector you have --
ul li:not(.year):nth-of-type(4n+1) { background: yellow; }
-- is perfectly correct (as shown by highlighting the selector).
The issue is with how you're using clear. It works if you use clear:right, and then clear:left on the following element:
ul li:not(.year):nth-of-type(4n+1) { clear: right; }
ul li:not(.year):nth-of-type(4n+2) { clear: left; }
Edit per comments The stricken-out text is nonsense. The real issue, as per BoltClock's answer, is that the :not pseudo-class doesn't affect nth-of-type. Adjusting the selector offset works in this case by coincidence, but would not work if the :not pattern was different.
ul li:not(.year):nth-of-type(4n+2) { clear: left; }
http://jsfiddle.net/8MuCU/
The reason your :not() doesn't appear to work is because the li.year is of the same element type as the rest of your li elements (naturally), so :nth-of-type(4n+1) matches the same elements regardless of the .year class.
It's not possible to stack selectors sequentially either. That's just not how they work.
Since you can't change your li elements to something else because of HTML markup rules, and :nth-match() is in a future spec and hasn't been implemented yet, you have to make do with changing your :nth-of-type() formula to accommodate the structure instead:
ul li:not(.year):nth-of-type(4n+2) { clear: both; }

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.

Is there a way to check if the current LI element has a certain element, such as UL using css?

I want to check if the current li has a ul, if so apply style to the li. is there a way to do this in css?
Using jQuery to do it is simple. $('li').has('ul').css('background-color', 'red');
CSS Tricks discusses what you want here - it's called parent selector, and it's not a great idea to implement. Generally I'll use jQuery to apply styles to a parent if the child exists.
are you wanting to know if an element (li) has a certain child element (ul), and if so, style the parent element (li)?
if so -- no, there is no way to style a parent based on it's children in pure css. However, jQuery has selectors that allow you to get nodes that match this pattern, which you can then apply styles to.
The following applies styles to the child uls of a li:
li ul li { color:red }
http://jsfiddle.net/bkC36/
To check if a clicked li has a ul inside of it you need JavaScript
This rule should apply a style to any li that has a ul at any level bellow it.
ul li {/* */}
If you want to style a li that has a ul directly bellow it you can use this rule
ul > li {/* */}

CSS3 selectors - select very first item or item after

Let's say a have the following code:
<nav id="main-navigation">
<ul>
<li>Link 1 Level 1</li>
<li>Link 1 Level 1</li>
<ul>
<li>Link 1 Level 2
</ul>
</ul>
</nav>
And now I want to to set first ul's height to 100px and second ul should be 300px.
When I try
nav ul {
height: 100px
}
Second ul also inherits this value.
I was trying "~", "+", ">", first-childs etc. but don't know how to do that, even with documentation.
Is there a good explained (preferably with demos/screens) guide to new css3 selectors? W3 Table is too nerdy for me.
Thanks!!!
Just select any ul that is a descendant of ul and give it that style, if you will only have 2 layers of <ul>s. No need for any special CSS2/CSS3 combinators since <ul> cannot directly contain <ul>, plus you don't have to worry about IE either.
nav ul {
height: 100px;
}
nav ul ul {
height: 300px;
}
To select direct children of an element, and not any descendant, you should use the > syntax. In your case (after you put the second ul inside a li) you need:
nav > ul {
height: 100px;
}
nav > ul > li > ul {
height: 300px;
}
Extra: It doesn't really make sense to have a 300px item inside a 100px item. Why do you want that?
Another extra: Try to read the w3c docs, it will save you some time in the long run. What you don't understand you can always ask on SO.
Firstly, how imporant is browser compatibility to you? All of those selectors you mentioned have issues in various versions of IE (IE8 is obviously better than IE7, but even IE8 is missing a lot of CSS selectors)
Simple nested selectors (ie just a space between the CSS names) will work for you - although as you say, setting nav li {height:100px;} sets it for all the LIs, you can override that with nav li li {height:300px;} to set the inner one back the way you want it.
If you want to use the 'correct' selectors, the one you want is >.
nav>ul>li {
height:100px;
}
This will only affect the outer LI elements, not the inner one. However as I say, it won't work in older versions of IE (fortunately it does work in IE7 and up, so it's only an issue if you want to support IE6).
You say that you've found the various selectors quite hard to grasp. I recommend you visit Quirksmode. For a start, it's got a very handy compatibility chart showing which browsers support which selectors, but it's also got excellent examples of how each selector works, which should help you understand them a bit better.

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