Knowledge/CSS/Introduction
20 Chapters
Modern Baseline
Living Document
Free License
Engineering Publication · Syed Omar Ibn Feroj← Back to portfolio
{}
Engineering Notes · Open Knowledge Repository

CSS — Engineering
Notes for Real Layouts

A working reference for CSS as it's used to ship interfaces — the cascade and specificity that decide who wins, modern layout with Grid and Flexbox, custom properties, and the container/logical features that replaced a decade of hacks.

20
Chapters
Modern
Baseline
Living
Document
Free
License
Ch. 01
Selectors
How you target elements — and the combinators most people underuse.
1.1 — The selector families
CSS
.card {}                 /* class */
#app {}                  /* id  (avoid for styling) */
a[target="_blank"] {}    /* attribute */
.a > .b {}              /* direct child */
.a .b {}                /* any descendant */
.a + .b {}              /* next sibling */
.a ~ .b {}              /* any later sibling */
:is(h1, h2, h3) a {}     /* match-any group */
:where(.a, .b) {}        /* like :is but 0 specificity */
Ch. 02
Specificity & Cascade
Why your rule isn't applying — almost always this.
2.1 — The specificity tuple (a, b, c)

Specificity is counted as three numbers: a = id selectors, b = class/attribute/pseudo-class, c = element/pseudo-element. Inline styles outrank all of them; !important overrides everything (and is a smell).

