Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matching the first/nth element of a certain type in the entire document

How can I specify :first-of-type of the entire document?

I want to style the first <p> of the HTML, no mater where it is located (I don't want to write section p:first-of-type because it may be located elsewhere in a different HTML document).

p {
  background:red;	
}

p:first-of-type {
  background:pink;
}

p:last-of-type {
  background:yellow;	
}
<body>
  <section>
    <p>111</p>
    <p>222</p>
    <p>333</p>
  </section>
  <p>444</p>
  <p>555</p>
</body>
like image 609
user3289092 Avatar asked Dec 17 '14 11:12

user3289092


People also ask

Which selects the first matching element in the document?

querySelector() The Document method querySelector() returns the first Element within the document that matches the specified selector, or group of selectors.

How do you find the nth element using CSS selector?

The :nth-child(n) selector matches every element that is the nth child of its parent. n can be a number, a keyword (odd or even), or a formula (like an + b). Tip: Look at the :nth-of-type() selector to select the element that is the nth child, of the same type (tag name), of its parent.

Can I use nth-of-type with class?

There cannot be a way to select :nth-of-type() of a class, because :nth-of-type() only selects the nth child of its type.

What is the difference between the nth child () and Nth-of-type () selectors?

As a general rule, if you want to select an interval of a selector regardless of the type of element it is, use nth-child . However, if you want to select a specific type only and apply an interval selection from there, use nth-of-type .


1 Answers

With CSS alone this unfortunately isn't possible. The documentation for the :first-of-type pseudo-class states:

The :first-of-type pseudo-class represents an element that is the first sibling of its type in the list of children of its parent element.

This means that :first-of-type is applied to the first element of its type relative to its parent and not the document's root (or the body element, in this case).


JavaScript solutions

:first-of-type

We can achieve this by introducing some JavaScript. All we need for this is JavaScript's querySelector() method, which pulls the first matching element from the selector specified.

In this example I've altered your :first-of-type pseudo-class to instead be a class of "first-of-type", then used JavaScript to add this class to the element returned when using querySelector('p'):

document.querySelector('p').className += ' first-of-type';
p {
  background:red;	
}


p.first-of-type {
  background: pink;
}
<body>
  <section>
    <p>111</p>
    <p>222</p>
    <p>333</p>
  </section>
  <p>444</p>
  <p>555</p>
</body>

:nth-child and :last-of-type

As for :nth-child and :last-of-type, we can instead make use of a similar method JavaScript gives us: querySelectorAll(). This method pulls all matching elements into a NodeList (which is similar to an array), which we can then iterate through or select specific elements from within through the index:

var elems = document.querySelectorAll('p');

// nth-of-type = NodeList[n - 1]
// e.g. to select the 3rd p element ("333"):
if (elems.length >= 2)
   elems[2].className += ' nth-of-type';

// last-of-type = NodeList length - 1
if (elems.length)
   elems[elems.length - 1].className += ' last-of-type';
p {
  background:red;	
}


p.nth-of-type {
  background: pink;
}

p.last-of-type {
  background: yellow;
}
<body>
  <section>
    <p>111</p>
    <p>222</p>
    <p>333</p>
  </section>
  <p>444</p>
  <p>555</p>
</body>

Note that I've included if statements around both selectors to ensure the elems NodeList has enough elements, otherwise an error will be thrown.

like image 187
James Donnelly Avatar answered Oct 03 '22 07:10

James Donnelly