While I was writing a bit of CSS, a situation that I have never encountered before using the :nth-child(n) appeared and I was doubt of what is actually happening.
When I use pseudo classes, I write them without a space between the selector, like so:
div#wrap:hover {
border-bottom: 2px solid orange;
}
/* OR */
div#wrap:nth-child(4) {
border-bottom: 2px solid orange;
}
But it didn't work the way I expected, so I tried inserting a space between the selector and the pseudo class. Surprisingly, it worked:
div#wrap :nth-child(4) {
border-bottom: 2px solid orange;
}
What is happening to make this work?
div#wrap :nth-child(4) {
border-bottom: 2px solid orange;
}
<div id="wrap">
<h1>Heading 1</h1>
<p>This is a test!</p>
<h2>Creating content</h2>
<p>The next paragraph uses the <strong>.html</strong> method to create a new element.</p>
</div>
You're misunderstanding the selector. It selects the element that is also the :nth-child(n) which also has the preceding element as a parent.
When there is no selector preceding, it defaults to *:nth-child(n)
Because you probably only want to apply this to direct descendants and not every element which is the fourth child of its parent and a descendant of the parent, I would use .element > *:nth-child(n) to only apply to direct descendants.
div#wrap > *:nth-child(4) {
border-bottom: 2px solid orange;
}
div#wrap > *:nth-child(4) {
border-bottom: 2px solid orange;
}
<div id="wrap">
<h1>Heading 1</h1>
<p>This is a test!</p>
<h2>Creating content</h2>
<p>The next paragraph uses the <strong>.html</strong> method to create a new element.</p>
</div>
If you wanted to be more specific and only select the fourth child if it is a <p> element, you can use .element > p:nth-child(n). This will select all <p> elements that are the fourth direct descendant of elements matching the div#wrap selector.
div#wrap > p:nth-child(4) {
border-bottom: 2px solid orange;
}
div#wrap > p:nth-child(4) {
border-bottom: 2px solid orange;
}
<div id="wrap">
<h1>Heading 1</h1>
<p>This is a test!</p>
<h2>Creating content</h2>
<p>The next paragraph uses the <strong>.html</strong> method to create a new element.</p>
</div>
If you want to select the second <p> element directly descending from each div#wrap, you can use .element > p:nth-of-type(n) like so:
div#wrap > p:nth-of-type(2) {
border-bottom: 2px solid orange;
}
div#wrap > p:nth-of-type(2) {
border-bottom: 2px solid orange;
}
<div id="wrap">
<h1>Heading 1</h1>
<p>This is a test!</p>
<h2>Creating content</h2>
<p>The next paragraph uses the <strong>.html</strong> method to create a new element.</p>
</div>
What does the space do?
Space before :nth-child(4) is equal to *:nth-child(4). * is a global CSS selector. So if any child element which is 4th in the list of elements of any parent, the CSS rules are applied to that element.
But using #wrap before the nth-child will limit the scope of the selection within the #wrap element.
Alternate Solution(Understanding how nth-child works):
You can also use: p:nth-child(4) which targets the paragraph element which is 4th with respect to the parent element which is #wrap.
:nth-child will select irrespective of whatever the element is, or what the sibling elements are. You will need to use :nth-of-type to differentiate.
* {
font-family: Helvetica;
}
p:nth-child(4) {
border-bottom: 2px solid orange;
}
p:nth-of-type(2) {
background: lightblue;
color: #fff;
}
<div id="wrap">
<h1>Heading 1</h1>
<p>This is a test!</p>
<h2>Creating content</h2>
<p>The next paragraph uses the <strong>.html</strong> method to create a new element.</p>
</div>
A space in a CSS selector means the next part is a descendant (not direct descendant) of what was previously selected.
tr td means a <td> inside a <tr>.
table td means a <td> inside a <table>.
In your case, the :nth-child() pseudo-class is applied after the <div> so it matches for the nth (4th...) child of that div. Had you removed the space, it would match a the 4th div with id "wrap" (which doesn't exist)
Related
lets say i have this html:
<div class="wrapper">
<p>testOne</p>
<p>testTwo</p>
<p>testThree</p>
</div>
If i want to apply to the p tag design, i can go to CSS and use:
1)
.wrapper > * {
color: red;
}
OR
2)
.wrapper {
color: red;
}
Both of them work just fine, so, what is the difference?
I have heard once that the the first example apply the design only to the direct childs of the "wrapper", so then i did:
<div class="wrapper">
<p>testOne</p>
<div class="container">
<p>testTwo</p>
</div>
<p>testThree</p>
</div>
so testTwo is not a direct child..but he still got the color red!
so testTwo is not a direct child..but he still got the color red!
testTwo's parent <div class="container"> has the color red, though, so all of its children inherit that style. It's the same fundamental behavior as setting your body color to red and that reflecting on the whole document.
I have heard once that the the first example apply the design only to the direct childs of the "wrapper"
That's right.
Maybe border will better illustrate the difference between the selectors, since children don't inherit it:
.wrapper > * {
border: 1px solid red;
}
.wrapper {
border: 1px solid blue;
}
<div class="wrapper">
<p>testOne</p>
<div class="container">
<p>testTwoA</p>
<p>testTwoB</p>
</div>
<p>testThree</p>
</div>
Although you didn't ask about it, for context consider also .wrapper *, which selects all children regardless of depth, further illustrating >:
.wrapper * {
border: 1px solid green;
}
.wrapper > * {
border: 1px solid red;
}
.wrapper {
border: 1px solid blue;
}
<div class="wrapper">
<p>testOne</p>
<div class="container">
<p>testTwoA</p>
<p>testTwoB</p>
</div>
<p>testThree</p>
</div>
Note that order matters in the above example since .wrapper * and .wrapper > * are no longer disjoint as .wrapper and .wrapper > * are.
I have a simple markup and I would like to select a div by it's content. Here is my code...
<div class="parent">
<h4>Child of parent</h4>
<div>
<div>I'm red!</div>
<h4>I'm red's sister</h4>
<div>I'm blue!</div>
<h4>I'm blue's brother</h4>
</div>
</div>
and selecting <div>I'm red!</div> with the following CSS...
div:contains("I'm red!") {
color: red;
}
since contains() is deprecated or never got implemented, I can do the following...
.parent div:nth-child(1) {
color: red;
}
.parent dh4:nth-child(2) {
color: red;
}
to target just the first two elements, and it worked, but I would like to know if it is a way I can target just the first two element which happened to be <div> and <h4> in one CSS line of code? I need to do this without javascript. Eventually I need to target just 3rd and 4th.
Yes. Use :nth-child(-n+2).
For the 3rd and 4th you can use :nth-child(n+3):nth-child(-n+4) or just :nth-child(-n+4) and let specificity fix it for you.
The logic is easy:
:nth-child(-n+a) selects the a-th element and its previous siblings
:nth-child(n+a) selects the a-th element and its following siblings
:nth-child(n+a):nth-child(-n+b) selects the a-th and b-th elements, and the siblings in-between.
.parent > div > :nth-child(-n+4) {
color: blue;
}
.parent > div > :nth-child(-n+2) {
color: red;
}
<div class="parent">
<h4>Child of parent</h4>
<div>
<div>I'm red!</div>
<h4>I'm red's sister</h4>
<div>I'm blue!</div>
<h4>I'm blue's brother</h4>
</div>
</div>
I don't think I understand your question. You can do that to have it on one line anyway.
.parent div:nth-child(1), .parent dh4:nth-child(2) {color: red;}
or you could apply a red class on the first two divs and do :
.red{color:red}
I have an interesting problem, consider this HTML:
<div class="foo">Hello</div>
<div class="foo">World</div>
<div class="bar">Hotel</div>
<div class="bar">Romeo</div>
<div class="bar">Foxtrot</div>
<div class="foo">Ford</div>
<div class="foo">Prefect</div>
This content is dynamically generated and I never know when the class is going to flip. Is there a pure CSS way of styling groups of elements of a class? For example, I want each adjacent group of class "foo" to be bold and have a specific margin while each adjacent group of class "bar" I want to be red in color.
**Hello**
**World**
Hotel
Romeo
Foxtrot
**Ford**
**Prefect**
Help me stackoverflow, you're my only hope!
How about:
.foo + .bar,
.bar + .foo{
margin-top:10px;
}
This will add 10px of margin every time a .bar div follows a .foo div, or vice versa.
.foo + .bar,
.bar + .foo {
margin-top: 10px;
border-top: solid 1px black;
}
<div class="foo">Hello</div>
<div class="foo">World</div>
<div class="bar">Hotel</div>
<div class="bar">Romeo</div>
<div class="bar">Foxtrot</div>
<div class="foo">Ford</div>
<div class="foo">Prefect</div>
I understand that I can change another element's style when hovering on a different element like this:
.element-one:hover .element-two {
opacity: 0.8;
}
But how can I change the style of all the elements in the page except element-two when I hover on element-one?
You can use .element-one:hover :not(.element-two).
Here is an example:
.element-one:hover :not(.element-two) {
opacity: 0.8;
}
.element-one {
background: black;
margin: 10px;
}
.element-one div {
background: green;
border: 1px solid blue;
margin: 10px;
padding: 10px;
}
<div class="element-one">
<div class="element-two">
element-two
</div>
<div class="element-three">
element-three
</div>
<div class="element-four">
element-four
</div>
</div>
However - note that it will work only for elements inside element-one and not for all the elements in the page.
You can do this with body for example, but the problem there is that .element-two is probably also inside some other element that exists inside body, and in such case the .element-two will get the opacity from it's containing element.
I have a LESS mixin applied to a number of different classes. Its possible for one element with the mixin to be within another element which also have the mixin. When this is the case I dont want the child element to have the styling applied.
http://codepen.io/anon/pen/NPBWXM
.style1() {
padding: 10px;
border: 1px solid red;
}
.elm1 {
.style1;
}
.elm2 {
.style1;
}
<div class="elm1">Element 1</div>
<div class="elm2">
Element 2
<div class="elm1">Element 1</div>
</div>
No, it appears this is not possible.