CSS Selectors Explained With Examples: A Beginner's Guide bishal-biswas.github.io | Bishal Biswas

CSS Selectors Explained With Examples: A Beginner's Guide

Table of Content

Introduction

When I started learning CSS, one of the first things I had to understand was how CSS knows which HTML elements should receive a particular style.

For example, suppose I have this HTML:

<h1>My Website</h1>
<p>Welcome to my website.</p>
<p>This is another paragraph.</p>

Now I want to make only the paragraphs blue.

How does CSS know that I want to target the <p> elements?

This is where CSS selectors come in.

A CSS selector tells the browser which HTML elements I want to select and style.

For example:

p {
    color: blue;
}

Here, p is the selector.

The browser finds all <p> elements and applies the color: blue rule to them.

In this article, I will explain the most important CSS selectors with simple examples.


What Is a CSS Selector?

A CSS selector is a pattern used to select HTML elements that I want to style.

A basic CSS rule looks like this:

selector {
    property: value;
}

For example:

p {
    color: blue;
    font-size: 18px;
}

Here:

  • p is the selector
  • color is a CSS property
  • blue is the property value
  • font-size is another property
  • 18px is its value

The browser applies these styles to all <p> elements.


1. Element Selector

The element selector is probably the easiest selector to understand.

I simply write the HTML element name.

For example:

p {
    color: blue;
}

This selects every <p> element.

HTML:

<p>Hello World</p>
<p>Welcome to my website.</p>
<p>I am learning CSS.</p>

All three paragraphs will become blue.

I can also target other HTML elements:

h1 {
    font-size: 40px;
}

button {
    background-color: black;
}

img {
    width: 300px;
}

This is useful when I want to apply the same style to every element of a particular type.


2. Class Selector

The class selector is one of the selectors I use most often in real projects.

First, I add a class to an HTML element.

<p class="highlight">This paragraph is important.</p>
<p>This paragraph is normal.</p>
<p class="highlight">This paragraph is also important.</p>

Then I use a dot (.) before the class name in CSS.

.highlight {
    color: red;
    font-weight: bold;
}

Only the elements having the highlight class will receive these styles.

The class selector is very useful because I can use the same class on multiple elements.

For example:

<h2 class="highlight">Important Heading</h2>
<p class="highlight">Important paragraph.</p>
<button class="highlight">Important Button</button>

All three elements can be styled using:

.highlight {
    color: red;
}

A common mistake

I sometimes see beginners write:

highlight {
    color: red;
}

That is not a class selector.

The correct syntax is:

.highlight {
    color: red;
}

The dot tells CSS that highlight is a class.


3. ID Selector

An ID selector targets an element based on its id attribute.

HTML:

<h1 id="main-heading">My Website</h1>

CSS:

#main-heading {
    color: green;
}

The # symbol tells CSS that I am selecting an ID.

For example:

<p id="description">
    This is my website.
</p>
#description {
    font-size: 20px;
}

Class vs ID

The main difference is how I generally use them.

A class can be reused:

<p class="text">One</p>
<p class="text">Two</p>
<p class="text">Three</p>

An ID is intended to identify one particular element within a page:

<h1 id="main-heading">My Website</h1>

For normal styling, I generally prefer classes because they are reusable.


4. Universal Selector

The universal selector selects every element on the page.

It is represented by an asterisk (*).

* {
    margin: 0;
    padding: 0;
}

This applies the styles to all elements.

A common use is resetting default browser spacing:

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

I often use a variation of this in projects because browsers have their own default styles.


5. Grouping Selector

Sometimes I want to apply the same styles to several different elements.

Instead of writing:

h1 {
    color: blue;
}

h2 {
    color: blue;
}

h3 {
    color: blue;
}

I can group them:

h1, h2, h3 {
    color: blue;
}

I simply separate the selectors with commas.

This makes the CSS shorter and easier to maintain.


6. Descendant Selector

The descendant selector allows me to select elements that exist inside another element.

For example:

<div class="card">
    <h2>Product</h2>
    <p>This is a product.</p>
</div>

I can target the paragraph inside .card like this:

.card p {
    color: gray;
}

Here:

.card p

means:

Select any <p> element that exists somewhere inside an element with the card class.

It does not have to be a direct child.

For example:

<div class="card">
    <section>
        <p>This will also be selected.</p>
    </section>
</div>

The selector still works:

.card p {
    color: gray;
}

7. Child Selector

The child selector is slightly different from the descendant selector.

It uses the > symbol.

.card > p {
    color: red;
}

This selects only <p> elements that are direct children of .card.

