LESSON 6.2

Advanced CSS Selectors

Write powerful styles with less code

Go deeper with CSS selectors and learn how to target child elements, siblings, attributes, and states like hover to write smarter, more efficient stylesheets.

💡 The Concept

CSS has more selectors than just elements, classes, and IDs. Advanced selectors let you target elements based on their relationships, attributes, positions, and states, often without adding extra classes to your HTML. This lesson covers the most useful ones.

A Quick Refresher: CSS Selector Syntax

Before diving in, here is a quick review of the selector types you already know. If you need a refresher, see CSS Syntax: Selectors, Properties, and Values and CSS Classes and IDs.

Element Selector

An element selector targets every instance of that HTML tag on the page. Use it when you want a consistent style applied everywhere that tag appears.

p {
    color: blue;
}

Class and ID Selectors

A class selector targets any element that has a matching class attribute. An ID selector targets a single unique element with a matching id attribute. You have used both of these already.

/* Class selector */
.highlight {
    background-color: yellow;
}

/* ID selector */
#main-header {
    font-size: 2em;
}

These get you far, but advanced selectors let you target elements based on their relationships, attributes, positions, and states — all without adding extra classes or IDs to your HTML.

Descendant and Child Selectors

One of the most common advanced techniques is selecting elements based on their nesting within the HTML document tree.

Descendant Selector (Space)

The descendant selector targets any element nested inside another, no matter how deeply nested it is:

/* Targets ALL paragraphs inside main, at any depth */
main p {
    line-height: 1.6;
}

This is useful when you want to style elements differently depending on which section of the page they are in.

Direct Child Selector (>)

Sometimes you only want to target immediate children, not deeply nested descendants. The > combinator handles this:

/* Only targets list items that are direct children of .nav-list */
.nav > li {
    display: inline-block;
    margin-right: 20px;
}

This is useful for navigation menus with dropdowns, where you want to style only the top-level list items without affecting any nested lists.

Attribute Selectors

Attribute selectors let you target elements based on the presence or value of HTML attributes, which means you can style elements without adding extra classes. We will come back to this in the lesson on Styling HTML Forms with CSS.


/* Target inputs with a specific type, in this example a submit button */
input[type="submit"] {
    border: 2px solid #ccc;
    padding: 8px;
}

Pseudo-Classes

These are critical when building navigation. The order in which you declare them matters (remember the mnemonic L-V-H-A: Link, Visited, Hover, Active):

/* Unvisited link */
a:link {
    color: #0066cc;
}

/* Visited link */
a:visited {
    color: #551a8b;
}

/* Mouse hovering over the link */
a:hover {
    color: #ff6600;
    text-decoration: underline;
}

/* Link being clicked */
a:active {
    color: #cc0000;
}

We will use these in depth in the lesson on CSS Pseudo-Classes for Navigation.

Structural Pseudo-Classes

These selectors target elements based on their position within a parent. They can eliminate the need for adding first, last, or odd classes to your HTML. We will practice this in the upcoming lesson on HTML tables.


/* Every odd row — great for table striping */
tr:nth-child(odd) {
    background-color: #f9f9f9;
}

Quick Reference Cheat Sheet

/* Descendant */           div p { }
/* Child */                div > p { }
/* Adjacent sibling */     h2 + p { }
/* General sibling */      h2 ~ p { }
/* Attribute exists */     [title] { }
/* Attribute equals */     [type="text"] { }
/* Attribute starts with */[href^="https"] { }
/* Attribute ends with */  [href$=".pdf"] { }
/* Attribute contains */   [class*="btn"] { }
/* First child */          li:first-child { }
/* Last child */           li:last-child { }
/* Nth child */            tr:nth-child(odd) { }
/* Negation */             li:not(:last-child) { }
/* Before pseudo-element */p::before { content: ""; }

Frequently Asked Questions

Do I need to memorize all of these selectors?

No. Professional developers look selectors up regularly. What matters is knowing that a selector exists for a given situation so you know what to search for. The ones worth knowing by memory early on are the descendant selector, the class and ID selectors, and the link pseudo-classes (:link, :visited, :hover, :active). The rest you will pick up gradually as you use them in real projects.

What is the difference between a descendant selector and a child selector?

A descendant selector (a space between two selectors) targets any matching element nested inside the first, no matter how deep. A child selector (the > symbol) only targets elements that are direct children — one level down, not further. For example, nav a would select every link anywhere inside the nav, while nav > a would only select links that are direct children of the nav. In practice the descendant selector is more common, but the child selector becomes important when you have nested navigation menus and only want to affect the top level.

Why does the order of link pseudo-classes matter?

CSS applies rules in order, and later rules override earlier ones when they have the same specificity. The LVHA order (Link, Visited, Hover, Active) ensures that each state wins when it should. If you put :hover before :visited, a visited link will show the visited color even when you are hovering over it, because :visited comes after and overrides :hover. Following LVHA guarantees that the most specific state (active, then hover) always takes precedence over less specific ones (visited, then link).

When should I use an advanced selector instead of just adding a class?

Use a class when you want to reuse a style across multiple unrelated elements, or when the selector would otherwise be fragile or hard to read. Use an advanced selector when the relationship between elements is already clear from the HTML structure. For example, styling all links inside a nav with nav a is cleaner than adding a class to every anchor tag. A good rule of thumb: if you would need to add the same class to five or more elements, an advanced selector is probably the better approach.

Key Takeaways

CSS selectors can do much more than just target tags and classes. This lesson covered descendant selectors, attribute selectors, and pseudo-classes that give you precise control over what gets styled. Next, you will learn how to build a navigation menu using an unordered list and CSS. Navigation is on almost every website and uses many of the selectors you just learned.

Google Ads

The costs of this website are partially offset by revenue from Google Ads.

Tools of the Trade

HTML/CSS Lessons