Web Development /CSS — Styling Modern Websites / Lesson
Web Development

CSS Selectors, Combinators and Specificity

Learn how CSS selectors target HTML elements, how combinators describe relationships between elements, and how CSS specificity determines which styles are applied when multiple rules conflict.

🎯

Learning Objectives

["Understand what CSS selectors are and why they are important.","Use universal, element, class, ID and attribute selectors.","Understand grouping selectors and selector lists.","Use descendant, child, adjacent sibling and general sibling combinators.","Understand how selectors can target elements based on relationships.","Use pseudo-classes such as :hover, :focus, :first-child and :nth-child().","Understand pseudo-elements such as ::before and ::after.","Understand the concept of CSS specificity.","Compare element, class, ID and inline-style specificity.","Understand how source order affects CSS when specificity is equal.","Write cleaner selectors without unnecessary specificity.","Debug conflicting CSS rules using selector specificity."]

📖

Lesson Content

Introduction

CSS becomes much more powerful when you can precisely control which HTML elements receive a particular style. This is the job of CSS selectors.

A selector tells the browser which HTML elements a CSS rule should target. For example, you can style every paragraph, a specific class of elements, one unique element, or even elements based on their relationship with other elements.

In this lesson, you will learn how selectors work, how combinators target elements based on relationships, and how CSS specificity determines which rule wins when multiple rules apply to the same element.

1. What Is a CSS Selector?

A CSS selector identifies the HTML element or elements that a CSS rule should style.

For example:

p {
    color: blue;
}

In this example:

  • p is the selector.
  • color is the property.
  • blue is the value.

The rule tells the browser to make the text of every paragraph blue.

2. Universal Selector

The universal selector is represented by an asterisk (*). It targets every element on the page.

* {
    box-sizing: border-box;
}

This is commonly used for global CSS rules.

Another example:

* {
    margin: 0;
    padding: 0;
}

However, universal selectors should be used thoughtfully because they affect every element.

3. Element Selector

An element selector targets HTML elements by their tag name.

h1 {
    color: navy;
}

p {
    line-height: 1.7;
}

The h1 rule affects all <h1> elements, while the p rule affects all paragraphs.

4. Class Selector

A class selector targets elements that contain a particular class attribute.

HTML:

<p class="highlight">Important information</p>

CSS:

.highlight {
    background-color: yellow;
    padding: 10px;
}

The period (.) tells CSS that highlight is a class selector.

A class can be reused on multiple elements.

<h2 class="highlight">Heading</h2>
<p class="highlight">Paragraph</p>

5. ID Selector

An ID selector targets an element with a specific id.

HTML:

<section id="hero">
    Welcome to Dwallnet
</section>

CSS:

#hero {
    background-color: #0b5ed7;
    color: white;
}

The hash symbol (#) identifies an ID selector.

An ID is normally intended to identify one unique element on a page, while classes are designed to be reused.

6. Class Selector vs ID Selector

Consider this example:

.card {
    padding: 20px;
}

#featured-card {
    border: 2px solid black;
}

The .card class can be used on many cards.

The #featured-card ID is intended for one particular card.

In modern CSS development, classes are generally preferred for reusable component styling because they make styles easier to maintain.

7. Grouping Selectors

You can apply the same CSS declarations to several selectors by separating them with commas.

h1,
h2,
h3 {
    font-family: Arial, sans-serif;
}

This avoids repeating the same CSS rule several times.

Instead of writing:

h1 {
    color: navy;
}

h2 {
    color: navy;
}

h3 {
    color: navy;
}

You can write:

h1,
h2,
h3 {
    color: navy;
}

8. Attribute Selectors

Attribute selectors allow CSS to target elements based on their attributes.

For example:

input[type="text"] {
    border: 1px solid #999;
}

This targets text input fields.

Another example:

a[target="_blank"] {
    font-weight: bold;
}

This targets links that have a target attribute with the value _blank.

9. Descendant Combinator

A descendant combinator targets an element that exists somewhere inside another element.

For example:

.card p {
    color: #444;
}

This targets paragraphs located anywhere inside an element with the card class.

Example HTML:

<div class="card">
    <h2>Web Development</h2>
    <p>Learn modern web development.</p>
</div>

The paragraph receives the style because it is inside the .card element.

10. Child Combinator

The child combinator is represented by the greater-than symbol (>).

.menu > li {
    margin-bottom: 10px;
}

This targets only li elements that are direct children of .menu.

It does not target deeper nested list items.

11. Adjacent Sibling Combinator

The adjacent sibling combinator uses the plus symbol (+).

h2 + p {
    margin-top: 0;
}

This targets the first paragraph immediately following an h2.

Example:

<h2>About Dwallnet</h2>
<p>Dwallnet provides technology training.</p>

The paragraph is an adjacent sibling of the heading.

12. General Sibling Combinator

