AD JB Toolbox 01 EN

CSS Tutorial / CSS Combinators and Pseudo-Classes

Combinators select elements by their relationships in the HTML structure, while pseudo-classes select states or structural conditions. A child selector differs from a descendant selector, and :first-child refers to the first child element rather than the first element of a particular type.

Read parent, child, descendant, and sibling relationships

In the following structure, section is the parent of h2, paragraph A, div, and paragraph C. Paragraph B is a child of div, which is a descendant of section. A and C are siblings because they have the same parents, but A and B are not siblings because they have different parents. The HTML structure is more important than whether it looks close on the screen.

<section class="garden">
  <h2>Visitor Information</h2>
  <p>A: Operating hours</p>
  <div>
    <p>B: Greenhouse Guide</p>
  </div>
  <p>C: What you need</p>
</section>
section.garden
├─ h2
├─ p  ← A
├─ div
│  └─ p  ← B
└─ p  ← C
relationship notation selector Paragraph selected Paragraph not selected
space: descendant .garden p A, B, C p outside this section
>: direct child .garden > p A, C B takes the div one step further
+: the next sibling h2 + p A B has different parents and there is a div before C.
~: subsequent sibling h2 ~ p A, C B has a different parent than h2.

A combinator normally targets the element on its right. h2 + p styles the p immediately following an h2 as a sibling. Whitespace text nodes from indentation or line breaks do not interrupt this element-sibling relationship. For further detail, see Basic CSS Selectors: Type, Class, ID, and Attributes.

Compare descendant and child selectors

