Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Learning

CSS selectors: What they are and how to use them

Understanding how to use CSS to select HTML elements and apply styles is critical for all front-end developers. Benjamin outlines the different selector types and how to use them in this article.

Benjamin Semah

·

30 Jan 2024

As a front-end developer, understanding CSS selectors and how they work is like having a key to control the look and feel of your web pages. In this article, you will learn all about CSS selectors, what they are, and how to make the most of them.

What are CSS selectors?

CSS Selectors allow you to choose specific HTML elements on a web page and add styles. Once you get the hang of them, they offer great flexibility. These selectors form the foundation for creating beautiful web pages.

But before you learn the various selectors, let’s first discuss two key concepts. Often, when you use the right selectors and your styles don’t work as expected, it’s one of these two principles at play.

The source order principle

This principle states that the last declaration wins when you have two or more selectors of the same specificity level.

For example, assuming you have two type selectors p in your stylesheet. The first adds a red color, and the second adds a blue color.

p { color: red; }


p { color: blue; }

The second rule will override the first rule because it was the last to be defined. The paragraphs will have a color of blue.

The specificity principle

This is a principle that shows which selector should take precedence when more than one CSS rule targets the same HTML element. You can think of specificity as a kind of ranking system for selectors.

The following is the specificity hierarchy for CSS selectors.

  • Universal selector (low specificity)

  • Type selectors

  • Class selectors

  • Pseudo-classes, Attribute selectors

  • ID selector (high specificity)

Let’s see an example of specificity at work. Below is a paragraph element with a class of greeting.

<!-- HTML -->
<p class="greeting">Welcome to Frontend Mentor</p>
/* CSS */
.greeting {
  color: green;
}

p { 
  color: red;
}

In the stylesheet are two selectors. A type selector p and a class selector .greeting. They both target the same paragraph element. However, the class selector has a higher specificity than the type selector. This means the color of the paragraph is going to be green even though the p selector is last in the source order.

CSS selector types

This article covers the following types of CSS selectors. Learning how to use them will make your work with CSS much easier.

  • Basic CSS selectors

  • Combined CSS selectors

  • CSS attribute selectors

  • CSS pseudo-element selectors

  • CSS pseudo-class selectors

Basic CSS selectors

These are the most straightforward ways to select HTML elements on a web page. They include the universal selector, type selectors, IDs, and classes.

Universal selector

This selects all the elements on a page. It’s useful for quick test situations. But it's not recommended for production code as it puts unnecessary weight on the browser. And can negatively affect performance. It’s denoted by the star (*) symbol.

For example, using the universal selector, the color blue is added to all the elements on the page.

Example of using the CSS universal selector.

Practice using the universal selector.

Type selector

You use this when you want to select all elements of the same type. The selection is based on the HTML tag name. For example, to select all paragraphs, you use the p tag.

Example:

Example of using the type selector to style elements.

The p selector adds the color blue to all three paragraphs on the page.

Practice using the element selector.

ID selector

This is denoted by the # symbol. You use ID selectors to target an element in your HTML with a unique element ID. ID selectors have a high specificity, which means they override the styles you set with other selectors.

Example:

Example of using the ID selector to style an element.

In the example above, the first type selector p adds the color blue to all paragraphs. However the ID selector #first-paragraph overrides that style by adding the color red to the first paragraph.

Practice using the ID selector.

Class selector

