Rendered from rules.md

Here are your HTML/CSS rules so far, consolidated into one reference.

HTML & CSS Basics — Rules So Far

# Rule Key point
1 Vertical margins can collapse Adjacent vertical margins on normal block elements can collapse. The resulting gap is generally the larger margin, not the sum. Flex/grid items and several other layout situations do not collapse this way.
2 Text contrast Normal text should have at least 4.5:1 contrast against its background. Large text can use 3:1.
3 Center a block with auto margins Give it an appropriate width and use margin-left: auto; margin-right: auto;, commonly margin: 0 auto;. A parent’s text-align: center does not replace this for block children. Still works on a flex container itself; use flex alignment for its children.
4 text-align: center centers inline content Set it on the parent to center text, images, spans, and other inline/inline-block content. It does not center normal block children — those still need width + margin: 0 auto (rule 3).
5 Know block vs inline Block elements normally start a new line and take available width. Inline elements flow with surrounding content and generally take only the space they need.
6 display can change default behavior An element's default block/inline behavior can be changed with display.
7 Use Flexbox for flexible layouts display: flex makes the direct children flex items. The flex container is still a block-level box (full width by default) unless you change that.
8 justify-content controls the main axis Packs items along the main axis: flex-start, flex-end, center, space-between, space-around, space-evenly.
9 align-items controls the cross axis Aligns items along the cross axis: stretch (default), flex-start, flex-end, center, baseline.
10 Prefer gap for spacing between flex items gap (or row-gap / column-gap) adds space between items only — not outside the edges. Use margin when one item needs unique spacing.
11 Lean on inheritance Properties like color, font-size, and font-family inherit. Set them once on a parent instead of repeating them on every child.
12 Keep CSS DRY Share styles through common selectors or classes. Avoid copying the same declarations onto many one-off rules when one shared rule can do the job.
13 Understand relative paths ./ = current directory, ../ = one directory up, ../../ = two up.
14 Understand root-relative paths / starts from the current origin's root rather than the current file's directory. This matters when an app is deployed under a subpath such as /my-app/.
15 Write meaningful alt text Describe the image's relevant meaning as though explaining it to someone over the phone.
16 Don't write “image of” in alt Screen readers already communicate that the element is an image.
17 Keep alt concise <125 characters is a useful guideline, not a strict HTML/WCAG requirement.
18 Decorative images use alt="" This allows assistive technology to ignore images that provide no meaningful information.
19 alt is primarily accessibility It also helps when images fail to load and can help search engines understand image content.
20 Use system/web-safe fonts when appropriate They are simple, fast, and reliable. Use web fonts when the design needs them, but always include sensible fallbacks.
21 Always include font backups If you set font-family, never list only one font. Provide at least one named backup when useful, and always end with a generic family (serif, sans-serif, monospace, or cursive) so the browser can still pick something sensible.
22 Box shorthand is clockwise: T → R → B → L Four values map to top, right, bottom, left. The same order applies to margin, padding, and border sides (border-width, border-style, border-color).
23 Find color schemes on Coolors Use coolors.co to explore, generate, or extract a palette, then apply those hex colors in your CSS (background, color, borders, accents). After picking colors, still check text contrast (rule 2).
24 Use Unsplash, Pexels, or undraw for imagery Free stock photos from Unsplash or Pexels are fine for practice/projects. Flat illustration heroes may use undraw.co (or a local undraw-style SVG). Attribution is usually appreciated rather than required, but always check the current license and usage terms.
25 div vs span Use div as a generic block container and span as a generic inline container. Prefer semantic elements such as section, article, nav, header, and footer when they describe the content meaningfully.
26 Use inherit when you want the parent’s value inherit makes a property take its parent’s computed value. Useful to undo a browser default, pass a parent style into a child that normally would not inherit that property, or keep nested text matching its container.
27 Google Fonts are fine for practice Load a font from Google Fonts with <link> tags in <head> (not CSS @import, which blocks rendering), then use it in font-family with backups (rule 21).
28 Local fonts via @font-face (TTF/OTF) Download a font (e.g. from 1001 Fonts), put the .ttf / .otf in your project, declare it with @font-face, then use the family name — always with backups.
29 Be careful with externally hosted animation assets WebP can be smaller than GIF, but avoid depending on hotlinked CDN URLs unless the service permits it. Check embedding and licensing terms.
30 Use an overlay on photo backgrounds Text on a busy background image often fails contrast (rule 2). Add a dark (or light) overlay between the photo and the content so text and controls stay readable.
31 text-shadow can improve readability It may help text stand out on busy backgrounds, but do not rely on it to satisfy contrast requirements. Prefer a proper overlay or stronger foreground/background contrast.
32 Always set lang on <html> Use a language code such as lang="en". Screen readers use it for pronunciation; search engines use it for language; browsers use it for language-related features (quotes, hyphenation, fonts).
33 Circular photos: equal size + border-radius: 50% Give the image equal width and height, add object-fit: cover to avoid distortion, then use border-radius: 50%.
34 Pill buttons use a huge radius Large horizontal padding + border-radius: 999px (or another very high value) makes a capsule / pill shape.
35 Soft card lift with box-shadow A light shadow (e.g. 0 4px 12px rgba(0, 0, 0, 0.15)) lifts a box off the page without a hard border.
36 Full-bleed band / breakout A section with full available width and no side margins can run a color or photo edge to edge as a visual band. For partial breakout, use a 4-column grid with outer minmax(0, 1fr) gutters and inner content tracks, then grid-area so media spans into a gutter while copy stays in the constrained column.
37 Truncate long text with ellipsis overflow: hidden; white-space: nowrap; text-overflow: ellipsis cuts a single line with “…”.
38 Soft square (squircle) Medium border-radius (about 12px24px) softens corners without going fully circular.
39 Same-size thumbnails Set both width and height, then use object-fit: cover so images stay even without being stretched.
40 Two-tone section rhythm Alternate backgrounds (e.g. .box / .box-alt) to create visual rhythm without complex layout.
41 Strong header band as a visual anchor A tall, high-contrast header/nav band can “anchor” the page even without position: sticky.
42 flex-direction sets the main axis row (default) = main axis horizontal; column = main axis vertical. Also row-reverse and column-reverse. Changing direction swaps what justify vs align control.
43 :hover — pointer is over the element Styles the “pointer over me” state. Keep contrast (rule 2); don’t hide essential info only behind hover (touch).
44 :focus — element currently has focus Styles inputs, buttons, and links while focused. Keep focus obvious for accessibility. Later, learn :focus-visible for keyboard-focused UI states. Never use bare outline: none (or outline: 0) without a visible replacement in the same ruleset.
45 :active — element is being pressed Applies during the click/press. Often a slightly darker or tighter look than :hover.
46 :visited — link already opened Styles a links the user has visited. Browsers limit what you can change (often mainly color) for privacy.
47 :first-child — first among siblings Targets the first child element in a parent (e.g. first li in a list).
48 :nth-child(...) — child by pattern Picks children by number or pattern, e.g. :nth-child(odd) / :nth-child(even) for zebra rows, or :nth-child(3) for the third.
49 Specificity decides which selector wins When multiple CSS rules target the same property on the same element, the selector with higher specificity usually wins. Think roughly: inline styles > IDs > classes/attributes/pseudo-classes > element selectors.
50 Later rules win when specificity ties If two competing rules have the same specificity and both apply, the rule that appears later in the stylesheet wins.
51 Avoid overly specific selectors Prefer simple reusable classes over long selector chains or IDs for styling. High specificity makes later overrides harder. :is() can shorten lists, but its specificity is that of its most specific argument.
52 Group selectors to share styles Separate selectors with commas when they need the same declarations, e.g. h1, h2, h3 { font-family: Georgia, serif; }. Prefer :is(h1, h2, h3) when nesting or repeating the same list.
53 Group related content semantically Use meaningful containers such as section, article, header, nav, main, and footer when they describe the content. Use div when no semantic element fits.
54 Understand the complete box model Every element is built from the inside out: content → padding → border → margin. With the default content-box, declared width and height apply only to the content.
55 Prefer box-sizing: border-box for predictable sizing With border-box, declared width and height include content, padding, and border. Margin always remains outside the declared size.
56 Combine width with min-width and max-width width proposes a size, while min-width and max-width set lower and upper limits. A common responsive pattern is width: 100%; max-width: 960px;. Use min-width carefully because it can force horizontal overflow.
57 Prefer flexible height constraints Use min-height when a box needs a minimum size but may grow with content. Use max-height only when you have decided what excess content should do; a fixed height can clip or overflow changing content.
58 Choose CSS units by what should control the size Use px for deliberate fixed details, % for a containing block, rem for root-relative sizing, em for component-relative sizing, and viewport units when the viewport should control the result.
59 Choose overflow behavior deliberately visible is the default; hidden clips; auto adds scrolling only when needed; scroll reserves scrolling behavior even when content fits. Prefer auto for content users must still reach.
60 Element selectors target a tag name A selector such as h2 matches every h2 element. Use it for broad defaults that should apply to every instance of an element.
61 Class selectors create reusable styles A selector such as .card matches every element with class="card". Prefer classes for reusable component and utility styles.
62 Descendant selectors use ancestry A selector such as .card img matches every img anywhere inside an element with class card. Keep descendant selectors short so they remain easy to override.
63 Attribute selectors match attributes A selector such as input[type="email"] matches inputs whose type is email. They are especially useful for distinguishing form controls.
64 Commas group selectors A selector list such as h1, h2, h3 applies one declaration block to every listed selector and avoids duplicated CSS. :is() groups the same way inside a larger selector (e.g. nav :is(a, button):hover).
65 static keeps normal flow position: static is the default. The element stays in normal flow, and offset properties do not move it.
66 relative preserves layout space A relatively positioned element keeps its original place in normal flow, while offsets move only its rendered box. It can also establish the containing block for absolute descendants.
67 absolute leaves normal flow An absolutely positioned element no longer reserves layout space. It uses the nearest positioned ancestor as its containing block, or an initial containing block when none exists.
68 fixed follows the viewport A fixed element normally stays at the same viewport location while the document scrolls. Reserve space and test zoom so it does not hide content or controls.
69 sticky needs a threshold A sticky element participates in normal flow until scrolling reaches an offset such as top: 0. Ancestor overflow and available scroll space affect whether it sticks.
70 z-index controls intentional overlap Positioned or layered elements with a larger z-index appear above lower layers within the same stacking context. Prefer a small documented scale instead of arbitrary huge values.
71 Stacking contexts contain z-index A child cannot use a large z-index to escape its ancestor’s stacking context. Compare ancestors when a z-index seems ineffective. Use isolation: isolate on a section root to create a local stacking context without changing layout.
72 Use one primary main Put the page’s unique primary content in one visible main. Repeated site navigation, page headers, and page footers normally remain outside it.
73 section groups a theme Use section for a thematic group that normally has a heading. Do not use it as a generic styling wrapper.
74 article stands independently Use article for content that can make sense on its own or be reused, such as a post, product card, review, or news item.
75 nav identifies major navigation Wrap major navigation link groups in nav. Label multiple navigation regions so users can distinguish them.
76 header and footer follow their scope At page level they introduce or conclude the document; inside a section or article they introduce or conclude that nearest piece of content.
77 aside is complementary Use aside for related but nonessential content. Visual placement in a sidebar does not by itself make content an aside.
78 Use figure for a referenced unit Group media with its caption in figure and figcaption when they form one self-contained unit referenced by the surrounding content.
79 Prefer native meaning over redundant ARIA Choose the correct HTML element first. Do not add a role that merely repeats the element’s built-in semantics.
80 Keep headings logical Use headings to describe the document hierarchy, not to obtain a particular font size. Keep one <h1> per page, never skip levels (e.g. h2h4), and use paragraphs for ordinary body copy.

