CSS select direct children, but not if inside another nested child - css

So, if this is the HTML of an element:
<div class="parent">
<div class="ignore-me">
<p class="child">ignore me</p>
<p class="child">ignore me</p>
<p class="child">ignore me</p>
<!-- I don't know how many <p> gonna be here -->
</div>
<p class="child">paint me green</p>
<p class="child">paint me blue</p>
</div>
How can I :
Select the children .child but not the ones inside the
div.ignore-me?
Select them separately, based on their index order.
I tried to use a mix of > and :nth-child(n) like this:
.parent > .child:nth-child(1)
But, it doesn't work!
Can this be done only CSS?
.parent > .child:nth-child(1) {
background: green;
}
.parent > .child:nth-child(2) {
background: blue;
}
<div class="parent">
<div class="ignore-me">
<p class="child">ignore me</p>
<p class="child">ignore me</p>
<p class="child">ignore me</p>
<!-- I don't know how many <p> gonna be here -->
</div>
<p class="child">paint me green</p>
<p class="child">paint me blue</p>
</div>

Use div.parent > p.p
> is the child combinator. It matches only those elements matched by the second selector that are the direct children of elements matched by the first.
div.parent > p.p {
color:green;
}
<div class="parent">
<div class="ignore-me">
<p class="p">don't select me</p>
<p class="p">don't select me</p>
<p class="p">don't select me</p>
<!-- I don't know how many <p> gonna be here -->
</div>
<p class="p">select me</p>
<p class="p">select me too</p>
</div>

The accepted answer can be further simplified to div.parent > p, because > already only selects direct children.
div.parent > p {
color:green;
}
<div class="parent">
<div class="ignore-me">
<p>don't select me</p>
<p>don't select me</p>
<p>don't select me</p>
<!-- I don't know how many <p> gonna be here -->
</div>
<p>select me</p>
<p>select me too</p>
</div>
Regarding
Select them separately, based on their index order.
you can use :nth-child, but be aware that :nth-child also counts <div class="ignore-me"> as a child of <div class="parent">. So your first <p class="child"> is the second child. You can then use even and odd to alternate between the children.
div.parent > p {
color:green;
}
div.parent > p:nth-child(odd) {
color:blue;
}
<div class="parent">
<div class="ignore-me">
<p class="child">ignore me</p>
<p class="child">ignore me</p>
<!-- I don't know how many <p> gonna be here -->
</div>
<p class="child">paint me green</p>
<p class="child">paint me blue</p>
<p class="child">paint me green</p>
<p class="child">paint me blue</p>
</div>

Selecting direct nth p tag inside "parent" class
div.parent>p.child:nth-child(2) {
background: green;
}
div.parent>p.child:nth-child(3) {
background: blue;
}
div.parent>p.child:nth-child(4) {
background: green;
}
we can slect odd and event children
div.parent>p.child:nth-child(odd) {
background: green;
}
div.parent>p.child:nth-child(even) {
background: red;
}

Related

How do I hide only the first element of a parent class [duplicate]

