How to use the :last-child selector? - html

I want to simply add a border-bottom to the last .slab
I tried a few things and I am unable to understand what is going on.
Case 1 - use .wrapper:last-child
If I try this on codepen.io or on Stackoverflow snippets, I don't get a border-bottom on last .slab
If I try this on JSFiddle or run the code separately in Chrome, I get a border-bottom on last .slab. However, if I uncomment <div class="something">New</div>, then the border-bottom on last .slab vanishes in both JSFiddle and on Chrome.
.wrapper {
width: 10em;
margin: 1em;
}
.wrapper:last-child {
border-bottom: 1px solid #999;
}
.slab {
background-color: #eee;
border-top: 1px solid #999;
padding: 1em;
}
<div class="wrapper">
<div class="slab">Hello</div>
<div class="slab">Hello</div>
<div class="slab">Hello</div>
</div>
<!--<div class="something">New</div>-->
Case 2 - use .slab:last-child
Turns out this works everywhere - JSFiddle, Chrome, codepen.io and on Stackoverflow. But I thought the selection was really for the last-child of .slab and not the last .slab
.wrapper {
width: 10em;
margin: 1em;
}
.slab {
background-color: #eee;
border-top: 1px solid #999;
padding: 1em;
}
.slab:last-child {
border-bottom: 1px solid #999;
}
<div class="wrapper">
<div class="slab">Hello</div>
<div class="slab">Hello</div>
<div class="slab">Hello</div>
</div>
Questions:
Does .slab:last-child mean the last child of .slab or the last occurrence of .slab ?
In case 1, why is the border-bottom vanishing after the introduction of an unrelated element .something ?
What is the best way to apply border-bottom to the last .slab ?

Does .slab:last-child mean the last child of .slab or the last occurrence of .slab ?
Neither. It matches an element that
has the "slab" class, and
is the last child of its parent.
The last .slab within its parent may not necessarily be its last child. .slab:last-child will match if and only if both conditions are true for the given element.
In case 1, why is the border-bottom vanishing after the introduction of an unrelated element .something ?
Because then the last child of the parent of .wrapper becomes that other element. This element isn't unrelated to .wrapper — it's related to it by way of being its next sibling.
The .slab elements within that wrapper never receive a border; the border is being applied to the .wrapper for as long as it is the last child of its parent. (Incidentally, the parent of .wrapper in your examples is implied to be body.)
What is the best way to apply border-bottom to the last .slab ?
You won't be able to do this reliably unless you can guarantee that the only possible children of .wrapper are .slab elements, in which case the class name then becomes quite irrelevant (but you can still include it in your selector so you avoid matching the last child of .wrapper when it's not a .slab).

last-child means exactly what is says...the very last element that is a child of a parent.
Not the last of class...the last element.
There is no last-of-class selector.
This: .slab:last-child means the last child that also has a class of .slab.
If it's not the last-child it won't apply and, equally, if it doesn't have a class of .slab it won't be selected.

The :last-child structural pseudo-class selector applies to siblings of a parent. It is equivalent to :nth-last-child(1),
In terms of your code, you would apply :last-child to .slab to select the last sibling of parent div.wrapper.
If the last child of div.wrapper did not have a slab class, then the selector wouldn't match. It would do nothing.
If the :last-child were applied to the div children of div.wrapper, like this:
.wrapper > div:last-child { ... }
... then the selector would match the last child regardless of the class, id or other attributes. It would match any div. If the last child was not a div, the selector would do nothing.
If you wanted to match the last child of div.wrapper, regardless of anything – meaning it just needs to be the last child – then you could do something like this:
.wrapper > *:last-child { ... }
Without the > child combinator, let's say .wrapper *:last-child { ... }, the last child of all descendant parent elements would be matched.
When you select .wrapper:last-child, you're targeting the element with class wrapper that is the last child of its parent (presumably body, in this case).
If div.wrapper is the only child of its parent, then :last-child, :first-child, :only-child and most other structural pseudo-class keyword selectors would match.
For a better understanding of these selectors (and all others), refer to this section of the CSS spec:
http://www.w3.org/TR/css3-selectors/#selectors