Semantic HTML

Semantic HTML communicates what content means and how regions relate. It does not prescribe a visual design; CSS can restyle semantic elements without removing their meaning.

Use this decision order:

Content relationship Element
Unique primary page content main
Thematic group with a heading section
Independently meaningful or reusable item article
Major navigation link group nav
Introductory content for a page, section, or article header
Closing metadata for a page, section, or article footer
Complementary content aside
Media and caption that form one unit figure + figcaption
No accurate semantic relationship div

A page should normally have one visible main. A section usually needs a heading, while an article should still make sense when separated from the surrounding page. Headers and footers are scoped by where they are nested.

Use one <h1> for the page’s primary title. Nest headings without skipping levels — an h2 is followed by h3, not h4. Skipping (for example h2h4) treats heading level as a font-size shortcut and breaks the outline assistive technology exposes.

Multiple navigation regions need distinct accessible names:

<nav aria-label="Primary navigation">...</nav>
<nav aria-label="Related articles">...</nav>

Use native elements instead of duplicating their semantics:

<main>...</main>

Do not write <div role="main"> when main itself is available, and do not add role="navigation" to nav. ARIA is useful when native HTML cannot express the needed name, state, or relationship; it is not a replacement for choosing the correct element.

Common CSS selectors

Selectors appear before the opening brace of a CSS rule and decide which HTML elements receive its declarations. Start with these common forms:

Selector type Example What it matches
Element h2 Every h2 element
Class .card Every element with class="card"
Descendant .card img Every img inside .card
Attribute input[type="email"] Email inputs
Grouped h1, h2 Every h1 and every h2

Prefer simple classes for reusable styles. Use descendant selectors when the ancestor is an important part of the context, and group selectors when they share the same declarations.

Positioning and stacking

Normal flow should remain the default. Position an element only when its visual relationship cannot be expressed clearly by ordinary document flow or layout.

Value Flow behavior Positioned relative to
static Remains in normal flow Normal layout; offsets are ignored
relative Keeps its original space Its normal position
absolute Leaves normal flow Nearest positioned ancestor
fixed Leaves normal flow Usually the viewport
sticky Keeps flow space, then sticks Its scroll container and offset threshold

Offsets (top, right, bottom, and left) describe where a positioned edge should sit. Avoid setting opposing offsets unless the intended size behavior is clear.

For an anchored badge, position the parent and then position the badge:

.card {
  position: relative;
}

.badge {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
}

For sticky positioning, provide a threshold:

.section-nav {
  position: sticky;
  top: 0;
  z-index: 10;
}

