Skip to main content

Core Fundamentals

Notes organized by topic, with the corresponding course slides.

Box model​

Every HTML element on the page is a box; most layouts are just rectangles composed together. Each box has four layers.

Box Anatomy

Box model example on CodePen

Box Properties​

Box Properties

A box has two properties: box size and box type.

Box Size​

A box's width and height are resolved in one of two ways:

  • Intrinsic sizing — driven by the content's own requirements.
  • Restricted sizing (course term) — constrained by CSS or the available layout space.

For a normal block-level div, width: auto fills the parent's available width, while height: auto grows with the content.

With a parent height of 400px:

Child's heightResult
autoFits the content; can exceed 400px.
100%400px, even if the text needs more space.
600px600px, exceeding the parent's height.

A parent can affect a child's size even without setting a maximum on it.

Box types and sizing​

The second property is box type: block-level, inline-level, or anonymous.

Block-level boxes​

Box type: Block

Anonymous boxes​

Anonymous box

The browser generates an anonymous box to hold content for layout when no element corresponds to it.

<div>
Hello
<p>World</p>
</div>

Hello is wrapped in an anonymous block box so it can be laid out as a block next to <p>.

  • It exists in the layout tree but adds no node to the DOM.
  • It has dimensions and follows layout rules, but no CSS selector can target it.
  • Anonymous boxes can be block or inline.

"Anonymous" describes how the box is generated; "block" and "inline" describe how it participates in layout.

Mathematics of Block Elements​

Mathematics of Block Elements

The width calculation depends on box-sizing:

  • content-box (default) — width sets only the content area. The rendered width is the sum of every layer: width + padding-left + padding-right + border-left + border-right.
  • border-box — padding and border are included in width. Nothing extra to add in JavaScript except the margins.

Because of this, teams often apply border-box globally:

*,
*::before,
*::after {
box-sizing: border-box;
}

It simplifies layout math: the width you set is the final rendered width, percentages and fixed padding can coexist without overflowing their container, and adjusting an element's padding never changes its footprint or pushes sibling elements around.

Inline elements​

Inline Elements

Inline elements render like a run of text, flowing left to right and top to bottom. They participate in an inline formatting context (not a block one) and generate inline-level boxes.

Mathematics of Inline Elements​

Mathematics of Inline Elements

Inline elements follow different sizing rules:

  • width and height are ignored entirely.
  • Vertical margins have no effect.
  • Vertical padding does not change the height used for inline layout.

Mathematics of Inline Elements

The layout height comes from the intrinsic height or the line-height. Anything extending past the line box — visible as extra height in the browser console — is ignored in the layout calculation. This is called non-context height.

Formatting contexts​

Browser Formatting Context - 1

A formatting context is a "realm" with its own layout rules. When an element enters it, those rules apply — for example, "take up 100% of the parent's width" and "render top to bottom" recreate a block formatting context.

Nested formatting contexts​

Browser Formatting Context - 2

An inner formatting context is isolated from the outer one. Once an element enters it, it follows the inner rules, not the outer layout rules.

Key ideas​

Formatting Context - Key Ideas

  • Isolation — elements inside a context are shielded from the layout rules of outer contexts.
  • Scalability — a new set of layout rules can be introduced as a new context. Flex and Grid are the best-known examples.
  • Predictability — a strict rule set makes element positions predictable.

Becoming the browser: formatting exercise​

Formatting context exercise

Walking the tree and asking, at each element, "does this create a new formatting context?":

inline-block is a special case of a block formatting context — there is no separate "inline-block formatting context".

Browser positioning system​

Normal flow​

Normal Flow

Normal flow renders elements in their natural order — top to bottom, and left to right (or right to left in RTL languages). The position property changes how the browser positions an element; the most useful values are static, relative, and absolute.

Static positioning​

Position: static

The default. Elements render top to bottom and left to right.

Relative positioning​

Position: relative

The browser lays the element out in normal flow, then adjusts its final position with top / right / bottom / left. The offset does not affect other elements — the original space is preserved.

Containing block​

Containing block

A containing block is the reference used to calculate an element's position.

  • For the html element, the reference is the browser viewport.
  • Rules determine when an element establishes a containing block for its descendants — for example, giving a div position: relative makes it the containing block for an absolutely positioned paragraph inside it.

Absolute positioning​

Position: absolute

The element is removed from normal flow and establishes a new stacking context, isolating its changes from the default one. Its final position comes from top / right / bottom / left, measured against its containing block. With no positioned ancestor, that is the viewport, so it lands in the top-left corner.

Stacking contexts and the Z-axis​

Stacking Context

