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.

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-type when 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-child when 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: none still 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.

Play in Editor

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.

Selectors Level 4 - The :first-of-type Pseudo-Class

Selectors Level 3 - The :first-of-type Pseudo-Class