CSS :first-of-type Pseudo-Class
The CSS :first-of-type pseudo-class selects an element that is the first sibling of its HTML element type. It allows you to style the first paragraph, heading, list, or other element of a particular type within a parent, even when different types of elements appear before it.
:first-of-type Syntax
:first-of-type {
property: value;
}
The :first-of-type pseudo-class does not accept arguments. It matches an element when that element is the first sibling of its element type within its parent.
Example Syntax
p:first-of-type {
font-weight: bold;
}
This rule makes the first paragraph within each parent bold, even when another type of element appears before it.
The :first-of-type pseudo-class has a specificity of 0-1-0. Combined with the p type selector, its specificity becomes 0-1-1.
Using a Parent Selector
article > p:first-of-type {
color: #0088cc;
}
This rule selects the first paragraph that is a direct child of each <article> element. The child combinator (>) prevents the rule from selecting paragraphs inside nested containers.
How :first-of-type Works
The browser examines the element children of a parent and compares their HTML element types. An element matches :first-of-type when no earlier sibling has the same element type.
Other element types do not affect the matching position. Comments, whitespace, and text nodes are also ignored when determining sibling order.
Expected Matching Behavior
| Condition | Matches :first-of-type? |
|---|---|
| First paragraph among its siblings | Yes |
| Second paragraph among its siblings | No |
| First paragraph after a heading | Yes |
| Only element of its type within a parent | Yes |
| First element after a comment | Yes |
| First element of its type after whitespace | Yes |
| First element of its type hidden with display: none | Yes |
The selector is evaluated independently for each parent. Multiple elements on a page can match :first-of-type when they belong to different parents or have different element types.
Important: The :first-of-type pseudo-class compares actual element types, not class names. Two elements with the same class but different HTML tags are considered different types.
Elements That Match :first-of-type
The :first-of-type pseudo-class can match any HTML element that is the first sibling of its element type.
First Paragraph After a Heading
<article>
<h2>CSS Selectors</h2>
<p>First paragraph.</p>
<p>Second paragraph.</p>
</article>
article p:first-of-type {
color: #0088cc;
font-weight: bold;
}
The first paragraph matches even though the heading is the article's first element child.
First Heading of a Particular Type
<section>
<h2>Section Title</h2>
<h3>First Subheading</h3>
<h3>Second Subheading</h3>
</section>
section h3:first-of-type {
color: #27ae60;
}
The First Subheading matches because it is the first <h3> element among its siblings. The preceding <h2> does not affect the result.
Different Element Types
<div class="content">
<h2>Introduction</h2>
<p>First paragraph.</p>
<ul>
<li>HTML</li>
<li>CSS</li>
</ul>
<p>Second paragraph.</p>
</div>
.content > :first-of-type {
border-left: 3px solid #0088cc;
}
The heading, first paragraph, and list all match because each is the first element of its own type within the container. The second paragraph does not match.
Nested Containers
<div class="groups">
<section>
<h2>HTML</h2>
<p>First HTML paragraph.</p>
<p>Second HTML paragraph.</p>
</section>
<section>
<h2>CSS</h2>
<p>First CSS paragraph.</p>
<p>Second CSS paragraph.</p>
</section>
</div>
.groups p:first-of-type {
font-weight: bold;
}
Both First HTML paragraph and First CSS paragraph become bold because each is the first paragraph within its own section.
Classes Do Not Define Element Types
<div class="group">
<div class="notice">First notice.</div>
<p class="notice">Second notice.</p>
<div class="notice">Third notice.</div>
</div>
.group .notice:first-of-type {
background-color: #eaf6fc;
}
Both the first <div> and the <p> match because each is the first sibling of its HTML element type. The shared notice class does not make them the same element type.
:first-of-type vs. :first-child
The :first-of-type and :first-child pseudo-classes differ in how they determine the first matching element.
Comparison
| Pseudo-Class | Matching Behavior |
|---|---|
:first-of-type |
Matches the first sibling of the same element type. |
:first-child |
Matches an element only when it is the first element child of its parent. |
HTML
<article>
<h2>Web Development</h2>
<p>First paragraph.</p>
<p>Second paragraph.</p>
</article>
CSS
article p:first-child {
color: #e74c3c;
}
article p:first-of-type {
color: #0088cc;
}
The p:first-child rule matches nothing because the heading is the first element child. The p:first-of-type rule matches the first paragraph because it is the first paragraph among its siblings.
When Both Match
<div>
<p>First paragraph.</p>
<p>Second paragraph.</p>
</div>
When the first paragraph is also the parent's first element child, it matches both :first-child and :first-of-type.
Use :first-child when the element must appear first among all element children. Use :first-of-type when its position among siblings of the same element type matters.
Related Selectors
Several structural pseudo-classes select elements according to their position among siblings.
Structural Selector Comparison
| Selector | Description |
|---|---|
:first-of-type |
Matches the first sibling of its element type. |
:last-of-type |
Matches the last sibling of its element type. |
:only-of-type |
Matches an element with no siblings of the same type. |
:nth-of-type(1) |
Matches the first sibling of its element type. |
:first-child |
Matches the first element child, regardless of type. |
:nth-child(1) |
Matches the first element child, regardless of type. |
Equivalent First-of-Type Selectors
p:first-of-type {
color: #0088cc;
}
p:nth-of-type(1) {
font-weight: bold;
}
Both selectors match the first paragraph among its siblings.
Selecting All Except the First of a Type
article > p:not(:first-of-type) {
margin-top: 15px;
}
This rule adds a top margin to every direct paragraph child of an article except its first paragraph.
Selecting the Last of a Type
article > p:last-of-type {
margin-bottom: 0;
}
This rule removes the bottom margin from the last paragraph among the article's direct children.
Practical Uses
The :first-of-type pseudo-class is useful when a particular element type needs different styling regardless of the other elements that appear before it.
Styling the First Paragraph
article > p:first-of-type {
font-size: 1.125rem;
font-weight: bold;
color: #333;
}
This rule emphasizes the first direct paragraph in an article, even when the article begins with a heading.
Removing the First Paragraph's Top Margin
.content > p:first-of-type {
margin-top: 0;
}
This rule removes the top margin from the first paragraph without affecting headings or other element types.
Highlighting the First Table
article > table:first-of-type {
border: 2px solid #0088cc;
}
This rule adds a blue border to the first table that is a direct child of each article.
Styling the First Image
.gallery > img:first-of-type {
border: 3px solid #0088cc;
padding: 4px;
}
This rule highlights the first image that is a direct child of the gallery container.
Styling the First List of Each Type
.content > ul:first-of-type {
background-color: #eaf6fc;
padding: 15px 15px 15px 35px;
}
This rule styles the first unordered list in a content container, even when paragraphs or headings appear before it.
Removing a Border from the First Section
main > section {
border-top: 1px solid #ccc;
padding-top: 15px;
}
main > section:first-of-type {
border-top: 0;
padding-top: 0;
}
This pattern removes the separator above the first section while keeping separators above subsequent sections.
Best Practices
- Use
:first-of-typewhen an element must be the first sibling of its HTML element type. - Remember that different element types do not affect which element matches.
- Use
:first-childwhen the element must be the first element child regardless of type. - Use the child combinator (
>) when the rule should apply only to direct children of a container. - Remember that class names do not determine element types.
- Remember that comments, whitespace, and text nodes do not affect matching.
- Remember that elements hidden with
display: nonestill count when determining element order. - Use
:not(:first-of-type)when styling all elements of a type except the first one. - Keep selectors specific enough to avoid unintended matches in nested containers.
- Use a class when an element must retain special styling even if its position among siblings changes.
:first-of-type Example
This example highlights the first paragraph inside an article, even though a heading appears before it. Use the buttons to add or remove a paragraph at the beginning of the article's paragraph group and observe how the matching element changes.
HTML
<div class="first-of-type-demo">
<article id="demo-article">
<h3>CSS Tutorial</h3>
<p>First paragraph.</p>
<p>Second paragraph.</p>
<p>Third paragraph.</p>
</article>
<button type="button" id="add-paragraph">Add First Paragraph</button>
<button type="button" id="remove-paragraph">Remove First Paragraph</button>
</div>
CSS
.first-of-type-demo article {
margin-bottom: 12px;
}
.first-of-type-demo h3 {
margin: 0 0 10px;
}
.first-of-type-demo p {
padding: 9px 12px;
margin: 0 0 5px;
background-color: #f5f5f5;
border-left: 4px solid #ccc;
}
.first-of-type-demo p:first-of-type {
background-color: #eaf6fc;
border-left-color: #0088cc;
font-weight: bold;
}
.first-of-type-demo button {
padding: 7px 10px;
margin: 0 4px 5px 0;
cursor: pointer;
}
JavaScript
const article = document.querySelector("#demo-article");
let paragraphCount = 1;
document.querySelector("#add-paragraph").addEventListener("click", () => {
const paragraph = document.createElement("p");
paragraph.textContent = "New Paragraph " + paragraphCount++;
article.querySelector("h3").after(paragraph);
});
document.querySelector("#remove-paragraph").addEventListener("click", () => {
const firstParagraph = article.querySelector("p");
if (firstParagraph) {
firstParagraph.remove();
}
});
Browser Result
The first paragraph initially has a blue background and border. Adding a new paragraph immediately after the heading transfers the styling to the new paragraph. Removing the first paragraph transfers the styling to the next paragraph automatically.
Browser Support
Baseline: Widely available. The :first-of-type pseudo-class has been supported across major browser engines for many years and works in modern versions of Chrome, Edge, Firefox, Safari, and other browsers.
It works with ordinary element selectors, class selectors, and combinators without requiring JavaScript.
For current compatibility information, visit Can I Use? .
Specifications
The :first-of-type pseudo-class is defined in Selectors Level 4 as a structural pseudo-class. It was also defined in Selectors Level 3.