z-index matters only when elements can overlap, and its comparison is bounded by stacking contexts. Start with source order, then use a small scale such as content 0, sticky navigation 10, and fixed utility controls 20. Do not use values such as 999999 as a substitute for understanding the relevant ancestors.

When a section contains layered decoration (absolute media, accents, floating UI), create a local stacking context on that section root with isolation: isolate. Internal z-index values then stay local and cannot paint over a neighbouring section.

CSS specificity

Specificity is the browser's way of deciding which CSS rule should win when more than one rule tries to set the same property on the same element.

A useful beginner order is:

Selector type Example Relative strength
Element p Low
Class / attribute / pseudo-class .card, [type="text"], :hover Medium
ID #hero High
Inline style style="color: red" Very high
p {
  color: black;
}

.notice {
  color: blue;
}

#warning {
  color: red;
}
<p id="warning" class="notice">Important</p>

The text is red because the ID selector is more specific than the class and element selectors.

If specificity is equal, the rule written later wins:

.card { color: blue; }
.card { color: green; } /* wins */

Prefer simple class-based styling. Avoid fighting specificity with very long selectors or !important unless you have a clear reason.

Grouping elements and selectors

There are two related ideas worth separating:

Grouping HTML content

Use containers to group related content. Prefer semantic elements when they describe what the group means:

<section class="services">
  <h2>Services</h2>
  <p>What we offer.</p>
</section>

Use div when you need a generic grouping box and no semantic element fits:

<div class="card-actions">
  <button>Save</button>
  <button>Cancel</button>
</div>

Use span when you need to group or style part of a line without creating a new block:

<p>Total: <span class="price">$99</span></p>

Grouping CSS selectors

If several selectors share the same declarations, separate them with commas:

h1,
h2,
h3 {
  font-family: Georgia, serif;
}

/* Same idea with :is() when the list sits inside a larger selector */
nav :is(a, button):hover {
  color: #0e7490;
}

This keeps CSS DRY and prevents repeated declarations. :is() takes the specificity of its most specific argument, so prefer simple arguments.

Pseudo-classes

Pseudo-classes style an element in a special state or position. Write them with a colon: button:hover, input:focus, li:first-child.

Style the default rule first, then add pseudo-class overrides. Live demos: pseudo-classes/.

Interaction states

Pseudo-class When it applies Typical use
:hover Pointer is over the element Buttons, links, cards
:focus Element is focused (Tab / click into field) Inputs, buttons, links — visible focus for a11y
:active Element is being pressed Brief “pressed” look on buttons
:visited Link has been visited a color after the user opens it

button {

  background: #0e7490;

  color: #ecfeff;

}

button:hover {

  background: #155e75;

}

button:active {

  background: #0f766e;

}

input:focus {

  border: 2px solid #0e7490;

  background: #ecfeff;

}

a:visited {

  color: #6b21a8; /* browsers may restrict other properties */

}

Tips:


/* Font grows on hover */

.grow:hover {

  font-size: 20px;

}

/* Background image swaps on hover */

.photo-card:hover {

  background: url("other.jpg") center center no-repeat;

  background-size: cover;

}

/* Swap visible text with two spans */

.btn .alt {

  display: none;

}

.btn:hover .main {

  display: none;

}

.btn:hover .alt {

  display: inline;

}

Structural (position among siblings)

Pseudo-class When it applies Typical use
:first-child Element is the first child of its parent Emphasize the first list item or card
:nth-child(odd) / :nth-child(even) Odd or even children Zebra-stripe rows
:nth-child(3) The 3rd child Spot-target one item

.list li:first-child {

  font-weight: 700;

}

.list li:nth-child(odd) {

  background: #f8fafc;

}

.list li:nth-child(even) {

  background: #dceaf7;

}

Document language (lang)

Every page should open with a language on the root element:


<!DOCTYPE html>

<html lang="en">

Match the code to the content (en, fil, ja, …). If a passage is in another language, you can set lang on that element too.

Circular photos

To make an image look round (avatars, profile shots):

  1. Set a width (and usually the same height) so the box is square

  2. Set border-radius: 50% — half of each side curves into a full circle


.avatar {

  width: 160px;

  height: 160px;

  border-radius: 50%;

}

If width and height differ, 50% makes an ellipse, not a perfect circle. Prefer a square box for circular photos.

Simple cool tricks

Handy one-liners and small patterns (live demos: special/tricks.html):

Trick Recipe Also see
Circular photo Square width/height + border-radius: 50% Rule 33
Pill button Padding + border-radius: 999px Rule 34
Soft card lift box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) Rule 35
Full-bleed band / breakout Full-width band, or 4-track grid with gutter breakout Rule 36
Centered page column width + margin: 0 auto Rule 3
Truncate text overflow: hidden; white-space: nowrap; text-overflow: ellipsis Rule 37
Soft square border-radius: 12px24px Rule 38
Tinted / readable photo text Overlay div or layered background Rule 30
Halo text text-shadow: 0 0 5px black Rule 31
Even icon/item row display: flex + justify-content: space-between or center Rules 7–8
Skip decorative images alt="" Rule 18
Same-size thumbnails Fixed width and height on each img Rule 39
Accent a word <span class="accent">…</span> inside the sentence Rule 25
Two-tone sections Alternate background classes Rule 40
Visual page anchor High-contrast header/nav band Rule 41

Flexbox

Set display: flex on a parent. Only its direct children become flex items.

Main axis vs cross axis

flex-direction Main axis (→ justify-content) Cross axis (→ align-items)
row (default) left → right top ↕ bottom
row-reverse right → left top ↕ bottom
column top → bottom left ↔ right
column-reverse bottom → top left ↔ right

.row {

  display: flex;

  flex-direction: row; /* main axis horizontal */

}

.stack {

  display: flex;

  flex-direction: column; /* main axis vertical */

}

justify-content (main axis)

Value Effect
flex-start Pack toward the start of the main axis
flex-end Pack toward the end
center Center along the main axis
space-between First at start, last at end; equal gaps between
space-around Equal space around each item (half-size at edges)
space-evenly Equal space everywhere, including edges

align-items (cross axis)

Value Effect
stretch Items fill the cross size (default)
flex-start Align to the start of the cross axis
flex-end Align to the end
center Center on the cross axis
baseline Align text baselines

To center a group both ways inside a tall/wide box:


.stage {

  display: flex;

  justify-content: center; /* main */

  align-items: center;     /* cross */

  height: 200px;

}

gap


.row {

  display: flex;

  gap: 16px; /* space between items only */

}

gap does not add padding on the outside of the container. Live demos: flexbox/01-playground.html.

Overlay for background contrast

Photo heroes and posters look great with background-size: cover, but bright/busy areas can wash out text. Put a translucent layer on top of the image, then put your content on that layer.

Option A — nested overlay div (clear and easy to tune):


<div class="hero">

  <div class="hero-overlay">

    <h1>Title</h1>

  </div>

</div>


.hero {

  background: url("photo.jpg") center center no-repeat;

  background-size: cover;

}

.hero-overlay {

  padding: 48px 24px;

  background: rgba(15, 23, 42, 0.65); /* dark scrim */

  color: #f8fafc;

}

Option B — layered background (image + gradient scrim in one box):