The general sibling combinator uses the tilde symbol (~).

h2 ~ p {
    color: #555;
}

This targets paragraphs that are siblings of the h2 and appear after it.

13. Pseudo-Classes

A pseudo-class allows CSS to style an element based on a particular state or position.

One of the most common examples is :hover.

button:hover {
    background-color: #084298;
}

This changes the button’s background when the pointer is placed over it.

Common Pseudo-Classes

  • :hover — when the pointer is over an element.
  • :focus — when an element has keyboard or input focus.
  • :active — while an element is being activated.
  • :first-child — targets an element that is the first child of its parent.
  • :last-child — targets an element that is the last child.
  • :nth-child() — targets elements based on their position.
  • :checked — targets selected checkboxes or radio buttons.
  • :disabled — targets disabled form controls.

14. The :nth-child() Pseudo-Class

The :nth-child() selector is useful when styling elements based on their position.

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

This targets the second list item.

You can also use expressions such as:

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

This targets even-numbered list items.

15. Pseudo-Elements

Pseudo-elements allow you to style a specific part of an element or insert generated content.

Two common pseudo-elements are:

  • ::before
  • ::after

Example:

.title::before {
    content: "★ ";
}

This adds a star before the content of the element.

Another example:

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

Pseudo-elements are useful for decorative effects, icons and visual enhancements.

16. What Is CSS Specificity?

Sometimes multiple CSS rules target the same element. When that happens, the browser needs a way to determine which rule should take priority.

This is where specificity becomes important.

Specificity is the system browsers use to determine which selector is more specific when competing CSS declarations apply to the same element.

17. Specificity Levels

A simplified specificity order is:

  1. Inline styles
  2. ID selectors
  3. Class, attribute and pseudo-class selectors
  4. Element and pseudo-element selectors

For example:

p {
    color: blue;
}

.notice {
    color: green;
}

#message {
    color: red;
}

HTML:

<p id="message" class="notice">
    Hello Dwallnet
</p>

The paragraph will be red because the ID selector is more specific than the class and element selectors.

18. Specificity Comparison

Consider:

p {
    color: blue;
}

.text {
    color: green;
}

HTML:

<p class="text">Welcome</p>

The text will be green because the class selector is more specific than the element selector.

19. Inline Styles

An inline style is written directly inside an HTML element.

<p style="color: red;">
    Important message
</p>

Inline styles generally have higher priority than normal stylesheet declarations.

However, excessive use of inline styles can make a project harder to maintain. External stylesheets and reusable classes are usually better for larger websites.

20. The !important Rule

CSS provides the !important keyword to give a declaration unusually high priority.

.message {
    color: red !important;
}

Although !important can be useful in specific situations, it should not be used as the normal solution to CSS conflicts.

Overusing it can make a stylesheet difficult to debug and maintain.

21. Specificity and Source Order

When two selectors have the same specificity, the rule that appears later in the stylesheet normally wins.

.title {
    color: blue;
}

.title {
    color: green;
}

The heading will be green because the second rule appears later.

22. Keeping Specificity Low

Good CSS is usually easier to maintain when selectors are simple.

Prefer:

.card-title {
    color: navy;
}

Instead of creating unnecessarily complicated selectors such as:

main section div article .card h2.card-title {
    color: navy;
}

The second selector creates unnecessary specificity and makes future changes harder.

23. Practical Selector Example

Consider this HTML:

<section class="courses">
    <h2>Our Courses</h2>

    <article class="course-card">
        <h3>Web Development</h3>
        <p>Learn HTML, CSS and JavaScript.</p>
    </article>

    <article class="course-card featured">
        <h3>Data Analysis</h3>
        <p>Learn how to work with data.</p>
    </article>
</section>

We can style the cards with:

.course-card {
    padding: 20px;
    border: 1px solid #ddd;
}

.course-card h3 {
    color: #0b5ed7;
}

.course-card.featured {
    border-width: 2px;
}

.course-card p {
    color: #555;
}

Notice that:

  • .course-card targets all course cards.
  • .course-card h3 targets headings inside course cards.
  • .course-card.featured targets an element containing both classes.
  • .course-card p targets paragraphs inside course cards.

24. Combining Classes

Multiple classes can be combined without a space.

.course-card.featured {
    border: 2px solid #0b5ed7;
}

This targets elements that have both course-card and featured.

Compare this with:

.course-card .featured {
    border: 2px solid #0b5ed7;
}

The second selector targets an element with the featured class that is inside an element with the course-card class.

The space between selectors changes the meaning.

25. Selector Debugging

When a CSS rule does not appear to work, check the following:

  1. Is the selector correctly written?
  2. Does the HTML actually contain the expected class or ID?
  3. Is there a spelling mistake?
  4. Is another rule more specific?
  5. Is another rule appearing later in the stylesheet?
  6. Is an inline style overriding the stylesheet?
  7. Is !important being used elsewhere?