This is the recommended selector for adding the same style to a group of elements. To use a class selector, you write a period . before the name of the class. The class selector is useful because it helps you obey the DRY (Don't Repeat Yourself) principle.

Example:

Example of using the class selector to style elements.

The second and third paragraphs both have a class of .other-paragraphs. The browser, therefore, applies the same style to both of them.

Practice using the class selector.

Combined CSS selectors

These types of selectors are a combination of the other selectors. Using them allows you to make more precise selections of HTML elements.

Grouping selector

Syntax: x, y

This selector allows you to apply the same styles to two or more elements.  To use the selector, write the names of the elements you want to style. And separate the names with a comma.

Note: There should be no comma after the last element. Otherwise, the grouping selector will not work.

Example:

Example of using the grouping selector to style elements.

The grouping selector is used here to add the color blue to the h1, the paragraph with the #first-paragraph ID, and the list items with a class of .front-end.

Practice using the grouping selector.

Descendant selector

Syntax: x y

You use this when you want to select all of a particular element (y) inside of another element (x). Note that the y elements do not have to be direct children of the x element.

To use this selector, first write the name of the parent element x, leave a space, and then the name of the descendant element y.

Example:

Example of using the descendant selector to style elements.

The descendant selector is used here to select all paragraphs inside the body. Note how the third paragraph is also included though it’s not a direct child of the body element.

Practice using the descendant selector.

Direct child selector

Syntax: x > y

Similar to the descendant selector but selects only direct children. While the descendant selector will select all y inside x, this selector selects only y elements that are direct children of x.

Example:

Example of using the direct child selector to style elements.

Only the first two paragraphs (which are direct children of the body element) are selected this time around.

Practice using the direct child selector.

Adjacent sibling selector

Syntax: x + y

When you want to target an element that comes directly after another element in your HTML, you use the adjacent sibling selector.

First, write the name of the element that comes first, x, followed by the plus symbol +, and then the name of the element you want to add style to,  y.

Example:

Example of using the adjacent sibling selector to style elements.

This example selects the paragraph that comes directly after the h1 header, which is the first paragraph in this case.

Practice using the adjacent sibling selector.

General sibling selector

Syntax: x ~ y

This will target all y elements that come after an x element. The key thing to note with this selector is that the x and y elements must be siblings. To use it, separate the names of the elements with the tilde ~ sign.

Example:

Example of using the general sibling selector to style elements.

The first and second paragraphs were selected because they are both siblings of the h1 element. The third paragraph, which is a child of the footer (and not a sibling of the h1 header), is not selected.

Practice using the general sibling selector.

Chain selector

Syntax:  x.y

You can chain selectors together when selecting elements based on certain conditions. The key is to concatenate the selectors without any spaces. Doing so will ensure that only the elements that satisfy all the specified conditions will get the styles. You can chain a combination of selectors like two classes, element, and ID, or even more complex combinations.

Example:

Example of using the chain selector to style elements.

The li.front-end selector selects all list items with a class of front-end. Note how other list items without the front-end class are ignored.

Practice using the chain selector.

CSS attribute selectors

The attribute selectors allow you to target an element using its attribute. This means whether or not the style is applied depends on the presence or value of the given attribute.

To better understand attribute selectors, let’s use the HTML code below. It’s a simple markup of three elements. A header, a paragraph, and a button.

<h1 class="active title">Welcome to Frontend Mentor</h1>

<p class="paragraph">
  Improving your coding skills by building realistic projects
</p>

<button type="button" class="btn-active">
  Login with GitHub
</button>

Attribute exists

Syntax: [attribute]

This will check whether the attribute you specify exists on the HTML elements. The selector doesn't care about the value of the attribute. All it cares about is whether the attribute exists. And if it does, it applies the style.

Example:

Example of targeting and style elements with the "attribute exists" selector.

The [type] selector adds the color blue to the button because it has the type attribute.

Practice using the “attribute exists” selector.

Attribute equals

Syntax: [attribute="value"]

You use this selector to style elements with a specific attribute and a matching value. The given value of the selector should be the same as that of the element's attribute. Otherwise, it will not work.

Example:

Example of targeting and style elements with the "attribute equals" selector.

All three elements have a class. But the [class="paragraph"] selector adds the style to only the element whose class attribute has a value of “paragraph”.

Practice using the “attribute equals” selector.

Attribute starts with

Syntax: [attribute^="value"]

As the name suggests, this will select elements with an attribute whose value starts with a given string. This is denoted by a caret ^ symbol before the equals sign.

Example:

Example of targeting and style elements with the "attribute starts with" selector.

The h1 header now has a color blue because the value of its class attribute begins with the string “active”.

Practice using the “attribute starts with” selector.

Attribute ends with

Syntax: [attribute$="value"]

This is the opposite of the previous attribute selector. Instead of the starting string, it checks whether the value of the attribute ends with a given string.

You denote the "attribute ends with" selector with a dollar sign $ before the equals sign.

Example:

Example of targeting and style elements with the "attribute ends with" selector.

The value of the button’s class btn-active ends with the string “active”. That’s why the color blue is applied to it.

Practice using the “attribute ends with” selector.

Attribute contains

Syntax: [attribute*="value"]

You can use this selector to select elements with a specified attribute whose value contains a given substring. The position of the substring doesn't matter. It could be at the start, in the middle, or at the end.

Example:

Example of targeting and style elements with the "attribute contains" selector.

The style is applied to both the h1 header and the button because both have classes that contain the string “active”.

Practice using the “attribute contains” selector.

Attribute includes

Syntax: [attribute~="value"]

HTML elements can have attributes with more than one value. These values are separated with spaces. For example, the h1 element has a class attribute with two values (active and title).

In an instance like this, you can use this selector to target the element by checking if one of the values is equal to the given string.

Example:

Example of targeting and style elements with the "attribute includes" selector.

The color blue is applied on the h1 header because one of the values for its class attribute is “active”.

Practice using the “attribute includes” selector.

CSS pseudo-element selectors

You use the pseudo-element selectors when you want to select and style a specific part of an HTML element. They also allow you to apply styles on elements not part of the HTML structure. These selectors are denoted by double colons (::).

::before

This selector is useful for creating and inserting content before an already existing element in your HTML.

For example, let’s say you want to add an icon in front of the links on a page. With the ::before selector, you can use a content property and set the value to the icon you want to use.

<!-- HTML -->
<a href="http://www.frontendmentor.io">Go to Frontend Mentor</a>
/* CSS */
a::before {
  content: "🚀 "
}

In this example, a rocket icon is placed in front of the link text:

Example of targeting and style elements with the "before" pseudo selector.

Practice using the ::before selector.

::after

This is the opposite of the ::before selector. You can use it to insert content after an existing HTML element.

Using the previous example, you can place the rocket icon after the link’s anchor text, as shown below:

a::after {
  content: " 🚀"
}

Example of targeting and style elements with the "after" pseudo selector.

Practice using the ::after selector.

::first-line

This selector works on text elements. It targets the first line of a selected text and adds your style to it.

Note that this only works on block-level elements like paragraphs, headings, divs, etc. It doesn’t work for inline-level elements like span.

Example:

<!-- HTML -->
<p>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed eleifend, purus non bibendum sollicitudin. Neque dolor accumsan ligula, at tristique elit turpis eget tortor. Quisque interdum sapien vel mi lacinia laoreet. Vestibulum aliquam fringilla urna, ac condimentum justo suscipit id. Praesent ac sem eu ipsum volutpat feugiat. Proin suscipit ex sit amet viverra. Fusce in justo vitae tortor placerat tincidunt.
</p>
/* CSS */
p::first-line {
  color: red;
  font-weight: bold;
}

This example adds the color red and font weight of bold to the first line of the text:

Example of targeting and style elements with the "first-line" pseudo selector.

Practice using the ::first-line selector.

::first-letter

What if you want to style only the first letter? You can use the ::first-letter selector. The ::first-letter selector also works on block-level elements only.

p::first-letter {
  color: red;
  font-size: 3em;
}

Example of targeting and style elements with the "first-letter" pseudo selector.

The style is added to only the first letter, which in this case is the letter “L”.

Practice using the ::first-letter selector.

::selection

A user can select a text on a webpage by clicking and dragging the mouse over it. The ::selection selector allows you to target and style texts when a user selects it.

Example:

p::selection {
  color: red;
}

Example of targeting and style elements with the "selection" pseudo selector.

The style applies only to the part of the text that is selected (where the user clicks and drags their mouse over).

Practice using the ::selection selector.

::placeholder

All browsers have default styles for placeholder texts. But you can override them using the ::placeholder selector.

In the following example is an email input field with a placeholder text. The selector is used to override the default placeholder text selector.

<!-- HTML -->
<input type="email" placeholder="Enter your email here">
<input type="submit" value="Sign Up">
/* CSS */
::placeholder {
  color: blue;
  font-style: italic;
}

Example of targeting and style elements with the "placeholder" pseudo selector.

The placeholder text is given a blue color and italic font style.

Other pseudo-elements

At the time of writing, some of the pseudo-element selectors listed below are still experimental. Some browsers may not support their usage. You need to check browser compatibility before you use them.

  • ::marker - Used to select and style markers for list items.
  • ::file-selector-button - for targeting input elements with type="file".
  • ::grammar-error - Used to select texts which a user agent determines to include some grammatical error.
  • ::spelling-error - You can use this to add styles to words that a user agent highlights as wrongly spelled

CSS pseudo-class selectors

These are selectors that allow you to target your HTML elements based on certain conditions or the state of the elements. You will often use the CSS pseudo-class selectors to apply styles to elements in response to user actions. They are denoted by a single colon (:).

:hover

The styles you specify under this selector will apply whenever the user hovers their mouse on the targeted element.

<!-- HTML -->
<button>Hover me!</button>
/* CSS */
button:hover {
  background-color: blue;
  color: white;
}

Example of targeting and style elements with the "hover" pseudo-class selector.

The button's background color changes to blue and the text to white anytime you hover the mouse on it.

Practice using the :hover selector.

:active

You can also change the appearance of an element when it’s in an active state. Or at the moment when the user is interacting with it. For example, when a user clicks on a button.

<!-- HTML -->
<button>Click button!</button>
/* CSS */
button:active {
  transform: translateY(7px);
}

Example of targeting and style elements with the "active" pseudo-class selector.

The CSS transform property is used to push the button down when the user clicks on it.

Practice using the :active selector.

:visited

The main purpose of this selector is to make it possible to add different styles to links the user clicks or “visits”. It helps give a visual cue to users on which links on a page they’ve visited and which ones they haven’t.

Example:

<!-- HTML -->
<h1>Frontend Mentor</h1>
<a href="https://www.frontendmentor.io/challenges">
  Challenges
</a>
<a href="https://www.frontendmentor.io/solutions">
  Solutions
</a>
<a href="https://www.frontendmentor.io/articles">
  Articles
</a>
/* CSS */
a:visited {
  color: orange;
}

Example of targeting and style elements with the "visited" pseudo-class selector.

Before visiting the Frontend Mentor challenges page, all the links had the same color. However, after visiting the challenges page, the color of the link’s anchor text changes to orange. The others remain unchanged because they’re yet to be visited.

Practice using the :visited selector.

:not()

The :not pseudo-class selector allows you to target all elements that do not match a specific selector. When you use :not, the style applies to other elements but not the one you specified.

<!-- HTML -->
<a href="https://www.frontendmentor.io/challenges">
  Challenges
</a>
<a href="https://www.frontendmentor.io/solutions">
  Solutions
</a>
<a href="https://www.frontendmentor.io/articles">
  Articles
</a>
<a href="https://www.frontendmentor.io/resources">
  Resources
</a>
/* CSS */
:not([href$="resources"]) {
  color: red;
}

Example of targeting and style elements with the "not" pseudo-class selector.

The :not selector here applies the color red to all elements whose href attribute does not end with the string “resources”. Remember the “attribute ends with” selector?

Practice using the :not selector.

:has()

You can use the :has() selector to select elements that have some specified content. It takes a selector as an argument. And targets a parent element with a child element that matches the given selector.

For example, let’s say you want to target all divs that have an unsecured link with "http" instead of "https":

<!-- HTML -->
<div>
  <a href="http://unsafe-link.com">Unsafe link 1</a>
</div>
<div>
  <a href="https://safe-link.com">Safe link</a>
</div>
<section>
  <a href="http://not-safe.com">Unsafe link 2</p>
</section>
/* CSS */
div:has([href^="http://"]) {
  border: 1px solid red;
}

Example of using the CSS :has selector to target an element.

This example uses the :has() selector together with the “attribute starts with” selector. The selector targets any div that has an element with a href attribute. And checks if the href attribute starts the string "http://".

The second unsafe link also has a href with a value that starts with "http://". But the selector ignores it because it’s not inside a div.

:is()

This selector takes in a list of selectors as arguments. And adds the same styles to the specified selectors. It’s similar to the selector with the  x, y syntax. But it’s a concise and cleaner alternative. Let’s see an example:

<section>
  <p>Paragraph one</p>
</section>
<article>
  <p>Paragraph two</p>
</article>
<div>
  <p>Paragraph three</p>
</div>
<footer>
  <p>Paragraph four</p>
</footer>

The following will select all paragraphs inside the section, article, or footer elements and add the color red:

section p,
article p,
footer p {
  color: red;
}

But you get the same result with the :is() selector like so:

:is(section, article, footer) p {
  color: red;
}

Example of using the CSS :is() selector to style elements.

All the paragraphs but number 3 (the p inside the div) get a red color.

:where()

The :where() pseudo selector works almost the same way as the :is() pseudo selector. The difference lies in how they handle specificity.

  • :is() - When you use the :is() selector with a comma-separated list of selectors, it considers the specificity of each selector and chooses the most specific one as the specificity for the entire group.

  • :where() - With the :where() selector, the specificity of the entire group is always considered to be zero, regardless of the specificity of the individual selectors.

To see this difference, let’s apply both the :is() and :where() selectors on the same markup below:

<!-- HTML -->
<p id="first">First paragraph (with an ID)</p>
<p class="middle">Second paragraph (with a class)</p>
<p class="middle">Third paragraph (with a class)</p>
<p>Final paragraph (with no ID or class)</p>
/* CSS */
:is(#first, .middle) {
  color: blue;
}

.middle {
  color: red;
}

Example of CSS specificity demo with the :is() selector.

The .middle class selector below the :is() selector does not work because .middle class selector inside the :is() selector is given the same specificity level as the #first ID selector. This means it has a higher specificity than the one below.

Now, let’s see how the :where() selector differs:

:where(#first, .middle) {
  color: blue;
}

.middle {
  color: red;
}

Example of CSS specificity demo with the :where() selector.

The .middle class selector below the :where() selector works here because all selectors within :where() have a specificity of zero where it’s an ID, class, or anything else.

:nth-child selectors

These selectors target elements based on their position within their parent element. There are several nth-child selectors you can use for different scenarios.

  • :nth-child(x) - Selects the element in the x position of its parent.
  • :first-child - Selects the first child of the parent.
  • :last-child - Selects the last child of the parent.
  • :nth-child(odd) - Selects all child elements in odd number positions.
  • :nth-child(even) - Selects all child elements in even number positions.
<!-- HTML -->
<div>
  <h3>First Header</h3>
  <p>First Paragraph</p>
  <h3>Second Header</h3>
  <p>Second Paragraph</p>
  <h3>Third Header</h3>
  <p>Second Paragraph</p>
</div>
/* CSS */
div :nth-child(2) {
  background-color: blue;
  color: white;
}

Example of targeting and style elements with the "nth-child" pseudo-class selectors.

The selector div :nth-child(2) selects the first paragraph because it is the second (2) child of the div element.

The difference between the :nth-child selectors and :nth-of-type selectors is in how they count the elements within the parent container.

  • :nth-child - Selector counts all elements without regard for the element type.
  • :nth-of-type - Selector counts only elements of the same type.

:nth-of-type selectors

You can use these selectors to select elements based on their position in the parent compared to other elements of the same type.

  • :nth-of-type(x) - Selects the element of a given type that is at position x.
  • :first-of-type - Selects the first element of a given type within the parent.
  • :last-of-type - Selects the last element of a given type within the parent.
  • :nth-of-type(odd) - Selects all elements of a type that are in an odd number position.
  • :nth-of-type(even) - Selects all elements of a type that are in an even number position.
div p:nth-of-type(2) {
  background-color: blue;
  color: white;
}

Example of targeting and style elements with the "nth-of-type" pseudo-class selector.

Unlike nth-child(2) which selects the first paragraph because it’s the second child of the div, the p:nth-of-type(2) selects the second paragraph in the div.

Other pseudo-classes

  • :checked - For styling form elements like checkboxes and radio elements when a user selects (or checks) them.
  • :focus - Often used for styling input elements when a user clicks on them.
  • :valid and :invalid - Targets form elements when they are valid or invalid based on the inputs provided. These are useful for form validation.
  • :optional - For any input elements without the required attribute.

Practice CSS selectors with games

To get comfortable with CSS Selectors, you should practice using them. The following is a list of some free online resources you can use for practice. These will help you solidify your knowledge of CSS selectors in a fun and interactive way.

Conclusion

Whether you are creating a simple layout or a complex user interface, a strong understanding of CSS selectors is crucial. It will give you CSS superpowers. Not only will you write styles that meet your design objective, but also be easy to maintain.

Continue to practice and experiment with the various selectors. Doing so will help you get familiar with their nuances. And help you to use them more efficiently in your projects. You can also bookmark this article for future reference and return to it when you need a quick reminder.

Practice building projects like a pro

  • Portfolio-ready projects
  • Professional design files
  • Curate your profile
  • Unlimited solution refinement
Unlock Pro

Get all community news and our latest articles in your inbox

Join over 50,000 developers receiving updates via our newsletter. Stay up-to-date with new challenges, articles, community news, featured solutions, and handy links from across the web. We promise no spam, and you can unsubscribe at any time.