.hero {

  background:

    linear-gradient(rgba(15, 23, 42, 0.65), rgba(15, 23, 42, 0.65)),

    url("photo.jpg") center center no-repeat;

  background-size: cover, cover;

  color: #f8fafc;

}

Use a light overlay (rgba(255, 255, 255, 0.75)) when the text is dark. Re-check contrast after you pick the opacity.

text-shadow

text-shadow paints a shadow behind glyphs. The common form is:


text-shadow: offset-x offset-y blur-radius color;

Part Meaning Example in 0px 0px 5px black
offset-x Horizontal shift (positive = right) 0px (no side shift)
offset-y Vertical shift (positive = down) 0px (no up/down shift)
blur-radius How soft/wide the shadow is 5px
color Shadow color black

When background/text contrast is weak (busy photo, similar colors), zero the offsets and use a higher blur so the shadow acts like a soft halo or outline around the letters:


/* Soft readable glow — offsets zeroed, blur does the work */

h1 {

  color: #ffffff;

  text-shadow: 0px 0px 5px black;

}

/* Stronger haze on a very busy image */

h1 {

  text-shadow: 0 0 8px rgba(0, 0, 0, 0.9);

}

Light text usually needs a dark shadow; dark text usually needs a light shadow (0 0 6px white). You can stack multiple shadows if needed. Still aim for solid contrast with an overlay when possible (rules 2 and 30).

div vs span

Tag Default display Use it when…
div block You need a box/section for layout: page wrapper, card, nav group, row.
span inline You need to style part of a sentence without starting a new line.

*<!-- layout chunk → div -->*

<div class="card">...</div>

*<!-- phrase inside text → span -->*

<h3>Hello, <span class="accent">Alex</span></h3>

How inherit works

Most text properties (color, font-family, font-size) already inherit. inherit forces any property to copy the parent:


body {

  color: #1a1a1a;

  font-family: "Georgia", serif;

}

/* Links often keep a browser-blue color — inherit pulls the parent's color */

a {

  color: inherit;

}

/* Non-inherited properties can also inherit if you ask */

.child {

  background: inherit; /* same background as parent */

}

Set shared styles on a parent (body / .page), let children inherit, and only override when needed (rules 11–12).

Google Fonts

  1. Pick a font on fonts.google.com.

  2. Add the provided <link> tags in <head> (often a stylesheet link; preconnect links help too). Do not load fonts with CSS @import — that waits for the stylesheet first and blocks rendering longer than a <link> in <head>.

  3. Use the family in CSS with backups:


<link rel="preconnect" href="https://fonts.googleapis.com">

<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@400;700&display=swap" rel="stylesheet">


body {

  font-family: "Outfit", Arial, sans-serif;

}

Local TTF / OTF fonts (1001 Fonts and similar)

  1. Download a font from 1001 Fonts (or another licensed source). Read the license; give credit if required.

  2. Put the file in your project, e.g. fonts/MyFont.ttf.

  3. Declare it once in CSS, then use the name:


@font-face {

  font-family: "MyFont";

  src: url("./fonts/MyFont.ttf") format("truetype");

/* OTF example: url("./fonts/MyFont.otf") format("opentype"); */

}

.hero-title {

  font-family: "MyFont", Georgia, serif;

}

Multi-word family names need quotes. Always end with a generic fallback (rule 21).

The complete box model

Every rendered element is a set of nested boxes:

  1. Content — text, images, or child elements

  2. Padding — space between the content and border

  3. Border — the edge surrounding content and padding

  4. Margin — transparent space outside the border

The default sizing mode is content-box:


.card {

  box-sizing: content-box;

  width: 300px;

  padding: 20px;

  border: 2px solid;

}

Its visible width is 300 + 40 + 4 = 344px, before margins.

With border-box, the declared width includes content, padding, and border:


.card {

  box-sizing: border-box;

  width: 300px;

  padding: 20px;

  border: 2px solid;

}

The visible width remains 300px. Margin is always outside that width.

Width constraints


.page {

  box-sizing: border-box;

  width: 100%;

  max-width: 960px;

  min-width: 280px;

  margin: 0 auto;

}

Height constraints


.card {

  min-height: 240px;

}

min-height creates a minimum while still allowing content to make the box taller. Prefer it over a fixed height for text-heavy components.

max-height limits growth, but it does not decide how excess content is handled. Content may spill out unless an appropriate overflow rule is also chosen. Do not use max-height blindly on changing text.

CSS units

Choose a unit based on what should control the size:

Unit Relative to Common use
px A CSS reference pixel Borders, small fixed details, deliberate component limits
% Usually the relevant size of the containing block Fluid widths and proportional layouts
rem The root element’s font size Consistent spacing and type across the page
em Font size in the element’s current context Components that scale with their text
vw 1% of viewport width Viewport-relative widths and display type
vh 1% of viewport height Viewport-height sections

em needs context: for font-size, it is based on the parent’s font size; for many other properties, it is based on the element’s computed font size. Nested em sizing can compound. rem avoids that compounding by always returning to the root.

Modern viewport units

Mobile browser controls can change the visible viewport. Newer units make the intended behavior explicit:

Use dvh for a section that should follow the currently visible height. Use svh when content must fit even while browser controls are visible. Test viewport-sized layouts on mobile.

Overflow

Overflow occurs when content is larger than the dimensions or constraints of its box.

Value Result
visible Default. Content may paint outside the box.
hidden Clips content outside the box. Do not use it to hide information users need.
auto Adds scrolling only when content does not fit. Usually the safest choice for reachable content.
scroll Creates a scroll container even when content fits; scrollbars may remain visible depending on the platform.

.panel {

  max-height: 20rem;

  overflow: auto;

}

A size constraint and overflow answer different questions: the constraint defines how large the box may become; overflow defines what happens to excess content.

Box shorthand (margin, padding, border)

Values go clockwise, starting at the top:

Position Longhand example In margin: 10px 20px 30px 40px
Top margin-top 10px
Right margin-right 20px
Bottom margin-bottom 30px
Left margin-left 40px

So these are equivalent:


margin-top: 10px;

margin-right: 20px;

margin-bottom: 30px;

margin-left: 40px;

/* same as */

margin: 10px 20px 30px 40px;

Two values: margin: 10px 20px

With two values, the first is top and bottom, the second is left and right:

Position Longhand In margin: 10px 20px
Top margin-top 10px
Right margin-right 20px
Bottom margin-bottom 10px
Left margin-left 20px

margin-top: 10px;

margin-right: 20px;

margin-bottom: 10px;

margin-left: 20px;

/* same as */

margin: 10px 20px;

The same top → right → bottom → left order applies to:

Value counts:

Font categories (generic families)

Category What it looks like Common use
serif Letters have small decorative strokes (“feet”) at the ends of strokes. Body text, traditional / print feel
sans-serif Without those feet — cleaner, more geometric letterforms. UI, headings, screen reading
monospace Every character takes the same width (like a typewriter). Code, IDs, aligned columns
cursive Looks like handwriting or calligraphy. Decorative accents (use sparingly)

Pick a named font that matches the category you want, then end the stack with that same generic category.

Web-safe fonts (W3Schools)

