# Expert Topics
For seasoned developers, CSS offers a wealth of powerful features. This chapter explores advanced selectors, pseudo-classes, modern at-rules, cascade layers, environment variables, and strategies for progressive enhancement.
# Table of Contents
- Advanced Selectors & Combinators
- Pseudo-classes & Pseudo-elements
- Modern At-Rules
- Cascade Layers & Custom Rules
- Environment Variables & Viewport Units
- Progressive Enhancement & Fallbacks
- Gotchas & Best Practices
- Quick Cheatsheet
- Practice Tasks
- Review Questions
- Related Links
# Advanced Selectors & Combinators
Modern CSS includes advanced selectors like :has(), :is(), :where(), :nth-child() with formulas, and the relational combinator :scope > :not(:first-child). Use them to target complex patterns with minimal markup.
/* Parent highlighting if it contains a checked checkbox */
label:has(input:checked) {
background: #def;
border-left: 4px solid #39f;
}
/* Target the first article only if it's followed by a second */
article:nth-child(1 of article:nth-last-child(n+2)) {
border-bottom: 1px solid #ccc;
}
/* Use :is() to group selectors without increasing specificity */
nav :is(a, button) {
padding: .5rem 1rem;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<label><input type="checkbox"> Select me</label>
<nav>
<a href="#">Link</a>
<button>Action</button>
</nav>
2
3
4
5
# Pseudo-classes & Pseudo-elements
Pseudo-classes like :target, :focus-visible, :nth-of-type, and :not() handle element states and positions. Pseudo-elements (::before, ::after, ::slotted()) create extra elements for styling or target distributed content in Web Components.
.accordion input:focus-visible + label {
outline: 2px dashed #09f;
}
a:target {
background: yellow;
}
/* Slotted content in Shadow DOM */
my-element::slotted(.highlight) {
color: crimson;
}
2
3
4
5
6
7
8
9
10
11
12
<div class="accordion">
<input id="q1" type="checkbox">
<label for="q1">Question 1</label>
<div>Answer 1</div>
</div>
2
3
4
5
# Modern At-Rules
CSS introduces new at-rules beyond @media and @font-face: @container for container queries【107830350795899†L206-L224】, @layer for cascade organization, @scope for scoping styles, and @property for custom property registration【460321113036012†L186-L194】.
@layer utilities {
.text-muted { color: #666; }
}
@scope (.card) {
.button { margin-block-end: 1rem; }
}
@supports (animation-timeline: scroll()) {
@scroll-timeline timeline {
start: cover 0%;
end: cover 100%;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
Use @supports to test for feature availability and provide fallbacks.
# Cascade Layers & Custom Rules
Cascade layers (@layer) define distinct layers of the cascade, giving fine-grained control over override order. Combined with @property and @nest, they enable modular and encapsulated styling.
@layer theme {
:root { --spacing: 1rem; }
}
@layer components {
.alert {
padding: var(--spacing);
border-left: 4px solid currentColor;
}
}
/* Nest rules to avoid repetition */
.nav {
display: flex;
> li {
margin-inline-end: .5rem;
&:last-child { margin-inline-end: 0; }
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@nest allows nested rules similar to preprocessors but is still experimental. Always provide flat CSS for unsupported browsers.
# Environment Variables & Viewport Units
CSS environment variables (env()) expose system metrics like safe area insets on iOS (notch spacing). Use constant() as a fallback for older Safari.
body {
padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}
/* Fallback for old Safari */
body {
padding: constant(safe-area-inset-top) constant(safe-area-inset-right) constant(safe-area-inset-bottom) constant(safe-area-inset-left);
}
2
3
4
5
6
7
8
Logical viewport units like svh, lvw, and dvh adapt to mobile browser UI changes (scrollbars, address bars). Use them instead of vh or vw for more stable layouts.
# Progressive Enhancement & Fallbacks
Always deliver core functionality with widely supported features and layer in advanced capabilities. Use @supports and @media queries to conditionally apply enhancements. Provide fallback values for custom properties and animation.
.banner {
background: url("hero.jpg") center/cover no-repeat;
min-height: 50vh;
display: grid;
place-content: center;
color: white;
text-shadow: 0 1px 2px rgba(0,0,0,.5);
}
@supports (background-blend-mode: multiply) {
.banner {
background-blend-mode: multiply;
background-color: rgba(0,0,0,.5);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# Gotchas & Best Practices
- Advanced selectors like
:has()may have limited support; provide fallbacks. - Avoid excessive specificity; prefer component-level encapsulation via classes and layers.
- Use
@supportsblocks to guard experimental features. @nestis not widely implemented; use a preprocessor or flatten as fallback.- Keep progressive enhancement top of mind: baseline support first, enhancements second.
# Quick Cheatsheet
- Selectors:
:has(),:is(),:where(),:nth-child(), complex formulas. - Pseudo:
:target,:focus-visible,::slotted(). - At-Rules:
@container,@layer,@scope,@property,@supports. - Environment:
env(safe-area-inset-top),svh,lvh,dvh. - Progressive: provide fallbacks and test feature support.
# Practice Tasks
- Use
:has()to style a parent element based on a child’s state; create a fallback using JavaScript or simpler selectors. - Create a component with nested rules using
@nestand flatten it for unsupported browsers. - Implement a banner that uses environment variables to avoid the iPhone notch area.
- Build a feature detection using
@supportsto enable scroll-driven animations only if supported. - Refactor a CSS file to organize rules into cascade layers and demonstrate the override order.
# Review Questions
- How do
:has(),:is(), and:where()differ in specificity and intent? - What do
@containerand@scopeprovide beyond traditional media queries【107830350795899†L206-L224】? - Explain the purpose of environment variables like
env(safe-area-inset-top). - Why is progressive enhancement important when using experimental features?
- Describe the benefits of cascade layers and how they interact with specificity.