CSS Expert
Overview
Advanced expertise in CSS — from the cascade, specificity, and layout fundamentals (Flexbox, Grid) to modern CSS features (cascade layers, container queries, scroll animations, @scope), architecture patterns, and Sass/SCSS.
1. The Cascade, Specificity & Inheritance
Cascade Order (high → low priority)
!important+ inline styles!important+ ID selectors!important+ class/attribute/pseudo-class!important+ type/pseudo-element- Inline styles (
style="") - ID selectors (
#id) - Class / attribute / pseudo-class (
.class,[attr],:hover) - Type / pseudo-element (
div,::before) - Universal selector (
*), combinators - Inherited values
- Browser defaults
Specificity Calculation
(a, b, c)
a = number of ID selectors
b = number of class, attribute, pseudo-class selectors
c = number of type, pseudo-element selectors
#nav .item:hover → (1, 2, 0)
.card > p → (0, 1, 1)
div ul li.active → (0, 1, 3)
:where(.card) → (0, 0, 0) always zero specificity
:is(.card, #hero) → takes highest specificity of its args
Inheritance
/* Inherited by default: color, font-*, line-height, text-*, visibility, cursor */
/* Not inherited: margin, padding, border, background, display, width, height */
p { color: inherit; } /* force inheritance */
p { color: initial; } /* reset to browser default */
p { color: unset; } /* inherits if inheritable, else initial */
p { color: revert; } /* revert to browser/user stylesheet */
p { all: unset; } /* reset all properties */
2. Selectors
/* Combinators */
div p /* descendant */
div > p /* direct child */
h1 + p /* adjacent sibling */
h1 ~ p /* general sibling */
/* Attribute selectors */
[type="text"] /* exact match */
[class~="card"] /* space-separated word match */
[href^="https"] /* starts with */
[href$=".pdf"] /* ends with */
[href*="example"] /* contains */
[lang|="en"] /* exact or starts with "en-" */
/* Pseudo-classes */
:hover :focus :active :visited :link
:focus-visible /* keyboard focus only (not mouse click) */
:focus-within /* has focused descendant */
:checked :disabled :enabled :required :optional
:valid :invalid :placeholder-shown :user-valid :user-invalid
:empty /* no children or text */
:target /* element whose id matches URL hash */
:root /* <html> — highest specificity for custom props */
/* Structural pseudo-classes */
:first-child :last-child :only-child
:nth-child(2) /* 2nd child */
:nth-child(2n) /* even children */
:nth-child(2n+1) /* odd children */
:nth-child(3n+1) /* every 3rd starting at 1 */
:nth-child(n+3) /* 3rd and beyond */
:nth-child(-n+3) /* first 3 */
:nth-of-type(2) /* 2nd of its element type */
:not(.excluded) /* negation */
:not(h1, h2, h3) /* multiple args (Selectors 4) */
:is(h1, h2, h3) span /* matches any heading's span */
:where(.card, .box) /* like :is() but zero specificity */
:has(> img) /* parent has direct child img */
:has(+ .sibling) /* element followed by .sibling */
/* Pseudo-elements */
::before ::after /* generated content */
::placeholder
::selection
::first-line ::first-letter
::marker /* list item bullet */
::backdrop /* behind <dialog> */
::file-selector-button
3. Flexbox
/* Container */
.flex {
display: flex; /* or inline-flex */
flex-direction: row; /* row | row-reverse | column | column-reverse */
flex-wrap: nowrap; /* nowrap | wrap | wrap-reverse */
flex-flow: row wrap; /* shorthand */
/* Main axis alignment */
justify-content: flex-start; /* flex-start | flex-end | center | space-between | space-around | space-evenly */
/* Cross axis alignment */
align-items: stretch; /* stretch | flex-start | flex-end | center | baseline */
/* Multi-line cross axis */
align-content: normal; /* same values as justify-content */
gap: 16px; /* row-gap + column-gap */
gap: 16px 24px; /* row-gap column-gap */
}
/* Items */
.item {
flex-grow: 0; /* proportion of free space to take */
flex-shrink: 1; /* ability to shrink */
flex-basis: auto; /* initial size before grow/shrink */
flex: 1; /* flex: 1 1 0 */
flex: 1 1 auto; /* grow, shrink, auto basis */
flex: 0 0 200px; /* fixed 200px, no grow/shrink */
align-self: auto; /* override align-items for this item */
order: 0; /* visual reorder */
margin-left: auto; /* push item to far right */
}
/* Common patterns */
/* Center anything */
.center { display: flex; align-items: center; justify-content: center; }
/* Sticky footer */
.page { display: flex; flex-direction: column; min-height: 100vh; }
.main { flex: 1; }
/* Equal-width columns */
.cols > * { flex: 1; }
/* Auto-wrap responsive grid */
.grid { display: flex; flex-wrap: wrap; gap: 1rem; }
.grid > * { flex: 1 1 min(300px, 100%); }
4. CSS Grid
/* Container */
.grid {
display: grid; /* or inline-grid */
/* Define columns */
grid-template-columns: 1fr 2fr 1fr;
grid-template-columns: repeat(3, 1fr);
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); /* responsive */
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); /* collapse empty */
grid-template-columns: 200px 1fr; /* sidebar + main */
grid-template-columns: [sidebar-start] 240px [sidebar-end main-start] 1fr [main-end];
/* Define rows */
grid-template-rows: auto 1fr auto; /* header, main, footer */
grid-auto-rows: minmax(100px, auto); /* implicit row size */
grid-auto-flow: row dense; /* fill gaps with dense packing */
/* Gap */
gap: 24px;
gap: 16px 24px; /* row-gap column-gap */
/* Named areas */
grid-template-areas:
"header header header"
"sidebar main main"
"footer footer footer";
/* Alignment */
justify-items: stretch; /* align cells on inline axis */
align-items: stretch; /* align cells on block axis */
justify-content: start; /* align grid on inline axis */
align-content: start; /* align grid on block axis */
place-items: center; /* align-items + justify-items */
place-content: center; /* align-content + justify-content */
}
/* Items */
.item {
grid-column: 1 / 3; /* start / end line */
grid-column: 1 / span 2; /* start / span count */
grid-column: sidebar-start / sidebar-end; /* named lines */
grid-row: 2 / 4;
grid-area: header; /* assign to named area */
grid-area: 1 / 1 / 2 / 3; /* row-start / col-start / row-end / col-end */
justify-self: center; /* override justify-items */
align-self: end; /* override align-items */
place-self: center end;
}
/* Holy Grail Layout */
.page {
display: grid;
grid-template: "header" auto "sidebar main" 1fr "footer" auto / 200px 1fr;
min-height: 100vh;
}
header { grid-area: header; }
aside { grid-area: sidebar; }
main { grid-area: main; }
footer { grid-area: footer; }
5. CSS Custom Properties (Variables)
/* Define */
:root {
--color-primary: #3b82f6;
--color-primary-dark: #1d4ed8;
--spacing-md: 1rem;
--radius: 0.5rem;
--font-sans: 'Inter', sans-serif;
--shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
}
/* Use */
.button {
background: var(--color-primary);
padding: var(--spacing-md);
border-radius: var(--radius);
/* Fallback value */
color: var(--button-color, white);
}
/* Scoped variables */
.card {
--card-padding: 1.5rem;
padding: var(--card-padding);
}
/* Dark mode via variables */
:root { --bg: #ffffff; --text: #111827; }
.dark { --bg: #111827; --text: #f9fafb; }
@media (prefers-color-scheme: dark) {
:root { --bg: #111827; --text: #f9fafb; }
}
/* Computed / dynamic */
.progress {
--value: 70;
width: calc(var(--value) * 1%);
}
6. Responsive Design — Media & Container Queries
/* Media Queries */
@media (max-width: 768px) { } /* mobile */
@media (min-width: 768px) { } /* tablet+ (mobile-first) */
@media (min-width: 768px) and (max-width: 1024px) { }
@media (prefers-color-scheme: dark) { }
@media (prefers-reduced-motion: reduce) { }
@media (prefers-contrast: high) { }
@media print { }
@media (hover: hover) and (pointer: fine) { } /* mouse device */
@media (hover: none) { } /* touch device */
@media (orientation: landscape) { }
@media (display-mode: standalone) { } /* PWA installed */
/* Container Queries (modern — target parent size, not viewport) */
.card-wrapper {
container-type: inline-size;
container-name: card;
}
@container card (min-width: 400px) {
.card { flex-direction: row; }
}
@container (min-width: 600px) {
.card__title { font-size: 1.5rem; }
}
/* Style Queries */
@container style(--variant: compact) {
.card { padding: 0.5rem; }
}
/* Responsive type with clamp() */
h1 { font-size: clamp(1.5rem, 4vw + 1rem, 3rem); }
p { font-size: clamp(1rem, 1.5vw, 1.25rem); }
/* Fluid spacing */
.section { padding: clamp(2rem, 5vw, 5rem); }
7. CSS Functions
/* Math functions */
width: calc(100% - 2rem);
width: calc(var(--sidebar) + 48px);
width: min(100%, 800px); /* smallest value */
width: max(300px, 50%); /* largest value */
width: clamp(200px, 50%, 800px); /* min, preferred, max */
/* Color functions */
color: rgb(59 130 246); /* modern no-comma syntax */
color: rgb(59 130 246 / 0.5); /* with alpha */
color: hsl(217 91% 60%);
color: hsl(217 91% 60% / 0.8);
color: color-mix(in oklch, #3b82f6 80%, white); /* blend colors */
color: oklch(0.6 0.2 240); /* perceptually uniform */
color: light-dark(#fff, #000); /* automatic light/dark */
/* Transform functions */
transform: translate(10px, 20px) rotate(45deg) scale(1.2);
transform: translateX(50%) translateY(-50%); /* center absolute element */
/* Gradient */
background: linear-gradient(135deg, #3b82f6, #8b5cf6);
background: radial-gradient(circle at center, #3b82f6, transparent);
background: conic-gradient(from 90deg, red, yellow, green, blue, red);
/* Shapes */
clip-path: polygon(0 0, 100% 0, 100% 80%, 0 100%);
clip-path: circle(50%);
clip-path: inset(0 0 20% 0 round 8px);
shape-outside: circle(50%);
/* Other */
filter: blur(4px) brightness(0.8) contrast(1.2) grayscale(100%);
backdrop-filter: blur(10px) saturate(180%);
content: counter(section) ". ";
8. Animations & Transitions
/* Transitions */
.btn {
transition: background-color 200ms ease, transform 150ms ease, box-shadow 200ms ease;
/* property duration timing-function delay */
}
.btn:hover {
background-color: #1d4ed8;
transform: translateY(-2px);
box-shadow: 0 10px 20px rgb(0 0 0 / 0.15);
}
/* Keyframe animations */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes spin {
to { transform: rotate(360deg); }
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.element {
animation: fadeIn 400ms ease-out both;
/* name duration timing fill-mode */
animation: spin 1s linear infinite;
animation-delay: 200ms;
animation-play-state: paused; /* or running */
animation-iteration-count: 3;
}
/* Respect user preferences */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
/* Scroll-driven animations (Chrome 115+) */
@keyframes reveal {
from { opacity: 0; transform: translateY(40px); }
to { opacity: 1; transform: translateY(0); }
}
.reveal {
animation: reveal linear both;
animation-timeline: view();
animation-range: entry 0% entry 30%;
}
/* View transitions */
@view-transition { navigation: auto; }
::view-transition-old(root) { animation: 300ms ease out slide-out; }
::view-transition-new(root) { animation: 300ms ease in slide-in; }
9. Cascade Layers (@layer)
/* Declare order (lower = lower priority) */
@layer reset, base, components, utilities;
@layer reset {
*, *::before, *::after { box-sizing: border-box; margin: 0; }
}
@layer base {
body { font-family: var(--font-sans); color: var(--color-text); }
a { color: var(--color-primary); }
}
@layer components {
.btn { /* component styles */ }
.card { /* card styles */ }
}
@layer utilities {
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0); }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}
/* Styles outside any layer beat all layered styles */
.override { color: red; } /* always wins vs layered styles */
/* Import with layer */
@import url("reset.css") layer(reset);
10. Sass / SCSS
// Variables
$color-primary: #3b82f6;
$spacing-base: 1rem;
$breakpoint-md: 768px;
// Nesting
.card {
background: white;
padding: $spacing-base;
&__title { font-size: 1.25rem; } // BEM modifier
&--featured { border: 2px solid $color-primary; }
&:hover { box-shadow: 0 4px 12px rgb(0 0 0 / 0.1); }
@media (min-width: $breakpoint-md) {
padding: $spacing-base * 1.5;
}
}
// Mixins
@mixin flex-center {
display: flex;
align-items: center;
justify-content: center;
}
@mixin responsive($breakpoint) {
@if $breakpoint == md { @media (min-width: 768px) { @content; } }
@if $breakpoint == lg { @media (min-width: 1024px) { @content; } }
}
.hero {
@include flex-center;
@include responsive(md) { padding: 4rem; }
}
// Functions
@function rem($px) { @return ($px / 16) * 1rem; }
.element { font-size: rem(18); }
// Extend / Placeholder
%visually-hidden {
position: absolute; width: 1px; height: 1px;
overflow: hidden; clip: rect(0,0,0,0);
}
.sr-only { @extend %visually-hidden; }
// Loops
@each $size in sm, md, lg {
.gap-#{$size} { gap: map-get((sm: 0.5rem, md: 1rem, lg: 2rem), $size); }
}
@for $i from 1 through 12 {
.col-#{$i} { width: ($i / 12 * 100%); }
}
11. CSS Architecture — BEM
/* Block__Element--Modifier */
.card { } /* Block */
.card__title { } /* Element */
.card__body { } /* Element */
.card__image { } /* Element */
.card--featured { } /* Modifier */
.card--compact { } /* Modifier */
.card__title--large { } /* Element + Modifier */
/* Never: .card .title (descendant — breaks encapsulation) */
/* Always: .card__title (flat BEM selector) */
12. Modern CSS Snippets
/* Smooth scroll */
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
/* Custom scroll bar */
::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-track { background: #f1f5f9; }
::-webkit-scrollbar-thumb { background: #94a3b8; border-radius: 4px; }
scrollbar-width: thin; scrollbar-color: #94a3b8 #f1f5f9; /* Firefox */
/* Aspect ratio */
.video { aspect-ratio: 16 / 9; width: 100%; }
.avatar { aspect-ratio: 1; }
/* Text clamp */
.clamp-2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* Logical properties (LTR/RTL aware) */
.box {
margin-inline: auto; /* = margin-left + margin-right */
padding-block: 1rem; /* = padding-top + padding-bottom */
border-inline-start: 4px solid blue; /* = border-left in LTR */
inset-inline-start: 0; /* = left in LTR */
}
/* Subgrid */
.grid { display: grid; grid-template-columns: repeat(3, 1fr); }
.card { grid-column: span 3; display: grid; grid-template-columns: subgrid; }
/* :has() real-world uses */
.form-group:has(:invalid) label { color: red; }
nav:has(.dropdown:hover) { z-index: 100; }
main:has(> aside) { grid-template-columns: 1fr 300px; }
/* CSS Nesting (native, no Sass needed) */
.card {
color: black;
& .title { font-size: 1.25rem; }
&:hover { background: #f9fafb; }
@media (min-width: 768px) { padding: 2rem; }
}
Core Competency Summary
- Master the cascade, specificity, and inheritance to write predictable CSS
- Build complex layouts with Flexbox and CSS Grid (named areas, subgrid, auto-fill/auto-fit)
- Use CSS custom properties for themeable, maintainable design systems
- Write responsive designs with media queries and container queries
- Create smooth animations and transitions, respecting
prefers-reduced-motion - Leverage modern CSS:
@layer,@scope,:has(),clamp(),color-mix(), scroll-driven animations - Architect scalable stylesheets with BEM naming and Sass/SCSS