Font Generic fallback
Arial sans-serif
Verdana sans-serif
Tahoma sans-serif
Trebuchet MS sans-serif
Times New Roman serif
Georgia serif
Garamond serif
Courier New monospace
Brush Script MT cursive

Example: font-family: Arial, Helvetica, sans-serif;

A useful theme behind all of these: HTML describes the content and its meaning; CSS controls how that content is presented and laid out. Prefer inheritance and shared rules so you repeat less.

Advanced Flexbox

  1. Use flex-wrap: wrap when a row should form additional lines instead of squeezing or overflowing. wrap-reverse reverses the cross-axis line direction, not the source order.
  2. Treat flex-basis as an item’s starting main size before the flex algorithm distributes free space.
  3. Use flex-grow to divide positive free space by relative factors; a value of 0 opts out of growth.
  4. Use flex-shrink to resolve negative free space. Content and minimum-size constraints can limit how far an item shrinks.
  5. Read the common shorthand flex: grow shrink basis in that order. For example, flex: 1 1 14rem means grow 1, shrink 1, basis 14rem.
  6. Use align-self to override cross-axis alignment for one flex item. It does not move an entire flex line.
  7. Use align-content only for multiple wrapped lines with spare cross-axis space. Use align-items or align-self for items within each line.
  8. Keep HTML in a meaningful reading and keyboard order. order changes visual placement only and must not be used to repair poor source order.

Advanced Flexbox separates three decisions: wrapping decides whether new lines form, flexible sizing distributes main-axis space, and alignment controls items or lines on the cross axis. Visual rearrangement is optional; accessible source order is not.

CSS Grid

  1. Use display: grid when rows and columns should work together as a two-dimensional layout. Grid properties apply to the container's direct children.
  2. Define explicit columns with grid-template-columns and explicit rows with grid-template-rows. Grid lines are the numbered boundaries around those tracks.
  3. Use grid-column and grid-row to place an item by start and end lines. A value such as 1 / span 2 starts at line 1 and covers two tracks.
  4. Use grid-template-areas and matching grid-area names when a readable layout map is clearer than line numbers. Every named area must form one complete rectangle.
  5. Keep source order meaningful. Grid placement changes visual position, not reading or keyboard order.
  6. Use repeat() to express repeated track patterns without copying the same track size.
  7. Use minmax() to give a track a useful minimum and flexible maximum, such as minmax(14rem, 1fr).
  8. Inside repeat(), auto-fit collapses empty repeated tracks so existing items can expand; auto-fill preserves the empty tracks.
  9. Use justify-items and align-items to align grid items inside their own grid areas on the inline and block axes.
  10. Use justify-content and align-content to align the whole track collection inside the container. They need spare space to produce a visible result.

Full-bleed breakout (rule 36): a page-wide grid of four columns — outer minmax(0, 1fr) gutters plus two inner content tracks — lets copy sit in a constrained column while an image uses grid-area to spill into a side gutter on wide viewports.

Grid separates track sizing, item placement, and alignment. Item alignment moves boxes inside cells; content alignment moves the track collection inside its container.

Responsive CSS and pseudo-elements

  1. Choose media-query breakpoints where the content needs a different layout. Do not build a breakpoint list from device names.
  2. Prefer a mobile-first base when practical: write a usable narrow layout first, then add @media (min-width: ...) or equivalent range-syntax enhancements such as @media (width >= ...) as space becomes available.
  3. Keep media-query overrides near or after the base declarations they change so the cascade remains easy to follow.
  4. Use max-width: 100% with height: auto when an image should shrink inside its container while preserving its intrinsic proportions.
  5. Use aspect-ratio when the layout needs a predictable image slot. Pair it with an intentional width or height.
  6. Use object-fit: cover to fill an image slot when cropping is acceptable; use contain when the entire image must remain visible.
  7. ::before and ::after generate child boxes around an element's content. They need the content property to appear.
  8. Keep essential words, instructions, status, and controls in HTML. Pseudo-element content is presentation and is not a reliable replacement for accessible document content.

Responsive design starts with content that can adapt, then adds conditional layout changes only where needed. Responsive images protect their containers; pseudo-elements add optional presentation without changing source meaning.

Responsive navigation without JavaScript

  1. Use native details and summary for a simple disclosure menu when JavaScript is not available. The browser provides keyboard operation and exposes the open/closed state to assistive technology.
  2. Give the control an accessible name. Visible Menu text is clearest; when the design requires an icon-only hamburger, use aria-label="Menu" on summary and keep the three lines decorative.
  3. Keep navigation links in meaningful source order. At the content-driven breakpoint, hide the desktop link group and show the disclosure menu so only one navigation set is exposed at a time.
  4. Treat the CSS-only pattern as progressive navigation, not a full application menu. It does not automatically close after a link is chosen or when a user clicks elsewhere; add JavaScript later only when that extra behavior is required.
<details class="mobile-menu">
  <summary aria-label="Menu">
    <span class="hamburger-icon"><span></span><span></span><span></span></span>
  </summary>
  <div class="mobile-menu-panel">
    <a href="#features">Features</a>
    <a href="#pricing">Pricing</a>
  </div>
</details>

Use a media query to keep this disclosure hidden while the full navigation fits, then swap the two presentations when the links need more room. For an icon-only control, list-style: none and summary::-webkit-details-marker { display: none; } remove the native chevron. Every clickable target needs a hit area of at least 24×24 CSS pixels (WCAG 2.2 Target Size Minimum); about 44×44 px remains a comfortable touch target for primary controls. Do not use a hidden checkbox as a substitute for a button: a checkbox communicates form state rather than menu disclosure state.

Accessible forms

  1. Give every form control a visible label. Prefer an explicit label whose for value matches the control's unique id.
  2. Treat placeholders as examples or short hints, never as replacements for labels. Placeholder text disappears during entry and may be missed or misunderstood.
  3. Choose an input type that matches the requested data. Appropriate types can provide suitable mobile keyboards, browser validation, and autofill behavior.
  4. Give every submitted control a meaningful name. In ordinary form submission, successful controls without names do not contribute values.
  5. Use recognized autocomplete tokens when a field requests familiar user information such as a name, email address, telephone number, or address.
  6. Use fieldset and legend to give a shared name to related radio buttons or checkboxes that answer one question.
  7. Keep detailed instructions visible. Associate separate help text with its control using aria-describedby when the relationship would otherwise be unclear.
  8. Prefer native constraints such as required, minlength, maxlength, min, and max before recreating those meanings with ARIA.
  9. Identify required fields and errors in text, not through colour alone. A coloured border can support a message but cannot replace it.
  10. Give every button an explicit type: submit sends the form, reset restores initial values, and button has no default submission action.
  11. Preserve a logical source and keyboard order, and keep focus indicators clearly visible on every interactive control.
  12. Use native inputs, selects, textareas, and buttons instead of rebuilding their behavior with generic elements and ARIA.
<form method="get">
  <label for="email">Email address</label>
  <input id="email" name="email" type="email" autocomplete="email" required>

  <label for="topic">Topic</label>
  <select id="topic" name="topic">
    <option value="accessibility">Accessibility</option>
    <option value="layout">Layout</option>
  </select>

  <label for="message">Message</label>
  <textarea id="message" name="message" aria-describedby="message-help"></textarea>
  <p id="message-help">Include the result you expected.</p>

  <button type="submit">Send</button>