Beyond X and Y, rendering has a Z-axis that matters for layering and 3D transforms. A stacking context is an isolated group of elements with its own layering order. (Stacking contexts later connect to GPU layers.) Applying translateZ to a set of boxes moves them along the Z-axis and stacks them on top of one another.

Reflow and the rendering pipeline​

Reflow

The browser builds two trees from your source:

The render tree then flows through a multi-step pipeline, usually kicked off by JavaScript:

Style and layout are CPU-heavy and run on the rendering thread — triggering reflow too often blocks it. Paint and composite run on the GPU, which is fast at drawing pixels and does not block the rendering thread.

Optimized versus non-optimized animation​

Initial Pipeline and Optimized Pipeline

The CodeSandbox example renders 2,000 rectangles. The optimized pipeline relies mainly on the GPU and holds 60 FPS with no visible lag; the non-optimized one runs the full style → layout → paint → composite path every frame.

Margin and translateY​

4 lines of code: massive difference

The code difference is two lines, but the pipeline cost is not:

Animating margin forces the browser to recompute positions for all 2,000 rectangles each frame (CPU). Animating translateY just moves already-rendered pixels (GPU).

How browsers use the GPU​

The example: four absolutely positioned divs that slightly overlap.

Render objects​

Browser Graphics API: Render Object

To render on the GPU, the browser builds a render object tree alongside the DOM. It looks like a one-to-one copy, but the objects hold different information:

  • A DOM element holds the HTML element and its attributes.
  • A render object knows how to draw the element onto a bitmap using a graphics context passed down to it.

Render layers​

Browser Graphics API: Render Layer

  • html is the root element → creates the root render layer.
  • body and main have no special properties → assigned to the root render layer.
  • Each of the four divs is absolutely positioned → each gets its own render layer, attached to the root.

Graphics layers​

Browser Graphics API: Graphic Layer

Browser Graphics API: Graphic Layer

A graphics layer owns a graphics context that draws its render layers. The page needs at least one, created from the root render layer. 3D acceleration (perspective changes, GPU-decoded video, 3D transforms) forces a new graphics layer; without it, render layers share one.

DOM elementRender objectRender layerGraphics layer
html✔root render layergraphics layer 1
body✔root render layergraphics layer 1
main✔root render layergraphics layer 1
div ×4 (absolute)✔render layers 2–5graphics layer 1

So five render layers still share a single graphics layer.

Graphics layers and memory​

Caveats

The single graphics layer uses 8.7 MB of GPU memory here. Their value is targeted optimization: a widget with heavy animation can be pushed onto its own graphics layer so the browser can run it at a very high frame rate (e.g. 120 FPS). But every graphics layer consumes GPU memory and processing resources.

Promoting layers​

Applying a 3D transform brings the total to five graphics layers. The first still uses 8.7 MB; each new one uses more than half a megabyte.

For a list of hundreds of elements, promoting every element to its own graphics layer can immediately consume around 100 MB of GPU memory. The system needs GPU memory too — memory pressure can force swapping and make the app unresponsive. Overusing graphics layers makes an app slower, not faster.

Questions about CSS performance​

The rule of thumb is to minimize reflow: prefer properties that do not trigger the full pipeline. CSS Triggers lists which properties trigger layout, paint, or composite.

Mobile devices​

Much web usage is on mobile, where resources are far more limited than on a powerful desktop. Be deliberate about the layers an app creates — a separate layer can help a highly interactive animated widget, but promoting every element on an otherwise static page causes problems.

CSS transforms and GPU memory​

CSS transforms avoid reflow but consume GPU memory — how to reconcile that?

Favor GPU work over CPU-heavy rendering work. CPU work can block the rendering thread and hurt responsiveness; making an app unresponsive through GPU usage generally takes substantial overuse, whereas a few mistakes in CPU-heavy rendering quickly cause dropped frames.

Becoming the browser, part two​

Let&#39;s become a browser: Part 2

Building every tree together — formatting contexts, in/out of normal flow, stacking contexts, DOM, render objects, render layers, graphics layers.

Steps 3, 5, 6​

Step 3: render section

Step 5: render div with display: inline-block

Step 6: render div with transform attribute

StepElementNew render layer?New graphics layer?New stacking context?New formatting context?
3section with display: flex + flex itemsNoNoNoFlex FC, plus a block FC for each flex item's contents
5div with display: inline-blockNoNoNoNew block FC
6div with absolute positioning and a 3D transformYesYes (3D transform)YesThe FC established by the div, nested inside the new stacking context

An ordinary div does not necessarily create a block formatting context — but a div that is a flex item does get one for its contents.