For example:

<div class="card">
    <p>This is selected.</p>

    <section>
        <p>This is not selected.</p>
    </section>
</div>

The first paragraph is a direct child of .card.

The second paragraph is inside <section>, so it is not a direct child.

Therefore:

.card > p

selects only the first paragraph.

This is an important difference:

.card p

means any descendant.

.card > p

means direct child only.


8. Attribute Selector

CSS can also select elements based on their attributes.

For example:

<input type="text">
<input type="email">
<input type="password">

I can select all elements having a type attribute with:

input[type] {
    border: 1px solid gray;
}

I can also target a specific attribute value:

input[type="email"] {
    border-color: blue;
}

Now only the email input is selected.

Another example:

<a href="https://example.com">Example</a>
<a href="/about">About</a>

I can select links that start with https:

a[href^="https"] {
    color: green;
}

Attribute selectors become particularly useful when I need to style elements based on their HTML attributes without adding extra classes.


9. Adjacent Sibling Selector

The adjacent sibling selector uses the + symbol.

It selects an element that comes immediately after another element.

For example:

<h2>Heading</h2>
<p>This paragraph comes immediately after the heading.</p>
<p>This is another paragraph.</p>

CSS:

h2 + p {
    color: blue;
}

Only the first paragraph is selected because it immediately follows the <h2>.

This can be useful when I want to style something based on what comes directly before it.


10. General Sibling Selector

The general sibling selector uses the ~ symbol.

It selects sibling elements that appear after another element.

For example:

<h2>Heading</h2>
<p>Paragraph One</p>
<p>Paragraph Two</p>
<p>Paragraph Three</p>

CSS:

h2 ~ p {
    color: blue;
}

All three paragraphs can be selected because they are siblings that appear after the <h2>.

The important difference is:

h2 + p

selects the immediately following sibling.

h2 ~ p

selects matching siblings that appear later.


11. Pseudo-Classes

Pseudo-classes allow me to select an element based on its state or position.

They usually start with a colon (:).

One of the most common examples is :hover.

button:hover {
    background-color: black;
    color: white;
}

This style is applied when I move the mouse over the button.

HTML:

<button>Hover Me</button>

There are many useful pseudo-classes.

:hover

a:hover {
    color: red;
}

Applies when the mouse pointer is over the element.

:focus

input:focus {
    border-color: blue;
}

Applies when an input receives focus.

:first-child

li:first-child {
    font-weight: bold;
}

Selects an element if it is the first child of its parent.

:last-child

li:last-child {
    font-weight: bold;
}

Selects the last child.

:nth-child()

This is particularly useful when I need to select elements based on their position.

li:nth-child(2) {
    color: red;
}

This selects the second <li>.

I can also select every second item:

li:nth-child(even) {
    background-color: lightgray;
}

Or odd items:

li:nth-child(odd) {
    background-color: white;
}

Pseudo-classes are extremely useful for interactive interfaces and lists.


12. Pseudo-Elements

Pseudo-elements allow me to style a specific part of an element.

They generally use two colons (::).

For example:

p::first-letter {
    font-size: 30px;
}

This makes the first letter of each paragraph larger.

Another example is ::before.

.note::before {
    content: "Note: ";
    font-weight: bold;
}

HTML:

<p class="note">Always test your code.</p>

The generated result will visually contain:

Note: Always test your code.

Another commonly used pseudo-element is ::after.

.link::after {
    content: " →";
}

Pseudo-elements are useful for decorative content and styling parts of an element without adding extra HTML.


13. The :not() Selector

Sometimes I want to select everything except a particular element.

The :not() pseudo-class is useful for this.

For example:

p:not(.special) {
    color: gray;
}

HTML:

<p>Normal paragraph</p>
<p class="special">Special paragraph</p>
<p>Another normal paragraph</p>

The normal paragraphs are selected, but .special is excluded.

This can help me avoid adding unnecessary CSS classes.


14. The :first-of-type and :last-of-type Selectors

These selectors allow me to select the first or last element of a particular type.

For example:

p:first-of-type {
    color: blue;
}

This selects the first <p> among its siblings.

Similarly:

p:last-of-type {
    color: red;
}

selects the last <p>.

These can be useful when working with mixed HTML elements.


15. Combining Multiple Selectors

I can combine selectors to make my CSS more specific.

For example:

<p class="text important">Important text</p>

I can target an element having both classes:

.text.important {
    color: red;
}

Notice that there is no space between the class names.

This:

.text.important

means an element that has both classes.

But this:

.text .important

means an element with .important inside an element with .text.

