How to get different class selectors using nth-child in css - css

I have these codes
<div class="test">
<div class="tag1"></div>
<div class="tag1"></div>
<div class="tag1"></div>
<div class="tag2"></div>
<div class="tag2"></div>
<div class="tag2"></div>
</div>
Now I want to get second child of .tag2 selector.
I try this code and it's not working, but when I use .tag1 it's working.
.test .tag2:nth-child(2) {
background-color: #000;
}
How can i fix this?

:nth-child works on elements, not on other selectors. Here your .tag2 element is the 4th element in the list.
When browsers begin to implement the Selectors Level 4 standards we'll be able to achieve this using the :nth-match structural pseudo-class selector, but unfortunately that's quite a way off yet.
A Potential CSS Solution (Markup-dependant)
If your markup will always be that the first .tag2 will only ever follow .tag1 and the second .tag2 will only ever follow .tag2, you can fake it with this:
.tag1 + .tag2 + .tag2 {
background-color: #000;
}
This selects the .tag2 element which immediately follows a .tag2 element which immediately follows a .tag1 element.
A JavaScript Solution
If you can't do that then you'll have to go for a JavaScript solution instead (or implement something on the back-end which generates the content).
The below example pulls all .tag2 elements within your .test container, then grabs the 2nd one ([1] here, remember the 0 index: [1] = 2nd), then applies the style to that element.
You'll need to add in some checks to ensure this element exists before applying the style.
document.querySelector('.test').querySelectorAll('.tag2')[1].style.background = '#000'
<div class="test">
<div class="tag1">tag1</div>
<div class="tag1">tag1</div>
<div class="tag1">tag1</div>
<div class="tag2">tag2</div>
<div class="tag2">tag2</div>
<div class="tag2">tag2</div>
</div>

I know your question isn't tagged with JavaScript, but a good solution with JS is as follows:
var alltagtwos = document.getElementsByClassName("tag2");
alltagtwos[1].className += " secondel";
.tag2.secondel {
background-color: #000;
color: #fff;
}
<div class="test">
<div class="tag1">tag1 - 1</div>
<div class="tag1">tag1 - 2</div>
<div class="tag1">tag1 - 3</div>
<div class="tag2">tag2 - 1</div>
<div class="tag2">tag2 - 2</div>
<div class="tag2">tag2 - 3</div>
</div>
What I've done here is add all elements with the class .tag2 into an array-like object using getElementsByClassName. I then select the second element which has the class .tag2 (index starts at zero, so I've select [1]) and appended another class to it (.secondel) which I've then styled with CSS.

Related

Use CSS selectors like :first-child inside shadow dom

Is there any way to use css selectors like :first-child, :not(:last-child) inside of the shadow dom?
The example is like this
CustomElement.html
<div id="parent-div>
<slot></slot>
</div>
App.html
<div>
<custom-element>
<div class="heading">Main Heading</div>
<div class="item">item 1</div>
<div class="item">item 1</div>
<div class="item">item 1</div>
<div class="heading">Second Heading</div>
<div class="item">item 1</div>
<div class="item">item 1</div>
<div class="item">item 1</div>
</custom-element>
</div>
what i want to do is find out the first .heading element and add custom styles to it. Since <div class=heading"> is actually a component, i can't add custom styling to it thinking only as the first heading.
P.S.:- I'm using angular-elements, if it helps
The same answer as I gave in your question yesterday
Slotted content is not moved to shadowDOM,
it remains (invisible) in lightDOM
and is REFLECTED in the shadowDOM <SLOT>
So SLOTTED content styling is done in the CSS scope where <custom-element> resides.
or with ::slotted( x )
From the docs:
::slotted can only take a compound selector (in the parenthesis). The reason of this > restriction is to make a selector style-engine friendly, in terms of performance.
So with your structure you can do:
::slotted(.heading) { }
or
::slotted(:first-child) { }
but not:
::slotted(.heading:first-child)
Because it is a complex selector, not a (simple) compound selector
So your headings can be styled in global CSS, and will REFLECT to slotted content:
my-element div.heading{
background:blue;
color:white;
}
If you want to encapsulate this styling you have to wrap everything in (another) component
You can target all UNnamed slotted content with:
::slotted(:not([slot])){
font-weight:bold;
}
Here is another JSFiddle to play with slotted styling:
https://jsfiddle.net/WebComponents/108ey7b2/
I found a workaround for this in JS way.
For each slot, we have a eventHandler called (slotchange). By using that we can get the DOM event for the slot whenever the slot changes. Like this (HTML)
<custom-element (slotchange)="onSlotChanged($event)"></custom-element>
JS
onSlotChanged($event) {
console.log($event) // Go and research yourself about this event, you'll find many things usefull.
$event.target.assignedNodes() // This will give you the array of every elements, that are in side of the shadow dom
// Example usage, adding the margin-bottom to only first time (css :firsh-child)
$event.target.assignedNodes()[0].shadowRoot.getElementById('some-id').style.marginBottom = '10px'
}
If you only need to add a property to the element, you don't have to query shadowDom like "node.shadowRoot". But, if you want to access the element inside the shadowRoot of that element, you have to use that