Related

Why isn't :last-of-type working on tumblr? [duplicate]

This question already has answers here:
Can I combine :nth-child() or :nth-of-type() with an arbitrary selector?
(8 answers)
Closed 5 years ago.
Despite limiting the :last-of-type to a certain div, when I add another div under that div, the :last-of-type class is suddenly canceled. Is there a reason why?
.container {
width: 400px;
border-bottom: 1px solid #111;
}
.container:last-of-type {
border-bottom: 0;
}
<div class="entry">
<div class="container">
{block:Posts} ....... {/block:Posts}
</div>
<div class="pagination">....</div>
</div>
Using this code, if I removed the .pagination div, the :last-of-type works normally and removes the border-bottom.But if I add the .pagination div, suddenly the :last-of-type doesn't work even though the .pagination div isn't included in the container class.
Is there a way to fix it? Or to select the last div of the .container div without having the .pagination class affecting it?
You’re selecting .container, not the last of its children. The form .container:last-of-type selects anything of class .container that is the last of its type. By inserting a space, which is the generic descendant selector, or a right angle bracket (>), which is the direct descendant selector, you’re now selecting the last of a given type within any element of class .container.
.container > :last-of-type
This may not be your best option, though. You should consider whether last-child makes more sense. For example, if you introduce elements of different a types at some point, the last of each type will be selected.
last-of-type refers to the element type (in this case div), not to the class, so it won't work the way you expect it, but will select the .pagination DIV, which is the last DIV inside the container element.
However, if the last .container div is always the second last DIV in there (only followed by the .pagination div, you can use :nth-last-of-type(2):
.container {
width: 400px;
border-bottom: 1px solid #111;
}
.container:nth-last-of-type(2) {
border-bottom: 0;
}
<div class="entry">
<div class="container">
container content
</div>
<div class="container">
container content
</div>
<div class="container">
container content
</div>
<div class="container">
container content
</div>
<div class="pagination">....</div>
</div>

Apply specific margins to first and last element that are not siblings

I have specific type of boxes in my HTML that have, let's say margin: 10px; to all of them. They are displayed in a row on the page (using Bootstrap) and I want to remove the left margin of the first element and the right margin of the last element. I could use :first-child or :first-of-type and their respective lasts but the elements are not siblings and they do not have a common parent. The HTML looks something like this:
<div class='container'>
<div class='col-md-2'>
<div class='MY-CUSTOM-BOX'>
</div>
</div>
<div class='col-md-5'>
<div class='MY-CUSTOM-BOX'>
</div>
</div>
<div class='col-md-5'>
<div class='MY-CUSTOM-BOX'>
</div>
</div>
</div>
:first-of-type applies to all boxes, not sure how to approach the :first-child because of the nested divs. Any ideas?
It looks like you could use a combination of css selectors to achieve this, namely the > as well as :first-child and :last-child
:first-child > .MY-CUSTOM-BOX {
margin-left: 0;
}
:last-child > .MY-CUSTOM-BOX {
margin-right: 0;
}
This selects the direct MY-CUSTOM-BOX descendants of any first and last child elements.
That should work where the boxes have the same level of parent (i.e. container -> div -> MY-CUSTOM-BOX)
You could also do it the other way round which may give you better results depending on how nested you are:
.container > :first-child .MY-CUSTOM-BOX {
margin-left: 0;
}
.container > :last-child .MY-CUSTOM-BOX {
margin-right: 0;
}
This selects the first and last child of container and then gives any MY-CUSTOM-BOX elements inside it margin left/right of 0.
Here's a (relatively crude) fiddle demonstrating both examples: https://jsfiddle.net/ttakchr1/

CSS selector to select the first element after n elements

Is there a way to select the first element with a some class after n elements? For example in the following HTML, I want to be able to select only the first div that has CSS class apple after the 5th div, resulting in the 7th div element being selected.
<div>
<div class="data-class">1</div>
<div class="data-class">2</div>
<div class="data-class">3</div>
<div class="data-class apple">4</div>
<div class="data-class">5</div>
<div class="data-class">6</div>
<div class="data-class apple">7</div>
<div class="data-class apple">8</div>
<div class="data-class">9</div>
<div class="data-class apple">10</div>
</div>
This selector selects all the divs, but I only want the first: .data-class.apple:nth-child(n+5)
And this one doesn't even work: .data-class.apple:nth-child(n+5):first-child
I have put the HTML and CSS samples here.
UPDATE
Current CSS selectors
.data-class{
background-color: #0ea;
padding: 10px;
margin-bottom: 5px;
border: 1px solid #444;
}
.data-class:nth-child(n+5)+.apple{
background-color: #f0f;
}
To select an element appearing after some other element, use the ~ combinator:
.data-class:nth-child(5) ~ .data-class.apple {
background-color: #f0f;
}
You won't be able to match only the first .apple that occurs using just one selector. You will need to create another rule to undo the styles that you apply for subsequent .apple elements:
.data-class:nth-child(5) ~ .data-class.apple ~ .data-class.apple {
background-color: #0ea;
}
This technique is explained here.
it is better to say having css class, not having css.
I couldn't find the appropiate selector strictly.
Instead of this, you could use jquery and write javascript function which
use for loop from 5th child until it finds class containing apple. You may use jquery n-th-child to select child in loop and hasClass to determine if it contains apple.
Therefore select result by passing result to n-th-child function.
It uses this test:
div > .data-class.apple, .data-class{.....}
or another use:
div > .apple:not(.data-class){.....}

How to use first-child?

I would like to select the first div called "aProduct" but I'm a bit confused on how to do this. I already tried this:
<div id="kasticketProducts">
<div class="aProductHeader"></div>
<div class="aProduct"></div>
<div class="aProductHeader"></div>
<div class="aProduct"></div>
</div>
This is my current CSS:
#kasticketProducts:first-child .aProduct {
margin-top: 30px;
background: red;
}
#kasticketProducts:first-child .aProduct
Using above css means first it'll search for id with kasticketproducts in that first-child, here first child refer to aProductHeader from here you are trying to search aProduct but it is not there.
Actually from DOM hierarchy aProduct class div is at second child this will be referred in css as nth-child(2) here and no need of again .aProduct .So the final solution for this is write as #kasticketProducts div:nth-child(2)
First, whats the difference?
From MDN :
:first-child()
The :first-child CSS pseudo-class represents any element that is the first child element of its parent.
:first-of-type()
The :first-of-type CSS pseudo-class represents the first sibling of its type in the list of children of its parent element.
So inshort, :first-child() is somewhat a loose pseudo selector compared to :first-of-type()
Unfortunately :first-child or :first-of-type doesn't respect classes or ids, they are only concerned with the DOM elements. So if you do something like, will fail
#kasticketproducts div.aProduct:first-of-type {
color: red;
}
So in this case the best you can do with CSS is use :nth-of-type() with 2 as a value, now obviously it will fail if your element doesn't have a class of aProduct
#kasticketproducts div:nth-of-type(2) {
color: red;
}
Demo
OR
you can use adjacent selector with :first-of-type()
#kasticketproducts div:first-of-type + div {
color: red;
}
Demo
Second solution is MORE COMPATIBLE as far as IE is concerned
DEMO
Code is not working because aProductHeader class is before first occurrence of aProduct class.
See demo.
You can't target the first element of a class, but you can target the elements that come after, so you can set the styles on all the aProduct elements and then override it on all aProduct that comes after the first one using the ~ opreator:
#kasticketproducts .aProduct {
margin-top: 30px;
background: red;
}
#kasticketproducts .aProduct ~ .aProduct {
margin-top: 0;
background: none;
}
Demo: http://jsfiddle.net/a9W5T/
You can use
:first-child, :nth-of-type(1), :first-of-type or :nth-child(1n)
And why your code donst work, is because you use:
#kasticketProducts:first-child .aProduct
this will take the first element #kasticketProducts, use this instead: #kasticketProducts .aProduct:nth-child(2) {
color: red;
} <-- This will take the first element .aProduct inside your ID element
Another solution would be to style .aProduct, and then override the style for any succeeding occurrences of .aProduct using the general sibling combinator:
#kasticketProducts .aProduct {
// effectively becomes the style for the first occurrence of .aProduct
}
#kasticketProducts .aProduct ~ .aProduct {
// overrides the style set above for all occurrences of .aProduct,
// apart from the first
}
The biggest advantage of this approach is that it doesn't rely on the structure of the markup.
General sibling selectors on MDN
Here's an example
Check the #id, it's case sensitive
Also, be careful with quotes, you are not closing them.
<div id="kasticketProducts">
<div class="aProductHeader">aaa</div>
<div class="aProduct">aaa</div>
<div class="aProductHeader">aaaa</div>
<div class="aProduct">aaa</div>
For the first .aProduct get selected:
#kasticketProducts .aProduct:nth-child(2) {
/* your styles */
}
Sorry for that, thought was for getting the first kasticketProduct. Apologizes.