This question already has answers here:
Can I combine :nth-child() or :nth-of-type() with an arbitrary selector?
(8 answers)
Closed 2 years ago.
I have the following markup:
.shwonlyclick {
display: none;
}
.asd>.delfirstdiv:first-child>.shwonlyclick:first-child {
display: block;
}
<div class="asd">
<div>title</div>
<div>sub title</div>
<div class="delfirstdiv">
<p class="shwonlyclick">Show this</p>
</div>
<div class="delfirstdiv">
<p class="shwonlyclick">Hide</p>
</div>
<div class="delfirstdiv">
<p class="shwonlyclick">Hide</p>
</div>
</div>
all tags are hidden, I only want the first one show. How?
Move your title and sub-title outside the parent div and fix your typo in your selector and it will work:
first-child is the first element inside it's parent (not the first element with a class name)
.shwonlyclick {
display: none;
}
.asd>.delfirstdiv:first-child>.shwonlyclick:first-child {
display:block;
}
<div>title</div>
<div>sub title</div>
<div class="asd">
<div class="delfirstdiv">
<p class="shwonlyclick">Show this</p>
</div>
<div class="delfirstdiv">
<p class="shwonlyclick">Hide</p>
</div>
<div class="delfirstdiv">
<p class="shwonlyclick">Hide</p>
</div>
</div>
if you are unable to change the html layout, then you can use the adjacent sibling combinator to hide any divs that follow another (which will mean the first is shown):
.delfirstdiv+.delfirstdiv .shwonlyclick {
display: none;
}
<div class="asd">
<div>title</div>
<div>sub title</div>
<div class="delfirstdiv">
<p class="shwonlyclick">Show this</p>
</div>
<div class="delfirstdiv">
<p class="shwonlyclick">Hide</p>
</div>
<div class="delfirstdiv">
<p class="shwonlyclick">Hide</p>
</div>
</div>

css/sass :not(:first-of-type) not working, is hiding all elements of type

I have a sass block that i have tried several different ways:
I've tried this:
.progress-body {
display: none;
&:first-of-type {
display: block;
}
}
and this:
.progress-body {
&:not(:first-of-type) {
display: none;
}
}
and this:
.progress-body:not(:first-of-type) {
display: none;
}
when applied to HTML that looks like this:
<div class="panel">
<div class="panel-heading">
</div>
<div class="panel-body progress-body">
<div class="row">
<div class="col-md-12">
<p class="lead">Step 1: Choose your template...</p>
</div>
</div>
</div>
<div class="panel-body progress-body">
<div class="row">
<div class="col-md-12">
<p class="lead">Step 2: Compose your email...</p>
</div>
</div>
</div>
</div>
the result is that it hides all the elements with the progress-body class. This is normally pretty straight forward CSS so no idea what is wrong here...
In this case progress-body is not the first-of-type, this would technically be .panel-heading since the first-of-type refers to the type element selector (div) and not the class.
The :first-of-type CSS pseudo-class represents the first element of
its type among a group of sibling elements.
Ref: :first-of-type - CSS | MDN
Consider wrapping your .progress-body elements in a containing element, you will achieve the expected behaviour, since .progress-body would be the first of its type with the class name .progress-body.
Code Snippet Demonstration:
.progress-body:not(:first-of-type) {
display: none;
}
<div class="panel">
<div class="panel-heading">
</div>
<div class="panel-outer-body">
<div class="panel-body progress-body">
<div class="row">
<div class="col-md-12">
<p class="lead">Step 1: Choose your template...</p>
</div>
</div>
</div>
<div class="panel-body progress-body">
<div class="row">
<div class="col-md-12">
<p class="lead">Step 2: Compose your email...</p>
</div>
</div>
</div>
</div>
</div>
If you can't wrap as UncaughtTypeError wrote in his answer, youcan use (general) sibling selectors.
.progress-body + .progress-body {display: none;}
or
.progress-body ~ .progress-body {display: none;}
I expect the first is block by default, if you didn't change it elsewhere.

CSS Grab All Class Name Except For Last