</form>

Accessible forms start with names and relationships, not appearance. Labels name individual controls, legends name groups, help text explains expectations, and native elements provide keyboard behavior and semantics before CSS is added.

Tables and lists

  1. Use ul when item order does not change meaning and ol when sequence, ranking, or count matters.
  2. Put list content inside li elements. A nested list belongs inside the li that owns that subgroup.
  3. Use dl, dt, and dd for directly associated term/description, name/value, or question/answer groups—not merely to indent content.
  4. Use table only for data whose row and column relationships matter. Do not use tables to arrange page layout.
  5. Give each data table a concise caption that identifies its subject or purpose.
  6. Use th for headers and td for data. Visual boldness on a data cell does not create a header relationship.
  7. In a simple table, add scope="col" to column headers and scope="row" to row headers.
  8. Use thead, tbody, and tfoot when rows have those distinct purposes. Row groups organize structure but do not replace header cells.
  9. Keep table source order logical and use colspan or rowspan only when a cell truly covers related columns or rows.
  10. Prefer simple tables. Complex multi-level headers need an explicit, carefully tested association strategy.
  11. On narrow screens, put a wide table inside a labelled overflow: auto wrapper. Do not turn table elements into blocks and destroy their row/column relationships.
  12. Keep list markers when they communicate grouping or sequence. If presentation removes them, provide another visible treatment that preserves that meaning.
<table>
  <caption>Workshop schedule</caption>
  <thead>
    <tr>
      <th scope="col">Time</th>
      <th scope="col">Topic</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">10:00</th>
      <td>Accessible tables</td>
    </tr>
  </tbody>
</table>

Lists describe membership, sequence, or direct associations. Tables describe two-dimensional data relationships. Choose the structure from the content relationship first, then style it without changing what that structure means.

Advanced form controls and status

  1. Use optgroup with a meaningful label when select options need categories. The group label organizes choices but is not itself selectable.
  2. Connect an input's list attribute to a datalist's id. Datalist options are suggestions, not restrictions; users may still enter another valid value.
  3. Match specialized input types to the requested data: search, url, date, number, file, range, and color expose useful browser behavior but still need visible labels.
  4. Use native range constraints such as min, max, and step, and explain required formats or limits in persistent text when browser presentation may vary.
  5. Use accept to help users choose suitable files, not as validation. Validate file type, size, and content on the server.
  6. A hidden input is not interactive and does not need a visible label, but its value is neither secret nor trustworthy. Treat submitted hidden values as untrusted input.
  7. Use output for a calculated result, give it an accessible name, and use its for attribute to identify the controls contributing to that result.
  8. Use progress for completion of a task with a known maximum. Its minimum is always zero; omit value only when progress is genuinely indeterminate.
  9. Use meter for a scalar measurement within a known range, such as a score or storage level. It may define min, max, low, high, and optimum.
  10. State important output, progress, and meter values in text. Native bars and colour changes can support the message but must not be the only way the value or meaning is communicated.
<label for="topic-search">Topic</label>
<input id="topic-search" name="topic" type="search" list="topics">
<datalist id="topics">
  <option value="Accessible forms"></option>
  <option value="Semantic tables"></option>
</datalist>

<label for="course-progress">Course completion</label>
<progress id="course-progress" value="4" max="6">4 of 6</progress>
<span>4 of 6 lessons complete</span>

Specialized controls improve input only when their native meaning matches the content. Preserve visible labels and instructions, expect browser interfaces to vary, validate submitted data on the server, and repeat important visual status as understandable text.

CSS motion

  1. Use transitions for state changes such as hover and focus. Define the base state and changed state, then add a duration greater than zero.
  2. Name each property that should transition instead of using transition: all; explicit properties prevent unrelated future changes from animating.
  3. Give pointer and keyboard users equivalent feedback. If hover and focus represent the same action, style both :hover and :focus-visible. A visible focus indicator must meet WCAG 2.2 Focus Appearance: at least 3:1 contrast against adjacent colours and at least a 2px thick perimeter (or equivalent area). Never remove the outline with bare outline: none / outline: 0 unless the same ruleset supplies that replacement.
  4. translate(), scale(), and rotate() change the rendered box without changing the space it reserves in normal flow. Leave room when transformed content could overlap its surroundings.
  5. Transform functions share one transform value and are applied in sequence. Changing their order can change the final result.
  6. transform-origin sets the point around which scaling and rotation occur; its default is the element's centre.
  7. Use @keyframes when motion needs intermediate stages or runs independently of a state change. Attach the keyframes with animation-name and a duration.
  8. Animation properties control timing, delay, repetition, direction, and fill behavior. Prefer a finite animation and add only the controls the effect needs.
  9. Prefer animating transform and opacity when practical because they usually avoid repeated layout work.
  10. Keep motion brief and purposeful, never make it the only carrier of meaning, and use @media (prefers-reduced-motion: reduce) to remove or reduce nonessential movement.
.button {
  transition: background-color 200ms ease, transform 200ms ease;
}

.button:hover,
.button:focus-visible {
  background-color: #174f52;
  transform: translateY(-0.125rem);
}