.garden p { color: #087f5b; }
.garden > p { border-left: 4px solid #087f5b; padding-left: 12px; }

The first rule makes all p in garden green. It contains B even if there is a div in the middle. The second rule adds a left border and margin only to the direct children A and C. Since color and border-left are different properties, A and C can have both green and border.

A descendant selector suits shared paragraph styling throughout a section. A direct-child selector can exclude paragraphs inside nested cards. Structure changes affect these matches; avoid chaining unnecessary child combinators that make the stylesheet depend on a rigid depth. See MDN: Combinators.

Compare next and subsequent siblings

h2 + p { background-color: #fff4cc; }
h2 ~ p { font-style: italic; }

The first rule gives paragraph A, the next element sibling of the heading, a yellow background. The second italicizes A and C because both are later p siblings of h2. B has a different parent and therefore does not match. Neither sibling combinator selects an earlier sibling.

If you insert <div>Additional notice</div> between h2 and A, the yellow background will disappear because A is no longer the immediate sibling. However, the condition that it follows h2 within the same parent holds, so the slant remains. Seeing this difference will save you from having to memorize + and ~ as “similar selectors.”

Select states and positions with pseudo-classes

a:hover { background-color: #fff4cc; }
a:focus-visible { outline: 3px solid #1d4ed8; outline-offset: 3px; }
.plants li:first-child { font-weight: bold; }
.plants li:nth-child(odd) { background-color: #e9f7ef; }

:hover selects the state in which the pointer is raised. :focus-visible selects the state in which the browser determines that focus display is necessary, and is useful for checking when moving through tabs on the keyboard. :focus selects the focused state itself, so the meaning of the two is not completely the same. This example specifies an additional outline without removing the default focus indicator. You can continue practicing how to distinguish color and focus by state in an actual link in CSS Link States and Visible Keyboard Focus.

When you hover your mouse over the link, the background turns yellow, and when you tab to the link, a blue outline appears. In a touch environment, hover cannot be guaranteed to be always experienced by the user. Leave essential information, such as operating hours or link names, still readable by default.

:first-child selects if it is the first child element of its parent. :nth-child(odd) selects cases where the order of child elements is odd, such as 1, 3, or 5. The list of plants above only has li, so mint number 1 becomes bold and creates a background for items 1 and 3. If you use even instead of odd, numbers 2 and 4 are the targets.

p:first-child means “a p element that is its parent's first child,” rather than “the first p.” The first child of section in this example is h2, so .garden > p:first-child matches no paragraph. nth-child counts all sibling elements, not just elements with the same tag. Use a condition such as nth-of-type when you need positions within one element type. The MDN pseudo-class reference explains these state and position conditions.

Run the complete example

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Small Garden</title>
  <style>
body { margin: 24px; font-family: sans-serif; line-height: 1.7; }
    .garden p { color: #087f5b; }
    .garden > p { border-left: 4px solid #087f5b; padding-left: 12px; }
    h2 + p { background-color: #fff4cc; }
    h2 ~ p { font-style: italic; }
    .plants li:first-child { font-weight: bold; }
    .plants li:nth-child(odd) { background-color: #e9f7ef; }
    a:hover { background-color: #fff4cc; }
    a:focus-visible { outline: 3px solid #1d4ed8; outline-offset: 3px; }
  </style>
</head>
<body>
<h1>Small Garden</h1>
  <section class="garden">
    <h2>Visitor Information</h2>
    <p>A: We open at 9am every day.</p>
    <div>
      <p>B: Please observe quietly in the greenhouse.</p>
    </div>
    <p>C: Bring a water bottle and comfortable shoes.</p>
  </section>
  <ul class="plants">
    <li>1: Mint</li>
    <li>2: Basil</li>
    <li>3: Rosemary</li>
    <li>4: Time</li>
  </ul>
  <a href="#contact">Go to the contact section</a>
  <h2 id="contact">Contact</h2>
  <p>Ask at the information desk.</p>
</body>
</html>

When you save and run, A·B·C are green, and only A·C has a left border. A has a yellow background, and A·C has italic text. The plant list has the first item in bold and the odd-numbered items have a light background. Check the links using the mouse and keyboard respectively. The letters A~C in front of paragraphs are letters written directly in the text to compare selection results.

Change the structure and test each condition

  1. Add one div between h2 and A. Verify that only the background of A disappears, leaving the italics and borders. After practicing, delete the added div.
  2. Make B a direct child of section by removing only the div tag surrounding paragraph B. Make sure B also has a left border and slant. Only A is still correct in the + condition. After confirmation, restore the div.
  3. Replace :nth-child(odd) with :nth-child(even). Check that the list background moves from numbers 1 and 3 to numbers 2 and 4, and that the bold letters for first-child still remain in number 1.
  4. Put your mouse away, click inside the page and tab to the link. Make sure the focus outline is visible and you can move to the contact section with Enter. If the browser address bar has focus, it returns to the page first.

Please check each condition separately. Changing only the color value to expand the selection range or adding hover to the keyboard focus issue will not solve the cause. In developer tools, you can compare with the ability to force the state to be turned on, but in the end, it is better to check the results visible to the user through actual tab movement and mouse movements.

More in This Category
CSS Tutorial / CSS Width, Height, min/max Limits, and box-sizing

CSS Tutorial / CSS Width, Height, min/max Limits, and box-sizing

Compare content-box and border-box sizing, percentage heights, fluid width limits, and the consequences of fixed heights for growing text.

CSS Tutorial / CSS Tables: Borders, Sizing, and table-layout

CSS Tutorial / CSS Tables: Borders, Sizing, and table-layout

Style semantic tables, compare automatic and fixed layout with long content, and provide horizontal scrolling when a table needs more space.

CSS Tutorial / CSS Container Queries for Reusable Components

CSS Tutorial / CSS Container Queries for Reusable Components

Reuse one card in main content and sidebar containers, compare nearest and named containers, and verify the baseline layout when a query does not apply.

CSS Tutorial / CSS Keyframe Animations, Fill Modes, and Pausing

CSS Tutorial / CSS Keyframe Animations, Fill Modes, and Pausing

Build a complete animation example, compare end states and delays, pause decorative motion, and check a prefers-reduced-motion alternative.

CSS Tutorial / CSS Colors and Units: px, em, rem, and Percentages

CSS Tutorial / CSS Colors and Units: px, em, rem, and Percentages

Compare equivalent color formats and practical sizing examples, including nested em values, rem, percentages, and unitless line height.

CSS Tutorial / CSS Overflow, Long Text Wrapping, and Ellipsis

CSS Tutorial / CSS Overflow, Long Text Wrapping, and Ellipsis

Compare scrolling, clipping, long-word wrapping, and single-line ellipsis, including keyboard access and minimum-size issues in layout containers.

CSS Tutorial / CSS Fonts, Font Sizes, and Line Height

CSS Tutorial / CSS Fonts, Font Sizes, and Line Height

Build a readable font stack, compare line-height inheritance, and use browser tools to identify the fonts actually rendering your text.

CSS Tutorial / CSS Media Queries and Content-Based Breakpoints

CSS Tutorial / CSS Media Queries and Content-Based Breakpoints

Calculate a practical layout breakpoint, compare overlapping min/max conditions, and test the widths immediately around each threshold.

CSS Tutorial / Check Responsive CSS with Width, Zoom, and Keyboard Tests

CSS Tutorial / Check Responsive CSS with Width, Zoom, and Keyboard Tests

Follow a repeatable browser checklist, test breakpoint boundaries and longer text, and record layout problems before changing CSS rules.

CSS Tutorial / The CSS Box Model: Content, Padding, Border, and Margin

CSS Tutorial / The CSS Box Model: Content, Padding, Border, and Margin

Measure the four box areas, compare padding shorthand and vertical margin collapse, and inspect the resulting dimensions in DevTools.