Syntax
element { }
.class { }
#id { }
* { }Examples
The Four Basic Types
Type, class, ID, and universal selectors.
p { color: #333; } /* every <p> element */
.highlight { background: yellow; } /* every element with class="highlight" */
#main-header { font-size: 2rem; } /* the single element with id="main-header" */
* { box-sizing: border-box; } /* every element on the page */Combining Selectors
Selectors can be combined for more specific targeting.
p.intro { font-weight: bold; } /* only <p> elements that ALSO have class="intro" */
.card.featured { border: 2px solid gold; } /* elements with BOTH classes */Parameters and values
- element (type selector): Matches all elements of that tag name
- .class (class selector): Matches all elements with that class
- #id (ID selector): Matches the single element with that id
- * (universal selector): Matches every element
Best practices
- Prefer classes over IDs for styling - classes are reusable across multiple elements, while IDs must be unique per page and carry high specificity that is hard to override
- Avoid styling directly by element type (like p or div) in larger projects, since it applies globally and is easy to accidentally affect unrelated content
- Use the universal selector (*) sparingly, typically just for resets like box-sizing, since it applies to literally everything
- Combine class selectors (.card.featured) rather than deeply nesting selectors, for flatter, more maintainable specificity
At a glance
- Purpose
- Presentation and layout
- File extension
- .css
- Runs in
- Web browsers
- Usually used with
- HTML and JavaScript
Specifications & further reading
Related CSS documentation
Combinators
Combinators define relationships between selectors. The descendant combinator (space) matches any nested element. The child combinator (>) matches only direct children. The adjacent sibling combinator (+) matches the very next sibling. The general sibling combinator (~) matches all following siblings.Attribute Selectors
Attribute selectors target elements based on the presence or value of an HTML attribute, using square bracket syntax. They support several matching modes beyond exact equality, including starts-with, ends-with, and contains, making them powerful for targeting elements without needing extra classes.:has() - The Parent Selector
:has() matches an element if any of the selectors passed to it match something within it - effectively letting you style a parent based on its children or descendants, something CSS could never do natively before. It has broad, mainstream browser support as of 2026 and is safe to use in production.:is() and :where()
:is() and :where() both accept a list of selectors and match any of them, letting you write more compact selector groups. The key difference is specificity: :is() takes on the specificity of its most specific argument, while :where() always contributes zero specificity, making its rules trivially easy to override.
Combinators define relationships between selectors. The descendant combinator (space) matches any nested element. The child combinator (>) matches only direct children. The adjacent sibling combinator (+) matches the very next sibling. The general sibling combinator (~) matches all following siblings.Attribute Selectors
Attribute selectors target elements based on the presence or value of an HTML attribute, using square bracket syntax. They support several matching modes beyond exact equality, including starts-with, ends-with, and contains, making them powerful for targeting elements without needing extra classes.:has() - The Parent Selector
:has() matches an element if any of the selectors passed to it match something within it - effectively letting you style a parent based on its children or descendants, something CSS could never do natively before. It has broad, mainstream browser support as of 2026 and is safe to use in production.:is() and :where()
:is() and :where() both accept a list of selectors and match any of them, letting you write more compact selector groups. The key difference is specificity: :is() takes on the specificity of its most specific argument, while :where() always contributes zero specificity, making its rules trivially easy to override.