@keyframes arrive {
  from {
    opacity: 0;
    transform: translateY(1rem);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .button {
    transition-duration: 0.01ms;
  }
}

Transitions connect known states; transforms change rendered geometry; and keyframes describe multi-step animation. Motion should support an interface's meaning without becoming necessary to perceive or operate it.

CSS variables and colour themes

  1. A CSS custom property begins with two hyphens, such as --color-brand. The declaration stores a value but does not apply that value to a visual property by itself.
  2. Use semantic names that describe a role, such as --color-surface, --color-text, and --color-border. Names such as --blue become misleading when a palette changes.
  3. Declare document-wide values on :root, then read them with var(--property-name) wherever that colour role is needed.
  4. Custom properties participate in the cascade and normally inherit. A declaration on a nearer ancestor can override a value from :root for that ancestor and its descendants.
  5. Override related colour roles together on a theme or component container. Changing only one side of a text/background pair can create unreadable contrast.
  6. Add a fallback with var(--property-name, fallback) when a missing or invalid custom property would otherwise make the whole declaration invalid.
  7. A fallback is not a contrast check. The browser does not use the fallback merely because a valid custom property contains a poorly chosen colour.
  8. Extract values that repeat or represent a clear design role. A custom property for every one-off literal adds indirection without making the stylesheet easier to maintain.
:root {
  --color-surface: #ffffff;
  --color-text: #1f2933;
  --color-brand: #176b73;
  --color-on-brand: #ffffff;
}

.card {
  background: var(--color-surface);
  color: var(--color-text);
}

.card-featured {
  --color-surface: #0d4f56;
  --color-text: #ffffff;
}

.button {
  background: var(--button-background, var(--color-brand));
  color: var(--button-text, var(--color-on-brand));
}

The root palette supplies shared defaults. The featured card overrides values only within its scope, while the button keeps readable defaults if its optional component variables are absent. Re-check contrast and visible interaction states for every palette; variables reduce repetition but do not guarantee accessibility.

Clip-path

  1. Use clip-path to hide parts of an element's paint with a geometric shape. The layout box (space the element occupies) does not shrink to match the visible silhouette.
  2. Start with basic shapes: circle(...), ellipse(...), inset(...), and polygon(...). Leave SVG path() and url(#id) clips for later work.
  3. Percentages in shape arguments are relative to the clipped element's own box.
  4. Keep required text, controls, and instructions inside the visible region. Content clipped away is hard or impossible to perceive.
  5. When clipping a photograph, keep a meaningful alt on the img. The clip is presentation; the image meaning stays in HTML.

Glassmorphism

  1. Glassmorphism is a CSS presentation technique. Ordinary glass panels do not require JavaScript; add JavaScript only when blur or opacity must react dynamically to scrolling, pointer movement, or application state.
  2. Use a translucent background so detail behind the panel can remain partly visible.
  3. Use backdrop-filter: blur(...) to blur content behind a panel. filter: blur(...) instead blurs the element itself and is not a substitute.
  4. Include -webkit-backdrop-filter with the same value for WebKit/Safari compatibility.
  5. Give glass a subtle translucent border, rounded corners, and a restrained shadow so its edge remains visible.
  6. Put visible colour, imagery, gradients, or shapes behind the glass. A blur over a flat, featureless background may be technically active but visually imperceptible.
  7. Text contrast requirements still apply: at least 4.5:1 for normal text and 3:1 for large text. Increase the panel opacity or use a darker surface when the background makes content difficult to read.
body {
  background:
    radial-gradient(circle at 20% 20%, #7657ff, transparent 24rem),
    #080b18;
}

.glass {
  background: rgba(8, 11, 24, 0.65);
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 1rem;
  box-shadow: 0 0.5rem 2rem rgba(0, 0, 0, 0.2);
  color: #ffffff;
  backdrop-filter: blur(0.75rem);
  -webkit-backdrop-filter: blur(0.75rem);
}

The recipe is translucent background + backdrop blur + subtle edge + sufficient contrast. The Prism combined project demonstrates the treatment without JavaScript in combine/16-prism-landing.html.

Admin UI and form presentation

  1. An admin dashboard shell usually separates a sidebar (or top navigation), a topbar with page title and actions, and a main canvas for content.
  2. Prefer a muted page background with white (or tokenized) surfaces for cards and forms so work areas read as raised planes.
  3. Choose one elevation system per product UI: border-only cards, soft shadow without a border, or a hairline border plus a soft shadow. Mixing all three on one screen usually looks inconsistent.
  4. Structure cards with optional header, body, and footer slots. Place overflow actions in the header rather than scattering them through the body.
  5. A metric card typically includes a label, a large value, and a trend line or pill. Communicate increase or decrease with text as well as colour.
  6. An icon well is a fixed square with a soft radius and tinted background beside a metric label. Mark decorative icons with aria-hidden="true" when the label already names the metric.
  7. An operational status strip (counts awaiting action) sits above the KPI row and is not a substitute for metric cards.
  8. Muted secondary text (dates, “vs last month”) uses lower emphasis than body copy while remaining readable against its background.
  9. Keep a radius scale: tighter radii on controls, larger radii on cards, and pill radii only for capsules and trend chips.
  10. An input group is a flex row that joins addons and a field behind one continuous border. Round only the outer corners of the group.
  11. Input-group addons are supplementary. Keep a visible field label (or group name) and connect helpful addon text with aria-describedby when needed.
  12. Soft admin fields often use a thin border, comfortable height (about 2.5rem–2.75rem), and a focus ring from outline or from box-shadow. Never remove every visible focus style.
  13. Size modifiers (small, default, large) should change padding, font size, and height together rather than only the corner radius.
  14. Disabled and readonly fields change background and border together. Do not rely on opacity alone when the value must stay readable.
  15. Form layouts include stacked fields, horizontal label/field pairs that stack on narrow viewports, multi-column grids, and compact inline toolbars.
  16. A switch presentation is still a native checkbox with a visible label. Style the control with CSS; do not rebuild toggle behaviour with empty elements in the HTML/CSS workbook.
  17. Floating labels still use a real label element. Placeholders remain examples, not names.
  18. Validation presentation pairs a border or ring change with persistent text. Do not communicate errors by colour alone.
  19. Dropzone chrome is presentation around a real input type="file". The accept attribute suggests types; servers must still validate uploads.
  20. Star ratings in CSS lessons are radio groups with styled labels so keyboard and assistive technology still work.
  21. Multi-step wizard chrome can mark current and completed steps in HTML. Changing steps and validating each step belongs to JavaScript.

Storefront patterns

  1. A storefront shell separates top navigation, optional category navigation, primary main content, and a site footer. Name each nav region.
  2. Product cards are appropriate browsing units: image, title link, price, and rating or badge text. Do not wrap the whole page in nested decorative cards.
  3. Filter catalogs place labelled fieldsets in an aside beside a product grid and stack the columns on narrow viewports.
  4. Product detail pages compose a gallery and a buy box. Colour and size choices need visible group names; quantity needs a visible label.
  5. Specification and invoice data belong in real tables with captions and headers, not in layout grids pretending to be tables.
  6. Cart and checkout summaries may use sticky positioning, but the summary must remain reachable in source order for keyboard users.
  7. Delivery and payment options are radio groups (or native selects) with helper text. Do not rely on card chrome alone to name the choice.
  8. Account hubs combine profile metrics, static tab chrome, and orders or reviews tables. Status pills use text as well as colour.
  9. Print-friendly invoices hide lesson and site chrome with @media print while keeping address blocks and line-item tables readable.

Admin commerce patterns

  1. Table variant classes (striped, hover, bordered, compact) change presentation only. Keep semantic table structure from Chapter 13.
  2. Ops table chrome includes a toolbar, status pills, scroll wrapper, and optional row-action menus. Native details/summary can provide a static action menu without Bootstrap dropdown scripts.
  3. Search fields and pagination controls may appear as non-functional chrome in CSS lessons. Wiring search, sort, and pages belongs to JavaScript Phase 9.
  4. Add-product layouts use a main details column and a pricing or stock sidebar. Reuse input-group prefixes for currency and vanity URLs.
  5. Shipping fulfilment choices are radio cards with short helper copy describing responsibility and cost.
  6. Admin list pages sit inside the dashboard shell: sidebar, topbar actions, toolbar, data table, and pagination chrome.
  7. Entity detail pages lead with identity and actions, then definition cards, then a related orders or items table.

Travel booking patterns

  1. A travel agency shell separates named primary navigation for booking verticals (such as Hotel, Flight, and Trip), primary main content, and a site footer.
  2. Booking search chrome uses labelled native fields for trip type, places, dates, and travelers. Do not replace those controls with third-party widgets in the HTML/CSS workbook.
  3. Fare catalogs place filter fieldsets in an aside beside result rows that show airline, times, duration, stops, price, and a clear Select action.
  4. Experience detail pages lead with title, price per person, and meta, then overview and itinerary content, with a sticky book box that stays reachable in source order.
  5. Stay detail pages offer room cards with amenities and price notes beside a sticky stay summary; hotel compare pages use a real attribute table, not a layout grid pretending to be a table.
  6. Booking checkout composes guest, house-rule, and payment fieldsets with a sticky booking summary for dates, party, fees, and total.

Landing / hero composition patterns

Named catalog demos live under ui/heroes/ (twenty-three patterns: fifteen foundations plus eight Phase-2 stylistic systems). Phase-2 allow-list and technique vocabulary live in CSS/hero-composition/allowed.md.

  1. A motif kit is two or three reusable shapes (for example teardrop, circle, soft square) plus an optional faint dot-grid utility. Reuse the same shapes as badge, cluster, and frame instead of inventing a new silhouette per accent.
  2. Text on photographic heroes still needs a translucent overlay or scrim between the image and the copy (rules 30–31). Treat text-shadow as a secondary aid, not the only contrast strategy.
  3. Mask photos with border-radius: 50%, organic clip-path, or an SVG blob container so the image has a deliberate footprint. Allow a controlled breakout (about 10–20%) past the mask edge for depth; keep headlines and primary CTAs in the safe unclipped region.
  4. Plan an explicit z-index stack before decorating: field → geometry → media → floating UI → seam-overlapping pills or cards. Without a stack recipe, absolute accents collide and clip unpredictably on narrow viewports.
  5. Dual-tone headlines (accent colour on key words, ink on the rest) and a short accent rule or banner under the H1 sharpen hierarchy without adding extra marketing blocks.
  6. Compound hero widgets—contact pills, vertical social rails, multi-field search hubs, and overlapping feature pills—are valid when they are the named pattern’s job. On ordinary landing tops that are not those patterns, keep the first viewport to brand, one headline, one lede, one CTA group, and one dominant visual.
  7. Prefer soft, wide, low-opacity shadows and light blurred spheres (bokeh) for atmosphere. Avoid harsh multi-layer glow stacks and purple-on-white default themes in this workbook’s studio palette.
  8. A wave or soft shape under the hero is a section exit—a transition into the next band—not a substitute for content hierarchy or for readable type.
  9. Decorative motion and carousel autoplay must honor prefers-reduced-motion. Every catalog hero includes a responsive .hero-nav with a burger at or below 48rem.
  10. Prefer inline SVG <path> elements with Bézier commands (C, Q, S) when a smooth irregular wave or blob is the design idea. Use border-radius or polygon clip-path as simpler CSS approximations while learning. Generators such as freesvgwaves.com (no attribution required) and getwaves.io / Haikei can produce pasteable inline paths; prefer local SVG over hotlinked assets (rule 230). Hero-field SVG waves (agency backgrounds) are distinct from the section-exit wave in rule 225.
  11. Cutout photography places a transparent PNG/WebP (or transparent SVG) over a field or organic shape instead of a rectangular framed photo. Give meaningful subjects real alt text; use alt="" when the cutout is purely decorative and nearby text already carries the meaning.
  12. Document the stack before decorating: field → SVG geometry → cutout/media → copy and UI → seam-overlapping badge. Device mockups often sit on the seam between a light content field and a coloured SVG wave.
  13. Flat illustration heroes may use undraw.co or a local undraw-style SVG under ui/heroes/assets/ (rule 24). Prefer local copies over hotlinked CDN URLs for workbook demos.
  14. Geometric motif heroes can stay CSS-first: circles, small squares, short bars, and rotated lines aligned to a clean grid, with an overlapping badge connecting copy and media columns.
  15. Glossary — Bézier path: SVG curve via control points; organic blob: freeform filled shape behind media; editorial collage: photo cutouts plus vector doodles; geometric motif kit: a short reusable set of CSS shapes; cutout: background-removed subject layered on the page.

Page layout system and naming

  1. Name your page-width container. Define one reusable class with max-width, horizontal centering, and side padding (often fed by --max / --max-width). Compose it onto semantic elements as a second class instead of inventing a new max-width rule per section.
  2. Prefer full-bleed backgrounds on the outer section and constrained content inside the shared container so band colour can run edge to edge.
  3. Adopt one class-naming convention per page or component set. A useful default is block__element with optional block--modifier or is-state classes. Nested chains such as nav__menu__btn appear in the wild but are not strict BEM — prefer flatter element names while learning.
  4. Do not mix flat kebab names, block__element, and kebab-block __ element styles inside the same component without a deliberate reason.
  5. After colour tokens (rules 155–162), you may store spacing, sizing, radius, breakpoint documentation values, and motion timing as custom properties. Prefer a small role-based scale. See Chapter 24 and ui/navbars tokens.
  6. Inline style="--name: value" may pass per-instance data from HTML into CSS (for example animating a bar to width: var(--progress)). Prefer that data channel over rewriting selectors for every numeric instance; still avoid inline styles for ordinary colours and spacing.

Document metadata, performance, and UX laws

  1. Ship a unique <title>, <meta name="description">, favicon (rel="icon"), and Open Graph / Twitter card tags on pages meant for the public web. Add rel="canonical" when URL variants or mirrors exist.
  2. Aim for Core Web Vitals budgets: INP ≤ 200 ms (p75), LCP ≤ 2.5 s, CLS ≤ 0.1. Long tasks over 50 ms harm INP — keep handlers short or yield. Intrinsic width/height on images (already taught) protect CLS. Keep shipped JS toward ≤ 300–400 KB gzipped for interactive pages; this workbook stays far under that by design (no framework/bundler required).
  3. Prefer WebP/AVIF where practical, responsive srcset/sizes or <picture>, and loading="lazy" on below-the-fold images. Keep the LCP image eager.
  4. Consistent Help (WCAG 2.2 SC 3.2.6): if the site offers help (docs, contact, chat), present that mechanism in the same relative order on every page that includes it.
  5. Miller's Law: keep a primary navigation group near ~7 items (about 5 minimum comfort, 9 absolute max). Chunk denser menus into labelled groups rather than one flat list of dozens.
  6. Honour prefers-color-scheme by overriding role tokens inside @media (prefers-color-scheme: dark) (and light if needed). Re-check contrast after each palette. A JS theme switcher is optional later — the media query is enough for system preference.
  7. Use container queries for component layout: set container-type: inline-size on the parent, then @container width rules on descendants. Keep viewport @media for page chrome.

Container queries

  1. Name a container with container-name (or the container shorthand) when more than one containment context nests on the page.
  2. Default the component to a usable narrow layout; enhance inside @container when the parent is wide enough — same mobile-first habit as Chapter 11, scoped to the component.

UX laws (implementable vocabulary)

  1. Fitts' Law: make primary targets large enough and spaced — the UX rationale behind the ≥24×24 px floor (comfortable ≈44×44 px).
  2. Law of Proximity: use gap and margin rhythm so related controls and copy sit closer to each other than to unrelated neighbours.
  3. Law of Common Region: shared background, border, or fieldset marks a group; do not rely on proximity alone when the region must be obvious.
  4. Von Restorff (isolation) effect: break visual uniformity for the one primary CTA — weight, colour, or size — so it is not one peer among many equal buttons.
  5. Serial Position Effect: put the most important items first and last in nav lists, step flows, and option groups; middling items are easier to miss.
  6. Jakob's Law: prefer familiar patterns for carts, menus, forms, and auth — match common affordances unless a clear product reason says otherwise.
  7. Goal-Gradient / Zeigarnik: show progress (steps, meters, or status text) in multi-step flows so unfinished work stays visible and motivating.