Advanced CSS Techniques
Pseudo-elements
::before and ::after create virtual elements inside any element — no extra HTML needed:CSS
.badge::before {
content: "✓ ";
color: #22c55e;
}
.quote::before {
content: """;
font-size: 3rem;
color: var(--accent);
position: absolute;
top: -10px;
left: -20px;
}content is required — without it, the pseudo-element doesn't render. Use content: "" for decorative pseudo-elements.Decorative lines and shapes
CSS
.section-title::after {
content: "";
display: block;
width: 60px;
height: 3px;
background: var(--accent);
margin-top: 0.5rem;
}The :has() selector
The "parent selector" CSS developers wanted for 20 years. It selects an element based on what's inside it:
CSS
/* Style a card differently if it contains an image */
.card:has(img) {
padding: 0;
}
/* Style a label when its input is focused */
label:has(input:focus) {
color: var(--accent);
}
/* Highlight form groups with invalid inputs */
.form-group:has(:invalid) {
border-left: 3px solid #dc2626;
}The :is() and :where() selectors
Reduce repetition in complex selectors:
CSS
/* Without :is() */
article h1, article h2, article h3 {
line-height: 1.2;
}
/* With :is() */
article :is(h1, h2, h3) {
line-height: 1.2;
}:where() works the same but has zero specificity — useful for resets and defaults that are easy to override.Logical properties
Instead of
left, right, top, bottom, use logical properties that work in any writing direction:CSS
.card {
margin-inline: auto; /* replaces margin-left + margin-right */
padding-block: 1rem; /* replaces padding-top + padding-bottom */
padding-inline: 1.5rem; /* replaces padding-left + padding-right */
border-inline-start: 3px solid var(--accent); /* replaces border-left */
}This makes your CSS work automatically in right-to-left (RTL) languages like Arabic or Hebrew.
Scroll snapping
Create smooth, snappy scroll behavior:
CSS
.carousel {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
gap: 1rem;
}
.carousel-item {
flex: 0 0 80%;
scroll-snap-align: start;
}Items snap into place when the user stops scrolling — no JavaScript carousel library needed.
Aspect ratio
Maintain consistent proportions:
CSS
.video-container {
aspect-ratio: 16 / 9;
width: 100%;
}
.avatar {
aspect-ratio: 1;
width: 48px;
border-radius: 50%;
object-fit: cover;
}Backdrop filter
Apply effects to the area behind an element:
CSS
.glass-card {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 12px;
}This creates the popular "glassmorphism" effect.
Color-mix() and modern color functions
CSS
.button:hover {
background: color-mix(in srgb, var(--accent), black 20%);
}This darkens the accent color by mixing it with 20% black — great for hover states without hardcoding a second color.
Nesting (native CSS)
Modern CSS now supports nesting, similar to Sass:
CSS
.card {
padding: 1rem;
border: 1px solid var(--border);
& h2 {
font-size: 1.25rem;
margin-bottom: 0.5rem;
}
&:hover {
border-color: var(--accent);
}
& .card-footer {
border-top: 1px solid var(--border);
padding-top: 0.75rem;
}
}This keeps related styles grouped together and reduces repetition.
The @layer rule
Control the cascade order explicitly:
CSS
@layer reset, base, components, utilities;
@layer reset {
* { margin: 0; box-sizing: border-box; }
}
@layer utilities {
.hidden { display: none; }
.text-center { text-align: center; }
}Styles in later layers always beat styles in earlier layers, regardless of specificity. This eliminates many specificity wars.
Key takeaway
Modern CSS is incredibly powerful.
:has() enables parent selection, scroll snapping replaces JavaScript carousels, native nesting reduces boilerplate, @layer tames the cascade, and logical properties make your CSS internationally friendly. These aren't experimental — they're supported in all modern browsers.