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)