CSS
#nav .item a    /* (1,1,1) */
.nav .item a    /* (0,2,1) — loses to above */
a.btn.lg        /* (0,2,1) */
:where(#x) a    /* (0,0,1) — :where zeroes it */
▹
Keep specificity flat and low. One class per concern, no id selectors for styling, :where() for resets. When everything is (0,1,0)-ish, source order decides — which is predictable.
2.2 — Cascade layers
CSS
@layer reset, base, components, utilities;
@layer components { .btn { color: blue; } }
/* a later layer always beats an earlier one,
   regardless of selector specificity */
Ch. 03
Inheritance
What flows down the tree, what doesn't, and the reset keywords.
3.1 — Inherited vs not

Typography-ish properties inherit (color, font-*, line-height, visibility). Box properties do not (margin, padding, border, display). Force it either way with the universal keywords:

CSS
.x { color: inherit; }      /* take parent's */
.x { margin: unset; }      /* inherited→inherit, else initial */
.x { all: revert; }        /* back to the UA stylesheet */
Ch. 04
Box Model
Content, padding, border, margin — and the one line everyone sets.
4.1 — border-box, always
CSS
*, *::before, *::after { box-sizing: border-box; }
/* width now INCLUDES padding + border —
   the intuitive behaviour */
▲
Adjacent vertical margins collapse — two stacked 20px margins make 20px of gap, not 40. It's by design; control it with gap in flex/grid layouts instead of relying on margins.
Ch. 05
Units
When to use rem, em, %, vw, ch — and when not to use px.
5.1 — The unit decision
UnitRelative toUse for
remroot font sizetype scale, spacing (respects user zoom)
emelement font sizepadding that scales with text
%parentfluid widths
vw/vh/dvhviewportfull-screen sections (dvh handles mobile bars)
ch"0" widthreadable line length (~60ch)
frgrid free spacegrid track sizing
▹
Use rem for font size and spacing so the layout respects the user's browser font preference. Fixed px everywhere is an accessibility failure.
Ch. 06
Colors
Modern color: hsl, oklch, relative colors, color-mix.
6.1 — Beyond hex
CSS
color: rgb(255 0 0 / .5);     /* modern slash-alpha */
color: hsl(210 100% 50%);
color: oklch(0.7 0.15 250);  /* perceptually uniform */
color: color-mix(in srgb, blue 30%, transparent);
/* relative color syntax */
--hover: oklch(from var(--brand) calc(l - .1) c h);
Ch. 07
Typography
Fluid type, line length, and the properties that decide readability.
7.1 — Fluid type with clamp
CSS
h1 {
  font-size: clamp(1.75rem, 1.2rem + 2vw, 3rem);
  line-height: 1.1;          /* tighter for headings */
  text-wrap: balance;        /* even multi-line headings */
}
p { max-width: 65ch; line-height: 1.6; text-wrap: pretty; }
Ch. 08
Custom Properties
Real cascading variables — themable, scoped, JS-readable.
8.1 — Define, fall back, override
CSS
:root { --space: 1rem; --brand: #38bdf8; }
.card { padding: var(--space, 1rem); }
.card.tight { --space: .5rem; }   /* scoped override */

[data-theme="dark"] { --brand: #7dd3fc; }
▹
Custom properties cascade and inherit, so a single --brand on a parent themes everything below it. This is how runtime theming works without a build step.
Ch. 09
Functions
calc, clamp, min, max — math in the stylesheet.
9.1 — The math toolkit
CSS
width: min(100%, 60ch);              /* fluid but capped */
width: max(320px, 40%);             /* floor */
padding: clamp(1rem, 5vw, 3rem);    /* min, preferred, max */
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
✓
minmax(220px, 1fr) + auto-fit is a complete responsive card grid in one line — no media queries needed.
Ch. 10
Display & Flow
block, inline, flow-root, and clearing the float era.
10.1 — The values that still matter

Modern layout is Flexbox and Grid; float is for wrapping text around an image and nothing else. display: flow-root creates a clean block formatting context (the modern clearfix). display: contents removes a box from layout while keeping its children — useful but breaks accessibility if misused.

Ch. 11
Flexbox
One-dimensional layout — rows or columns, with alignment.
11.1 — The core five
CSS
.row {
  display: flex;
  gap: 1rem;
  justify-content: space-between;  /* main axis */
  align-items: center;             /* cross axis */
  flex-wrap: wrap;
}
.grow { flex: 1; }        /* 1 1 0 — fill space */
.fixed { flex: 0 0 auto; }  /* don't grow/shrink */
▹
Reach for Flexbox when content size should drive the layout (a toolbar, a row of chips). Reach for Grid when the layout structure is fixed and content fills it.
Ch. 12
Grid
Two-dimensional layout — the most powerful tool in CSS.
12.1 — Tracks, areas, auto-placement
CSS
.layout {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "head head"
    "side main"
    "foot foot";
  min-height: 100dvh;
}
header { grid-area: head; }
main { grid-area: main; }
12.2 — Responsive without media queries
CSS
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 18rem), 1fr));
  gap: 1rem;
}
Ch. 13
Positioning
static, relative, absolute, fixed, sticky — and stacking.
13.1 — sticky and the z-index trap
CSS
.bar { position: sticky; top: 0; z-index: 10; }
/* sticky needs a scroll container + a threshold (top) */
▲
z-index only works within a stacking context. transform, opacity < 1, filter and will-change all create one — which is why a high z-index sometimes still renders behind a sibling. Fix the context, don't escalate the number.
Ch. 14
Backgrounds & Borders
Gradients, multiple backgrounds, border-radius, outline.
14.1 — Layered backgrounds
CSS
.hero {
  background:
    radial-gradient(circle at top, #0003, transparent),
    linear-gradient(135deg, #1e293b, #0f172a);
  border-radius: 1rem;
  outline: 1px solid #fff2;  /* doesn't affect layout */
}
Ch. 15
Transforms
translate, scale, rotate — GPU-friendly, layout-free.
15.1 — Individual transform properties
CSS
.x { translate: 0 10px; scale: 1.05; rotate: 3deg; }
/* composable + independently animatable (modern) */
.y { transform: translate3d(0,10px,0); }  /* old form */
▹
Animate only transform and opacity for 60fps — they're composited off the main thread. Animating width/top/margin triggers layout on every frame.
Ch. 16
Transitions
Smooth state changes — the cheapest motion you can add.
16.1 — Transition specific properties
CSS
.btn {
  transition: background-color .2s ease, transform .2s ease;
}
.btn:hover { transform: translateY(-2px); }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}
▲
Never transition: all — it animates properties you didn't intend (including expensive ones) and is a measurable perf cost. List the properties explicitly.
Ch. 17
Animations
@keyframes for multi-step, looping motion.
17.1 — Keyframes
CSS
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: .4; }
}
.dot { animation: pulse 2s ease-in-out infinite; }
Ch. 18
Media Queries
Responsive breakpoints, and the features beyond width.
18.1 — Range syntax + capability queries
CSS
@media (768px <= width < 1024px) { ... }  /* modern range */
@media (prefers-color-scheme: dark) { ... }
@media (hover: hover) { .x:hover { ... } }  /* skip on touch */
@supports (display: grid) { ... }
▹
Design mobile-first: base styles for small screens, then min-width queries add complexity for larger ones. It degrades gracefully and ships less CSS to the constrained device.
Ch. 19
Container Queries & :has()
The two features that changed how components are built.
19.1 — Style by the container, not the viewport
CSS
.card { container-type: inline-size; }
@container (min-width: 400px) {
  .card .layout { display: grid; grid-template-columns: 1fr 2fr; }
}
19.2 — The parent selector
CSS
.field:has(input:invalid) { border-color: red; }
/* style a label based on its input's state */
article:has(> img) { padding-block: 0; }
✓
:has() is the long-requested "parent selector" — it removes an enormous category of JavaScript that existed only to toggle a class on an ancestor.
Ch. 20
Architecture
Keeping CSS maintainable past 10,000 lines.
20.1 — Principles that scale
  • One low, flat specificity tier — single classes, no id styling, @layer for order
  • Design tokens as custom properties (color, space, radius, type scale) — one source of truth
  • Co-locate styles with components (CSS Modules / scoped) so deletion is safe
  • Logical properties (margin-inline, padding-block) for RTL/i18n from day one
  • A reset/normalize in the first @layer so UA differences never surprise you
▹
The hardest CSS problem isn't writing it — it's deleting it safely. Scoping (modules, @scope, or a strict naming convention) is what makes a large stylesheet refactorable instead of append-only.
REF
CSS Cheatsheet
Centering, and the modern one-liners.
Centre anything
CSS
/* flex */
.c { display: flex; place-items: center; min-height: 100dvh; }

/* grid — shortest */
.c { display: grid; place-content: center; }

/* absolute */
.c { position: absolute; inset: 0; margin: auto; width: fit-content; }
Modern one-liners
GoalDeclaration
Responsive gridgrid-template-columns: repeat(auto-fit, minmax(15rem, 1fr))
Readable columnmax-width: 65ch
Fluid typefont-size: clamp(1rem, 2.5vw, 1.5rem)
Aspect ratioaspect-ratio: 16 / 9
Truncate texttext-overflow: ellipsis; overflow: hidden; white-space: nowrap
Full-bleed bgmin-height: 100dvh (handles mobile bars)