That small space changes the meaning.


16. Selector Specificity

One topic I recommend learning along with selectors is CSS specificity.

Sometimes I write multiple CSS rules that target the same element.

For example:

p {
    color: blue;
}

.text {
    color: green;
}

#special {
    color: red;
}

And the HTML is:

<p class="text" id="special">Hello</p>

All three selectors match the paragraph.

So which color wins?

The answer is based partly on specificity.

A simplified way I remember the order is:

Element < Class < ID

So:

p

has lower specificity than:

.text

and .text has lower specificity than:

#special

Therefore, the ID rule normally wins here.

#special {
    color: red;
}

Specificity becomes very important when CSS gets larger.


17. CSS Selector Cheat Sheet

Here is the quick reference I use when revising CSS selectors.

Selector Meaning Example
* Select everything *
p Select all <p> elements p
.box Select elements with class .box
#header Select element with ID #header
h1, p Select multiple elements h1, p
.card p Select descendants .card p
.card > p Select direct children .card > p
input[type="text"] Select by attribute input[type="text"]
h2 + p Immediate sibling h2 + p
h2 ~ p General sibling h2 ~ p
a:hover Hover state a:hover
input:focus Focus state input:focus
li:first-child First child li:first-child
li:last-child Last child li:last-child
li:nth-child(2) Second child li:nth-child(2)
p::first-letter First letter p::first-letter
.box::before Content before element .box::before
.box::after Content after element .box::after
p:not(.special) Exclude matching elements p:not(.special)

A Practical Example

Let me put several selectors together in one small example.

HTML

<div class="card">
    <h2>My Product</h2>

    <p class="description">
        This is a product description.
    </p>

    <ul>
        <li>Feature One</li>
        <li>Feature Two</li>
        <li>Feature Three</li>
    </ul>

    <button>Buy Now</button>
</div>

CSS

.card {
    padding: 20px;
}

.card h2 {
    color: blue;
}

.card > .description {
    color: gray;
}

.card li:first-child {
    font-weight: bold;
}

.card li:nth-child(even) {
    background-color: lightgray;
}

.card button:hover {
    background-color: black;
    color: white;
}

Here I am using several concepts:

  • .card selects the card
  • .card h2 selects the heading inside the card
  • .card > .description selects the direct child description
  • li:first-child selects the first list item
  • li:nth-child(even) selects even list items
  • button:hover changes the button when I hover over it

Once I understand selectors, CSS becomes much easier because I can precisely tell the browser what I want to style.


Common CSS Selector Mistakes

1. Forgetting the dot for classes

Wrong:

button {
    color: red;
}

If I intended to target .button, this is not correct.

Correct:

.button {
    color: red;
}

2. Forgetting the # for IDs

Wrong:

header {
    color: red;
}

If I want to target:

<div id="header"></div>

I need:

#header {
    color: red;
}

3. Confusing descendant and child selectors

These are not the same:

.card p

and:

.card > p

The first can select paragraphs at any depth inside .card.

The second selects only direct children.


4. Using IDs everywhere

I generally avoid creating a separate ID for every element just to style it.

For reusable styles, classes are usually a better choice:

.card {
    border: 1px solid gray;
}

Instead of:

#card1 {
    border: 1px solid gray;
}

#card2 {
    border: 1px solid gray;
}

Classes make the CSS much easier to reuse.


How I Recommend Learning CSS Selectors

When I teach or learn CSS, I don’t recommend memorizing every selector at once.

I would learn them in this order:

Beginner level

Start with:

Element
Class
ID
Universal
Grouping

Then learn:

Descendant
Child

After that:

Attribute selectors

Then move to:

:hover
:focus
:first-child
:last-child
:nth-child()

Finally, learn:

::before
::after
Sibling selectors
:not()
Specificity

This progression makes the topic much easier.


Final Thoughts

CSS selectors are one of the foundations of CSS.

When I first started working with CSS, selectors looked simple, but I quickly realized that understanding them properly makes a huge difference when building real websites.

The selectors I use most frequently are:

.element
.class
#id
.parent .child
.parent > .child
:hover
:focus
:nth-child()
::before
::after

Once these become comfortable, I can start writing much more precise CSS without adding unnecessary classes or HTML elements.

My advice is simple: don’t just read about selectors. Create a small HTML page and experiment with each selector.

Change the HTML structure, change the selector, and see what gets selected.

That hands-on practice is what helped me understand CSS much faster.

CSS Flexbox and CSS Grid Complete Guide for BeginnersArticlesHTML Semantic Elements Explained: A Beginner's Guide