How do you make nth-child work with descendant selectors?

I have this code.
<div class="myDiv">
<div>
I want to be red.
</div>
</div>
<p>I'm some other content on the page</p>
<div class="myDiv">
<div>
I want to be blue.
</div>
</div>
.myDiv div:nth-child(odd) {
color: red;
}
.myDiv div:nth-child(even) {
color: blue;
}
I see why it's not working. It's making every odd div within myDiv be red. What I want it to do is make every odd example of a div within myDiv be red. How can I write that?
Here's a JSFiddle.
There are a couple of problems here. The :nth-child is on the wrong element. The inner divs are always the first child, so the :nth-child(odd) selector works for both. Instead move to
.myDiv:nth-child(odd) div
...however this does not work either because of the <p>. A working solution with your sample is
.myDiv:nth-of-type(odd) div
http://jsfiddle.net/tvKRL/1/
NOTE that the nth-of-type only works because the .myDiv elements are all divs (it's based on the element, not the selector), so the selector ignores the <p>. If there can be another div between .myDivs I don't think any CSS will work for what you want to do.
You can't do this generically, for the reason given by Domenic. To put it simply: there's no selector that lets you filter an existing subset of matched elements.
On the off chance that among your p and div.myDiv siblings the only div elements are the ones with that class anyway, then you could use :nth-of-type() to have it look at those intermediate divs only:
div.myDiv:nth-of-type(odd) div {
color: red;
}
div.myDiv:nth-of-type(even) div {
color: blue;
}
Or if there are other divs without that class which should be excluded, then unless there is some sort of pattern in which they're laid out, you're out of luck.
This is not possible. There is no CSS selector that will do what you want, as you can see by perusing the complete list of selectors.
In general CSS selectors do not "reach out" to encompass elements above the DOM tree of the one selected. You are asking for something even more sophisticated than that, combining characteristics of parent elements with ordinal properties of the targeted elements, even though those targeted elements are distributed among entirely different places in the DOM tree.
Just applynth-childto the first member of the descendant selector, not the last one.
div:nth-of-type(odd) > div {
color: red;
}
div:nth-of-type(even) > div {
color: blue;
}
<div class="myDiv">
<div>
I want to be red.
</div>
</div>
<p>I'm some other content on the page</p>
<div class="myDiv">
<div>
I want to be blue.
</div>
</div>