I want to grab all the class name ('my-class') and change it's color to red EXCEPT for the last one
Apparently I've been googling and there's no such thing as :last-of-class or whatever. I'm having trouble trying to find a work around without using JS.
div1 and div2 are both dynamic! If div2 doesn't exist, then div1 should have the first p element red and the second not.
Please note I left a 'p' tag at the top because I don't want that being part of my selector. I just need the 'my-class' specifically.
or is there a selector I can write to grab all "p"s inside of my-container which include nested P's
<p>Some text</p>
<div class="my-container">
<div class="div1">
<p class="my-class"></p>
<p class="my-class"></p>
</div>
<div class="div2">
<p class="my-class"></p>
<p class="my-class"></p>
<p class="my-class"></p>
<p class="my-class"></p> <!-- This tag should not be red-->
</div>
</div>
I can also use sass so feel free to include that in if need be.
I don't know of any SINGLE rule that would do this, but a simple workaround would be to use 2 separate rules in conjunction:
.my-class {
color: red;
}
.div-2 .my-class:last-child {
color: // whatever you want the default to be
}
note that the order is important, setting the last child's color should be done after setting everything first
You can use the workaround below.
use div:last-child . that will select the last div in the container and if there is only one, it will select it and so...the last p from the last div will be of other color ( in this example )
.my-container div p.my-class {
color:red;
}
.my-container div:last-child p.my-class:last-child {
color:blue;
}
<p>Some text</p>
<div class="my-container">
<div class="div1">
<p class="my-class">a</p>
<p class="my-class">a</p>
</div>
<div class="div2">
<p class="my-class">a</p>
<p class="my-class">a</p>
<p class="my-class">a</p>
<p class="my-class">b</p> <!-- This tag should not be red-->
</div>
</div>
This will get the behavior you're looking for without any forced reflow:
.my-class:not(:last-child) {
color: red;
}
<p>Some text</p>
<div class="my-container">
<div class="div1">
<p class="my-class">a</p>
<p class="my-class">b</p>
</div>
<div class="div2">
<p class="my-class">c</p>
<p class="my-class">d</p>
<p class="my-class">e</p>
<p class="my-class">f</p> <!-- This tag should not be red-->
</div>
</div>

Select all but first element using CSS3

I need to select all headers but the first
<div class="block">
<div class="header">first</div>
</div>
<div class="block">
<div class="header">second</div>
</div>
<div class="block">
<div class="header">third</div>
</div>
<div class="block">
<div class="header">fourth</div>
</div>
Using jquery I would do this $(".header:not(:first)"), I'm however restricted to CSS/CSS3. I cannot tag the elements other than in my example.
Using .header:not(:first-child) wont do the trick
The .header elements are not siblings, therefore you should probably select all but the first .block element, then select the descendant .header from there:
.block:not(:first-child) .header {}
Depending on your markup, you may also want to negate the first of type if the element's types differ:
.block:not(:first-of-type) .header {}
.block:not(:first-child) .header {
color: #f00;
}
<div class="block">
<div class="header">first</div>
</div>
<div class="block">
<div class="header">second</div>
</div>
<div class="block">
<div class="header">third</div>
</div>
<div class="block">
<div class="header">fourth</div>
</div>
As David Thomas points out, you can also use the adjacent sibling combinator, + or the general sibling combinator, ~ in order to select all following siblings:
.block ~ .block .header {}
or:
.block + .block .header {}
.block + .block .header {
color: #f00;
}
<div class="block">
<div class="header">first</div>
</div>
<div class="block">
<div class="header">second</div>
</div>
<div class="block">
<div class="header">third</div>
</div>
<div class="block">
<div class="header">fourth</div>
</div>

css check previous element classes

So, in my code i have the following possibilities:
<div class="price-box">
<p class="was-old-price">$PRICE$</p>
<p class="special-price">$PRICE$</p>
</div>
or
<div class="price-box">
<p class="old-price">$PRICE$</p>
<p class="special-price">$PRICE$</p>
</div>
I want when .was-old-price get printed insted of .old-price, the .special-price has display:none properties. is this possible to achieve this using CSS?
You can do that with the the Adjacent Sibling Combinator (+) selector:
.was-old-price + .special-price {
display: none;
}
The E + F selector selects the F element immediately following the E element. In this case, the .special-price element immediately following the .was-old-price element. Here's an example:
.was-old-price + .special-price {
display: none;
}
<h3>Box 1</h3>
<div class="price-box">
<p class="was-old-price">was-old-price</p>
<p class="special-price">special-price</p>
</div>
<h3>Box 2</h3>
<div class="price-box">
<p class="old-price">old-price</p>
<p class="special-price">special-price</p>
</div>

Resources