Browser developer tools can help you inspect which CSS rules are being applied and which rules are being overridden.

26. Practical Exercise

Create a webpage containing:

  • A page heading.
  • Three course cards.
  • A navigation menu.
  • A button.
  • An input field.

Use CSS selectors to:

  1. Style all paragraphs.
  2. Style all course cards using a class.
  3. Give one course an additional featured class.
  4. Style the heading inside each course card.
  5. Change the button appearance on hover.
  6. Style the input when it receives focus.
  7. Use :nth-child() to style one of the cards.
  8. Use a child combinator to target direct menu items.

27. Code Challenge

The following code contains CSS selector problems:

<div class="courses">
    <h2>Courses</h2>

    <div class="course">
        <h3>Web Development</h3>
        <p>Learn web development.</p>
    </div>

    <div class="course featured">
        <h3>Data Analysis</h3>
        <p>Learn data analysis.</p>
    </div>
</div>

Write CSS that:

  1. Changes all course headings to blue.
  2. Changes only the featured course border.
  3. Changes paragraphs inside courses to a darker gray.
  4. Adds a hover effect to each course.
  5. Styles the second course differently using :nth-child() or an appropriate selector.

28. Lesson Summary

CSS selectors determine which HTML elements receive styles. Element selectors target tags, class selectors target reusable groups, and ID selectors target unique elements.

Combinators allow selectors to describe relationships between elements. Descendant, child, adjacent sibling and general sibling combinators give developers precise control over page structure.

Pseudo-classes allow styling based on states or positions, while pseudo-elements can style specific parts of an element or generate decorative content.

Specificity determines which competing CSS rule takes priority. Understanding specificity helps developers avoid unexpected styling conflicts and write cleaner, more maintainable CSS.

💻

Code Example

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Dwallnet CSS Selectors</title>

    <style>
        * {
            box-sizing: border-box;
        }

        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 40px;
            background: #f5f7fb;
        }

        .courses {
            max-width: 900px;
            margin: auto;
        }

        .courses > h2 {
            color: #0b5ed7;
        }

        .course-card {
            background: white;
            padding: 24px;
            margin-bottom: 20px;
            border: 1px solid #ddd;
            border-radius: 10px;
            transition: transform 0.2s ease, box-shadow 0.2s ease;
        }

        .course-card h3 {
            color: #0b5ed7;
        }

        .course-card p {
            color: #555;
            line-height: 1.6;
        }

        .course-card:hover {
            transform: translateY(-3px);
            box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08);
        }

        .course-card.featured {
            border: 2px solid #0b5ed7;
        }

        .course-card:nth-child(3) {
            background: #eef5ff;
        }

        button {
            padding: 12px 20px;
            border: none;
            border-radius: 6px;
            background: #0b5ed7;
            color: white;
            cursor: pointer;
        }

        button:hover {
            background: #084298;
        }

        input {
            display: block;
            width: 100%;
            max-width: 400px;
            margin-top: 20px;
            padding: 12px;
            border: 1px solid #bbb;
            border-radius: 6px;
        }

        input:focus {
            outline: 2px solid #0b5ed7;
            border-color: #0b5ed7;
        }
    </style>
</head>

<body>

    <main class="courses">

        <h2>Our Courses</h2>

        <div class="course-card">
            <h3>Web Development</h3>
            <p>Learn HTML, CSS and JavaScript to build modern websites.</p>
            <button>Explore Course</button>
        </div>

        <div class="course-card featured">
            <h3>Data Analysis</h3>
            <p>Learn how to collect, clean, analyze and present data.</p>
            <button>Explore Course</button>
        </div>

        <div class="course-card">
            <h3>Cyber Security</h3>
            <p>Learn the fundamentals of protecting systems and information.</p>
            <button>Explore Course</button>
        </div>

        <input type="text" placeholder="Enter your name">

    </main>

</body>
</html>
⭐

Key Takeaways

["CSS selectors determine which HTML elements receive styles.","Element selectors target HTML tags.","Class selectors are reusable and are commonly used for component styling.","ID selectors target specific elements and have higher specificity than classes.","Attribute selectors can target elements based on their HTML attributes.","Combinators describe relationships between HTML elements.","The descendant combinator uses a space.","The child combinator uses >.","The adjacent sibling combinator uses +.","The general sibling combinator uses ~.","Pseudo-classes style elements based on state or position.","Pseudo-elements such as ::before and ::after can create decorative content.","Specificity determines which competing CSS declaration has priority.","When specificity is equal, the later rule normally wins.","Simple selectors are generally easier to maintain than unnecessarily complex selectors.","Avoid relying heavily on !important to solve CSS conflicts."]

Enjoying this lesson?

Sign in to your Dwallnet Academy student account to track your learning progress and mark lessons as complete.

Sign In to Track Progress