My code is as follows:
HTML
<div class="divs">
<div class="row">row 0</div>
<div class="not-row"></div>
<div class="row">row 1</div>
<div class="not-row"></div>
<div class="row">row 2</div>
<div class="not-row"></div>
<div class="row">row 3</div>
<div class="not-row"></div>
</div>
CSS
.row:nth-child(even) {
background: #fff;
}
.row:nth-child(odd) {
background: #eee;
}
This is supposed to paint the background of two of the rows gray and two of the rows white. Unfortunately it paints all of their backgrounds gray. What am I doing wrong?
I tried using nth-of-type instead of nth-child but that didn't change anything.
jsFiddle example
For even just use (as a default)
.row {}
Then override the odd ones with:
.row:nth-child(4n+1) {}
.row {
background: #fff;
}
.row:nth-child(4n+1) {
background: #eee;
}
http://jsfiddle.net/b8ma1hon/3/
More on how nth-child works can be found here:
https://css-tricks.com/how-nth-child-works/
You cannot simply use even/odd in this instance as that is in relation to all child elements, not just the ones with the class row.
Your inclusion of .row in the selector is purely an extra criteria and has no impact on the nth-child selector.
Likewise I could state:
.row:nth-child(1):hover {}
This would restrict selection to an element with a class of row, which is the 2nd child, which is currently in a hovered state.
It wouldn't make sense if this was the 2nd element out of all the hovered elements as you can only hover over one at a time.
I hope that makes sense!
It's also worth noting that your selector is now dependant on the not-row existing, or at least some kind of element existing between the row elements.
If this was to change then your selector would also have to change.
Alternatively you could change your element type for the not-row elements to something else so that you can make use of the nth-of-type selector:
<div class="divs">
<div class="row">row 0</div>
<span class="not-row"></span>
<div class="row">row 1</div>
<span class="not-row"></span>
<div class="row">row 2</div>
<span class="not-row"></span>
<div class="row">row 3</div>
<span class="not-row"></span>
</div>
.row {
background: #fff;
}
.row:nth-of-type(odd) {
background: #eee;
}
http://jsfiddle.net/b8ma1hon/5/
Related
I'm trying to do some styling using purely CSS selectors, my markup looks like this:
<div class="StyledRow">
<div class="Row">Input 1</div>
<div class="Row">Input 2</div>
</div>
<div class="StyledRow">
<div class="Row">Input 1</div>
<div class="Row">Input 2</div>
</div>
<div class="StyledRow">
<div class="Row">Input 1</div>
<div class="Row">Input 2</div>
</div>
The rendered elements are inputs side by side (2) and then stacked on top of one another (so the user can add as many data sets as they wish)
The above is a simplified version but because of additional elements, I need to be a bit more specific with my styles. For example, the current style of StyledRow looks like this:
const StyledRow = styled.div`
display: flex;
align-items: center;
*:not(:first-child) > * {
margin-left: 0.2rem;
}
`;
I am trying to target the second Row in the first StyledRow so that the styles can be different from the rest which use a margin-left: 0.2rem. I had tried to use first-of-type and not-first-child together but with no joy.
Any suggestions would be really appreciated!
If you use
*:not(:first-child) > * {
margin-left: 0.2rem;
}
it will apply that to everything. So if you use
.StyledRow:not(:first-child) > * {
margin-left: 0.2rem;
}
the styling will be applied on every iteration of StyledRow apart from the first one.
If you use:
.StyledRow:nth-child(2) > * {
margin-left: 0.2rem;
}
then that will specifically target the second iteration of StyledRow.
I'm trying to select every element within a wrapper except the elements within one of the children. Consider this:
<div class="wrapper">
<div class="this">
<div class="that"></div>
</div>
<div class="foo">
<div class="bar"></div>
<div class="orange">
<div class="ignore"></div>
</div>
</div>
<div class="hello"></div>
<div class="world">
<div class="ignore">
<div class="this"></div>
</div>
</div>
</div>
What I want to do is to make the text color of everything inside wrapper white, except the elements that are inside ignore. What I got so far is .wrapper *:not(.ignore *), which doesn't work.
EDIT: I can't accept solutions that include overriding what the color is within .ignore because that color is pre-set, and is out of my control. It is also impossible to know which color is used in the pre-set. Imagine there's a body {color:blue;}, only in my case, it's impossible to know what color it is.
Add color: #fff to .wrapper
Then, add whatever color your want to .ignore
After that, make sure .ignore loads after .wrapper in your style sheet.
.wrapper {
background: #131418;
color: #fff;
font-size: 25px
}
.ignore {
color: #933
}
<div class="wrapper">
<div class="this">
<div class="that">wrapper</div>
</div>
<div class="foo">
<div class="bar">wrapper</div>
<div class="orange">
<div class="ignore">ignore</div>
</div>
</div>
<div class="hello">wrapper</div>
<div class="world">
<div class="ignore">
<div class="this">ignore</div>
</div>
</div>
</div>
If you put them in right order you can get this:
.wrapper {
background: green;
}
.wrapper *:not(.ignore) {
color: white;
}
.wrapper *, .wrapper .ignore *{
color: red;
}
<div class="wrapper">
<div class="this">
<div class="that">1</div>
</div>
<div class="foo">
<div class="bar">2</div>
<div class="orange">
<div class="ignore">3</div>
</div>
</div>
<div class="hello"></div>
<div class="world">
<div class="ignore">
<div class="this">4</div>
</div>
</div>
</div>
Note that :not(...) is applied to the current element, so you can't use :not(something [some element inside])
I'd suggest:
.wrapper div:not(.ignore) {
color: white;
}
The reason your posted CSS selector doesn't work – and shouldn't be expected to work – is because:
.wrapper *:not(.ignore *)
Is trying to select all descendent elements that are not descendants of the .ignore elements, whereas in your question it seems that you're trying to select only elements that are not themselves of the .ignore class.
Further, the :not() pseudo-class:
...is a functional notation taking a simple selector (excluding the negation pseudo-class itself) as an argument. It represents an element that is not represented by its argument.
[Emphasis mmine, https://www.w3.org/TR/css3-selectors/#negation].
And a 'simple selector' is:
...either a type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class.
[https://www.w3.org/TR/css3-selectors/#simple-selectors-dfn]
Which appears to prevent the use of a combinator, the white-space, representing the selection of a descendant; meaning that your selector .ignore * is an invalid selector for the negation (:not()) pseudo-class.
Pure CSS doesn't seem to provide a good solution - at least not one I can think of.
The problem with not is it can only apply to "simple selectors", which basically means the selector it applies to can't contain combinators like whitespace.
For simple cases, you could do what a lot of people are suggesting - just have a second rule that selects .ignore * and undoes what your .wrapper * rule does. But if the .wrapper * rule does a lot, or if the exact state you'd get without the .wrapper * rule is unclear (maybe set by an external resource) then that isn't necessarily practical.
What you could do is use JavaScript (or similar) to propagate the .ignore class down to all of its descendants, then just use :not(.ignore)
I have this Fiddle, and what I am trying to do is when you mouse over each div section, it only changes the background for that section. Is there any way I can do that without having it change the background for everything? When I mouse over .two, the .one:hover gets fired. how can I make it fire .two and not .one when I mouse over .two?
CSS:
div.one:hover, div.two:hover, div.three:hover{
background-color: #69aeea;
}
HTML:
<div class="one">
Text 1
<div class="two">
Text 2
<div class="three">Text 3</div>
<div class="three">Text 3</div>
<div class="three">Text 3</div>
</div>
<div class="two">
Text 2
<div class="three">Text 3</div>
<div class="three">Text 3</div>
<div class="three">Text 3</div>
</div>
</div>
:hover is triggered all the way up to the root parent (typically <body>), so you can't trigger it only on the child when you have :hover states on the parent.
What you need to do is isolate the parts you actually want to show a hover state, which in this case I accomplished by wrapping the text in a <span>. This will keep the :hover state isolated from the other children of that parent.
<div class="one">
<span>Text 1</span>
<div class="two">
<span>Text 2</span>
<div class="three"><span>Text 3</span></div>
...
Then target specifically in the CSS: (The > character selects a direct descendent of a parent)
div > span:hover {
background-color: #69aeea;
}
You can then do different colors based on the level like so:
div.one > span:hover {
background-color: #69aeea;
}
div.two > span:hover {
background-color: #ae69ea;
}
div.three > span:hover {
background-color: #aeea69;
}
DEMO: http://jsfiddle.net/shshaw/8uetm/
Unfortunately, you can't access the parent of an element in CSS. Meaning, that if you hover over a child element, you can't set the background of its parent. You'll have to use javascript to achieve what you're asking.
I am trying to make the background color of the div's INSIDE reportRow to have a specific background color but I want it to switch colors every other reportRow.
I can't seem to get nth-child to work. Can anyone help?
<div class="reportRow">
<div style="width:75px;">Date1</div>
<div style="width:360px;">Address1</div>
<div style="width:40px;">Edit1</div>
<div style="width:40px;">Print1</div>
<div style="width:40px;">Delete1</div>
</div>
<div class="reportRow">
<div style="width:75px;">Date2</div>
<div style="width:360px;">Address2</div>
<div style="width:40px;">Edit2</div>
<div style="width:40px;">Print2</div>
<div style="width:40px;">Delete2</div>
</div>
http://jsfiddle.net/bhlaird/t75Zu/
You want to use nth-child on reportRow, but set the inner div's background
.reportRow:nth-child(2n) div {
background-color: blue;
}
In order to target every other nth-child, here's an example of what you should have in your CSS:
.reportRow:nth-child(even) {
background: #fff;
}
You can replace the parameter with even or odd as well as a couple of other things. Here's some documentation on the nth-child psuedo-class: http://www.w3schools.com/cssref/sel_nth-child.asp.
The issue lies within this CSS and HTML. Here is a link to jsFiddle with the sample code.
HTML
<ul>
<li class"complete">1</li>
<li class"complete">2</li>
<li>3</li>
<li>4</li>
</ul>
CSS
li.complete:last-child {
background-color:yellow;
}
li.complete:last-of-type {
background-color:yellow;
}
Shouldn't either of these lines of CSS target the last li element with the "complete" class?
This query in jQuery doesn't target it either:
$("li.complete:last-child");
But this one does:
$("li.complete").last();
li {
background-color: green;
}
li.complete:first-child {
background-color: white;
}
li.complete:first-of-type {
background-color: red;
}
li.complete:last-of-type {
background-color: blue;
}
li.complete:last-child {
background-color: yellow;
}
<ul>
<li class="complete">1</li>
<li class="complete">2</li>
<li>3</li>
<li>4</li>
</ul>
:last-child will not work if the element is not the VERY LAST element
I think it's crucial to add/emphasize that :last-child will not work if the element is not the VERY LAST element in a container. For whatever reason it took me hours to realize that, and even though Harry's answer is very thorough I couldn't extract that information from "The last-child selector is used to select the last child element of a parent."
Suppose this is my selector: a:last-child {}
This works:
<div>
<a></a>
<a>This will be selected</a>
</div>
This doesn't:
<div>
<a></a>
<a>This will no longer be selected</a>
<div>This is now the last child :'( </div>
</div>
It doesn't because the a element is not the last element inside its parent.
It may be obvious, but it was not for me...
Sidebar: This may seem like a ridiculous gotcha, but the devil's always in the details. :last-of-type may fit your needs in most cases (and feels intuitive) but :last-child definitely serves a purpose. It offers greater specificity (targeting only those elements which are, in-fact, the very last child in a parent). It depends on your use-case.
The last-child selector is used to select the last child element of a parent. It cannot be used to select the last child element with a specific class under a given parent element.
The other part of the compound selector (which is attached before the :last-child) specifies extra conditions which the last child element must satisfy in-order for it to be selected. In the below snippet, you would see how the selected elements differ depending on the rest of the compound selector.
.parent :last-child{ /* this will select all elements which are last child of .parent */
font-weight: bold;
}
.parent div:last-child{ /* this will select the last child of .parent only if it is a div*/
background: crimson;
}
.parent div.child-2:last-child{ /* this will select the last child of .parent only if it is a div and has the class child-2*/
color: beige;
}
<div class='parent'>
<div class='child'>Child</div>
<div class='child'>Child</div>
<div class='child'>Child</div>
<div>Child w/o class</div>
</div>
<div class='parent'>
<div class='child'>Child</div>
<div class='child'>Child</div>
<div class='child'>Child</div>
<div class='child-2'>Child w/o class</div>
</div>
<div class='parent'>
<div class='child'>Child</div>
<div class='child'>Child</div>
<div class='child'>Child</div>
<p>Child w/o class</p>
</div>
To answer your question, the below would style the last child li element with background color as red.
li:last-child{
background-color: red;
}
But the following selector would not work for your markup because the last-child does not have the class='complete' even though it is an li.
li.complete:last-child{
background-color: green;
}
It would have worked if (and only if) the last li in your markup also had class='complete'.
To address your query in the comments:
#Harry I find it rather odd that: .complete:last-of-type does not work, yet .complete:first-of-type does work, regardless of it's position it's parents element. Thanks for your help.
The selector .complete:first-of-type works in the fiddle because it (that is, the element with class='complete') is still the first element of type li within the parent. Try to add <li>0</li> as the first element under the ul and you will find that first-of-type also flops. This is because the first-of-type and last-of-type selectors select the first/last element of each type under the parent.
Refer to the answer posted by BoltClock, in this thread for more details about how the selector works. That is as comprehensive as it gets :)
I encounter similar situation. I would like to have background of the last .item to be yellow in the elements that look like...
<div class="container">
<div class="item">item 1</div>
<div class="item">item 2</div>
<div class="item">item 3</div>
...
<div class="item">item x</div>
<div class="other">I'm here for some reasons</div>
</div>
I use nth-last-child(2) to achieve it.
.item:nth-last-child(2) {
background-color: yellow;
}
It strange to me because nth-last-child of item suppose to be the second of the last item but it works and I got the result as I expect.
I found this helpful trick from CSS Trick