How do i style two same class divs differently?

So basically I've got a setup that spits out the code in the following fashion..
<div class="parent">
<div class="subparent">
<div class="TARGETCLASS"></div>
</div>
<div class="subparent">
<div class="TARGETCLASS"></div>
</div>
</div> //close for the parent class
Now what I'm trying to do is to style "TARGETCLASS" that comes above one way and the "TARGETCLASS" that comes second in another way. I tried n-th child, but unable to achieve the result I'm looking for. There's no way to add additional classes or ID to the existing "TARGETCLASS" class. Otherwise I wouldn't be posting this question :)
Also, the "subparent" class also is same. for both the targetclass classes. That's the issue
Thanks in advance for taking your time to answer this question for me.
Cheers!
Looks like you've got some mal-formed tags in your html. And nth-child should work just fine. Also, make sure you place the nth-child selector on the subparent class, and not TARGETCLASS. It's common to mis-place the child selector. Try this:
<div class="parent">
<div class="subparent">
<div class="TARGETCLASS">
first-child
</div>
</div>
<div class="subparent">
<div class="TARGETCLASS">
second-child
</div>
</div>
</div>
<style>
.parent .subparent .TARGETCLASS {
background-color:#f00;
}
.parent .subparent:nth-child(1) .TARGETCLASS {
background-color:#0f0;
}
</style>
fiddle: https://jsfiddle.net/8ejxokuj/
I would use nth-of-type selector like so:
.parent{}
.parent > .subparent {} //targets both subparents
.parent > .subparent:nth-of-type(2) {} //targets the second subparent
.parent > .subparent:nth-of-type(2) > .TARGETCLASS{} //targets the child of the second subparent
The nth-of-type() selector enables you to style a specific element amongst a series, in this case we targeted the second .subparent then specified the child we needed.
I hope this helps!
It seems, it is working by the nth child.
it is about how childrens are called. Not like "Ask parent to find nth child, but ask child, how far is he from parent"
.parent .subparent:nth-child(1) {background: #FEE; color:RED;}
.parent .subparent:nth-child(2) {background: #EEF; color:blue;}
<div class="parent">
<div class="subparent">
<div class="TARGETCLASS">aaa</div>
</div>
<div class="subparent">
<div class="TARGETCLASS">bbb</div>
</div>
//close for the parent class
</div>

CSS :nth-of-type selector breaks on non-matching childs

I have a problem with CSS :nth-of-type selector. In my code I have a list of DIVs (class "item") that should have an alternating background-color (eg. red and green). Between these items there can be some other items (class "noitem") that should not be matched from the background-color.
Problem is now, that the :nth-of-type rule breaks on every of these non-matching elements. that causes that you have one red item after the other...
Example HTML Code:
<div class="row">
<div class="item"><h2>Item</h2></div>
<div class="item"><h2>Item</h2></div>
<div class="noitem"><h2>No Item</h2></div>
<div class="item"><h2>Item</h2></div>
<div class="item"><h2>Item</h2></div>
<div class="item"><h2>Item</h2></div>
<div class="item"><h2>Item</h2></div>
<div class="noitem"><h2>No Item</h2></div>
<div class="item"><h2>Item</h2></div>
<div class="item"><h2>Item</h2></div>
</div>
CSS:
h2{
font-size: 14px;
margin: 0 0 10px 0;
padding: 0;
}
.row .item:nth-of-type(even) h2{
background-color: red;
}
.row .item:nth-of-type(odd) h2{
background-color: green;
}
Can anybody help? Running example of that can be found here: http://jsfiddle.net/5qnjshg7/
The type in nth-of-type refers to the type of element (tag name, such as div). It does not mean "nth-of-something-with-exactly-the-same-classes", or "nth-of-the-selector-I-specified", which does not exist in CSS.
In other words, .item:nth-of-type(even) does not mean "an even-numbered entry in the list of all child elements with class .item", but rather, "an element with class .item which also is in an even-numbered position in the list of all child elements of that type (div in this case), regardless of their class or anything else".
One possible approach if you're stuck with the existing HTML
If you can generate different HTML, including for example new classes, or replacing the div on noitem elements with spans, as one answer suggested, then that is the best solution. In case you are not able to do or don't want to do that, and need to work with the existing HTML for whatever reason, this bit of JS will do the job:
var elts = document.querySelectorAll('div.item');
for (var i = 0; i < elts.length; i++) {
elts[i].classList.add(i % 2 ? 'red' : 'green');
}
Seems impossible with CSS, unless you can change your markup and make noitem elements <span>s?
<div class="row">
<div class="item"><h2>Item</h2></div>
<div class="item"><h2>Item</h2></div>
<span class="noitem"><h2>No Item</h2></span>
<div class="item"><h2>Item</h2></div>
<div class="item"><h2>Item</h2></div>
<div class="item"><h2>Item</h2></div>
<div class="item"><h2>Item</h2></div>
<span class="noitem"><h2>No Item</h2></span>
<div class="item"><h2>Item</h2></div>
<div class="item"><h2>Item</h2></div>
</div>
nth-of-type matches the element to its parent, so although it is not the same selector, it is in fact the correct index relevant to its parent.

What is css "[class*=my-class] .my-subclass" doing?

I inherited some css and I have searched everywhere online to understand what is being expressed by a block of css that looks like:
[class*=wrapper] .logo {
padding-top: 32px !important;
}
What is the asterisk and square brackets doing?
It is hard to search for [ and * on google... Sorry if the question is dumb.
It selects an element with class logo that has an ancestor that has wrapper somewhere in its class attribute. For example note that the class burgerwrapper also leads to the element being selected below.
[class*=wrapper] .logo {
color: #f99;
}
<div class="logo">Not selected</div>
<div class="wrapper">
<div class="logo">
Selected
</div>
</div>
<div class="burgerwrapper">
<div class="logo">
Selected
</div>
</div>
See http://css-tricks.com/attribute-selectors/ for some background information on attribute selectors.
what square brackets doing
Attribute selectors
CSS 2.1 allows authors to specify rules that match elements which have
certain attributes defined in the source document.
Attribute selectors w3
What is the asterisk
Substring matching attribute selectors
[att*=val] Represents an element with the att attribute whose value
contains at least one instance of the substring "val". If "val" is
the empty string then the selector does not represent anything.
Substring matching attribute selectors
To sum it up in you example:
[class*=wrapper] .logo {
color: red;
}
<div class="wrapper">
<div>not this</div>
<div class="logo">this</div>
<div class="logo">this</div>
</div>
<div>
<div>not this</div>
<div class="logo">not this</div>
<div>not this</div>
</div>
Select child elements with class .logo that their parent element has attribute class with value wrapper appears somewhere in that attribute.

CSS first-child not working as expected

I am using the following CSS to try and remove the left-border on the first child div of any element with the class called, "tblRow"
.tblRow div:first-child{
border-left: none;
}
<div class="tbl">
<div class="tblRow">
<div class="tblCell">Lower limit QTY</div>
<div class="tblCell">Upper Limit</div>
<div class="tblCell">Discount</div>
</div>
<div class="tblRow">
<div class="tblCell">1</div>
<div class="tblCell">5</div>
<div class="tblCell">25%</div>
</div>
</div>
This only removes the left-border from the first child div in the first row. It does not remove it in the second row. Any ideas?
I generally only use the :first-child and :nth-child psuedo selectors when I have little or no control over the elements or they are populated dynamically where I cannot rely on an order. Additionally, since :nth-child is CSS3, you can't rely on complete browser compatibility. If you can do without this psuedo selector, my advise is to create a secondary class for this purpose.
.tblCell.firstCell{
border-left: none;
}
<div class="tbl">
<div class="tblRow">
<div class="tblCell firstCell">Lower limit QTY</div>
<div class="tblCell">Upper Limit</div>
<div class="tblCell">Discount</div>
</div>
<div class="tblRow">
<div class="tblCell firstCell">1</div>
<div class="tblCell">5</div>
<div class="tblCell">25%</div>
</div>
</div>
It seems to work on the fiddle, so you probably have a (hidden) text node somewhere there. Therefore I suggest using .tblRow div:first-of-type { ... }, if possible from browser support point-of-view.

Resources