Question

What the CSS `~` General Sibling Selector Means

csscss-selectors

Question

I found this CSS selector and want to understand what the ~ character means:

.copy.check:checked ~ .content {
}

What does the ~ selector do in CSS, and how does it affect which elements are matched?

Short Answer

By the end of this page, you will understand that ~ in CSS is the general sibling combinator. It selects elements that share the same parent and appear after another matching element. You will also see how it differs from other selectors like > and +, and how it is commonly used for UI states such as toggles, checkboxes, and show/hide interactions.

Concept

In CSS, the ~ symbol is called the general sibling combinator.

It is used to select an element that:

  • shares the same parent as another element
  • appears later in the HTML
  • matches the selector on the right side of ~

For example:

A ~ B

This means:

  • find an element matching A
  • then select every sibling matching B
  • but only if those B elements come after A

So in your example:

.copy.check:checked ~ .content {
}

CSS is saying:

  • find an element with classes copy and check
  • that element must also be :checked
  • then select any later sibling with the class .content

This matters because CSS often styles elements based on the state of nearby elements. A common pattern is a checked checkbox controlling the appearance of a content panel, menu, or accordion section.

The ~ selector is useful because it lets one element influence later siblings without JavaScript, as long as the HTML structure supports it.

Mental Model

Think of siblings in CSS like items in the same row of seats.

  • They must be in the same row = same parent element
  • ~ means “look to the right”
  • It can match one or many siblings after the starting element

So if one person in a row raises their hand (:checked), ~ lets you affect people sitting later in the same row.

It does not:

  • look backward
  • jump into children
  • match elements with different parents

A simple way to remember it:

  • + = the next sibling only
  • ~ = any later sibling
Take Quiz

Syntax and Examples

The core syntax is:

A ~ B {
  /* styles */
}

This selects all B elements that:

  • are siblings of A
  • come after A
  • share the same parent

Basic example

<div>
  <p class="note">First paragraph</p>
  <p>Second paragraph</p>
  <p>Third paragraph</p>
</div>
.note ~ p {
  color: blue;
}

What gets selected?

  • The second paragraph
  • The third paragraph

The first paragraph is not selected, because it is the element on the left side of ~, not the right side.

Example with :checked

<div>
  <input type="checkbox" class="copy check" checked>
  <div class="content">Visible content</div>
</div>
.copy.check:checked ~ .content {
  display: block;
}

This means:

  • if the checkbox is checked
  • then any later sibling with class content gets the styles

Example with hidden content toggle

<div class="panel">
  <input type="checkbox" id="toggle">
  <label for="toggle">Show details</label>
  <div class="content">Extra details here</div>
</div>
.content {
  display: none;
}

#toggle:checked ~ .content {
  display: block;
}

When the checkbox is checked, the .content element becomes visible.

Step by Step Execution

Consider this HTML and CSS:

<div class="box">
  <input type="checkbox" id="menu-toggle" checked>
  <label for="menu-toggle">Open menu</label>
  <div class="menu">Menu content</div>
</div>
.menu {
  display: none;
}

#menu-toggle:checked ~ .menu {
  display: block;
}

Here is what happens step by step:

  1. CSS first looks for an element matching #menu-toggle:checked.
  2. It finds the checkbox with id="menu-toggle".
  3. Because the checkbox is checked, the left side of the selector matches.
  4. CSS then looks for siblings after that checkbox.
  5. It checks whether any of those later siblings match .menu.
  6. The <div class="menu"> does match .menu.
  7. The rule is applied, so display: block overrides display: none.

Important detail

The <label> is ignored by the selector because it does not match .menu.

Also important

If .menu appeared before the checkbox in the HTML, the selector would not work:

<div class="box">
  <div class="menu">Menu content</div>
  <input type="checkbox" id="menu-toggle" checked>
</div>

In this case, #menu-toggle:checked ~ .menu matches nothing, because ~ only works with later siblings.

Real World Use Cases

The ~ selector appears often in UI code where one element controls the style of another nearby element.

Common uses

  • Checkbox-based show/hide panels
  • Accordion sections
  • Dropdown menus without JavaScript
  • Mobile navigation toggles
  • Form hints or validation messages
  • Theme or preference switches

Example: show a help message

<div class="field">
  <input type="checkbox" id="help-toggle">
  <label for="help-toggle">Show help</label>
  <p class="help">Your password should be at least 8 characters.</p>
</div>
.help {
  display: none;
}

#help-toggle:checked ~ .help {
  display: block;
}

Example: style later form elements

input.error ~ .message {
  color: red;
}

If an input has class error, any later sibling .message can be styled as an error message.

Example: menu toggle pattern

Developers sometimes place a hidden checkbox before a menu and use :checked ~ .menu to open or close it with pure CSS.

Take Quiz

Real Codebase Usage

In real projects, developers use ~ when HTML structure makes sibling-based styling convenient.

Common patterns

State-driven UI

A stateful element such as a checkbox, radio button, or input controls later siblings:

.sidebar-toggle:checked ~ .sidebar {
  transform: translateX(0);
}

Conditional messages

A validation state on one element affects a related message block:

input:invalid ~ .error-message {
  display: block;
}

Progressive enhancement

Even when JavaScript exists, CSS sibling selectors can handle simple visual state changes cleanly.

Why developers like it

  • reduces simple JavaScript-driven toggles
  • keeps state-based styling in CSS
  • works well for small interactive components

Limits in real code

Developers must design the HTML structure carefully. If the controlled element is not a later sibling with the same parent, ~ will not help.

Because of that, teams often combine ~ with:

  • utility classes
  • component-based markup
  • hidden checkboxes for toggle state
  • semantic labels for accessible interactions

Common Mistakes

Here are the most common beginner mistakes with ~.

1. Expecting it to match previous siblings

Broken example:

<div>
  <div class="content"></div>
  <input type="checkbox" id="toggle" checked>
</div>
#toggle:checked ~ .content {
  display: block;
}

This does not work because .content comes before #toggle.

Fix

Place .content after the checkbox, or use a different structure.

2. Forgetting that both elements need the same parent

Broken example:

<div>
  <input type="checkbox" id="toggle" checked>
</div>

<section>
  <div class="content"></div>
</section>
#toggle:checked ~ .content {
  display: block;
}

This fails because the checkbox and .content are not siblings.

Fix

Make sure both are under the same parent.

3. Confusing ~ with +

A + B

matches only the immediately next sibling.

A ~ B

matches any later matching sibling.

4. Thinking it selects children

Broken expectation:

.parent ~ .child

This does not mean “a child inside .parent.” It means “a sibling after .parent.”

Fix

Use descendant selectors for children, such as:

.parent .child

5. Forgetting that :checked only applies to checkable elements

:checked works with elements like:

  • checkbox inputs
  • radio inputs
  • some option elements

It does not apply to ordinary <div> elements.

Comparisons

Here is how ~ compares to related CSS combinators.

SelectorMeaningMust be same parent?Must come after?Matches how many?
A Bdescendant selectorNoNoany matching descendants
A > Bchild selectorYes, direct childNodirect children only
A + Badjacent sibling selectorYesYesnext sibling only
A ~ Bgeneral sibling selectorYesYesall later matching siblings

Example comparison

<div>
  <h2 class="title">Title</h2>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
  <span>Span</span>
</div>
.title + p {
  color: red;
}

Only Paragraph 1 is selected.

.title ~ p {
  color: blue;
}

Both Paragraph 1 and Paragraph 2 are selected.

When to use which

  • Use + when you need the very next sibling.
  • Use ~ when the target may be several positions later.
  • Use > when selecting direct children.
  • Use a space selector when selecting nested descendants.
Take Quiz

Cheat Sheet

A ~ B {
  /* styles for later sibling(s) B */
}

Rules

  • ~ is the general sibling combinator
  • B must come after A in the HTML
  • A and B must share the same parent
  • it can match multiple later siblings
  • it does not match previous siblings
  • it does not match children unless they are also siblings in the right place

Common example

input:checked ~ .content {
  display: block;
}

Quick comparison

  • A + B → next sibling only
  • A ~ B → any later matching sibling
  • A > B → direct child
  • A B → any descendant

Easy memory trick

  • + = next one
  • ~ = later ones

FAQ

What is the ~ symbol called in CSS?

It is called the general sibling combinator.

What does A ~ B mean in CSS?

It selects every B element that is a sibling of A, comes after A, and has the same parent.

What is the difference between + and ~ in CSS?

+ selects only the immediately next sibling. ~ selects any matching siblings that appear later.

Does the ~ selector work on previous siblings?

No. It only works on siblings that come after the first element in the HTML.

Do the elements need the same parent for ~ to work?

Yes. The two elements must be siblings under the same parent element.

Why is :checked ~ .content common in CSS?

It is often used to show, hide, or restyle content based on a checkbox or radio button state without JavaScript.

Can ~ select multiple elements?

Yes. If several later siblings match the selector on the right, all of them can be selected.

Can I use ~ with classes, IDs, and pseudo-classes?

Yes. You can combine it with normal selectors like classes, IDs, attributes, and pseudo-classes such as :checked or :focus.

Take Quiz

Mini Project

Description

Build a simple FAQ toggle using only HTML and CSS. This project demonstrates how the ~ general sibling selector can reveal content when a checkbox is checked. It is a practical example of state-based styling without JavaScript.

Goal

Create a toggleable answer panel that appears when the user checks a checkbox.

Requirements

  • Add a checkbox input to control the panel state.
  • Add a label that the user can click.
  • Add a content block that starts hidden.
  • Use the :checked ~ .content pattern to show the content.
  • Keep the checkbox, label, and content under the same parent element.
Take Quiz

Keep learning

Related questions

View more