Skip to main content

CSS Box Model

wgpu-html implements the standard CSS box model with content, padding, border, and margin boxes. The box model affects layout geometry (spacing, sizing) and paint (background clipping, border rendering).

Box Model Structure

┌─────────────────────────────────────────────┐
│ margin │
│ ┌───────────────────────────────────────┐ │
│ │ border │ │
│ │ ┌─────────────────────────────────┐ │ │
│ │ │ padding │ │ │
│ │ │ ┌───────────────────────────┐ │ │ │
│ │ │ │ content │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ └───────────────────────────┘ │ │ │
│ │ └─────────────────────────────────┘ │ │
│ └───────────────────────────────────────┘ │
└─────────────────────────────────────────────┘

The three canonical rectangles used throughout the layout and paint systems:

RectangleDefinitionUse
content_rectContent area inside paddingChild layout, inline text flow
border_rectContent + padding + borderPaint box, background positioning
margin_rectBorder + marginFlow spacing, parent's content sizing

Geometry assertions in tests use these three rectangles explicitly.

width and height

The width and height properties set the content-box dimensions by default:

.box {
width: 300px;
height: 200px;
}

Accepted values:

  • <length>: px, em, rem, vw, vh, vmin, vmax, %
  • auto: fills available container width, or sum of children for height
  • calc(): computed lengths
  • min(), max(), clamp(): math function lengths

min-width, max-width, min-height, max-height

These clamp the computed width/height:

.responsive {
width: 100%;
max-width: 800px;
min-width: 320px;
}

.card {
height: auto;
min-height: 200px;
max-height: 500px;
}

Clamping is applied in the layout pass after resolving width/height.

box-sizing

Controls whether width/height include padding and border:

/* Default: width = content width */
.box-content {
box-sizing: content-box;
width: 200px; /* content is 200px wide */
padding: 10px; /* border_rect is 220px wide */
border: 1px; /* border_rect is 222px wide */
}

/* Border box: width = content + padding + border */
.box-border {
box-sizing: border-box;
width: 200px; /* border_rect is 200px wide */
padding: 10px; /* content is 178px wide */
border: 1px; /* content is 176px wide */
}

The layout engine subtracts padding and border from the specified width/height when box-sizing: border-box.

Margin Properties

margin Shorthand

The margin shorthand accepts 1–4 values:

margin: 10px; /* all four sides */
margin: 10px 20px; /* top/bottom, left/right */
margin: 10px 20px 30px; /* top, left/right, bottom */
margin: 10px 20px 30px 40px; /* top, right, bottom, left */

Per-Side Longhands

margin-top: 10px;
margin-right: 20px;
margin-bottom: 30px;
margin-left: 40px;

auto Margins

auto margins enable horizontal centering in block layout:

.centered {
width: 600px;
margin-left: auto;
margin-right: auto;
}

When both left and right margins are auto, the remaining horizontal space is split equally, centering the element.

Padding Properties

padding Shorthand

Same 1–4 value expansion as margin:

padding: 10px;
padding: 10px 20px;
padding: 10px 20px 30px;
padding: 10px 20px 30px 40px;

Percent values are relative to the containing block's width.

Per-Side Longhands

padding-top: 8px;
padding-right: 16px;
padding-bottom: 8px;
padding-left: 16px;

Border Properties

border Shorthand

The border shorthand sets width, style, and color for all four sides simultaneously. Values can appear in any order:

border: 1px solid red;
border: 2px dashed #333;
border: 3px dotted rgba(0, 0, 255, 0.5);

The shorthand fans out to all four per-side longhands during parsing. Missing components leave existing values intact (cascade order: border: 2px solid red; border-top: 4px dashed blue; works correctly).

Per-Side Border Shorthands

border-top: 2px solid blue;
border-right: 1px dashed gray;
border-bottom: 3px double green;
border-left: 1px solid transparent;

Border Longhands

Each side has three sub-properties:

border-top-width: 2px;
border-top-style: solid;
border-top-color: red;

Available border styles:

StyleDescriptionRendering
noneNo borderSkipped
hiddenNo border (table conflict resolution)Skipped
solidSingle solid lineQuad / SDF ring
dashedDashed line segmentsSegment loop / patterned ring
dottedDotted lineSegment loop / patterned ring
doubleTwo solid linesFalls through to solid
groove3D grooved effectFalls through to solid
ridge3D ridged effectFalls through to solid
inset3D inset effectFalls through to solid
outset3D outset effectFalls through to solid

Note: double, groove, ridge, inset, and outset are parsed but rendered as plain solid. Dashed/dotted on rounded boxes follow the curve only when all four corners are uniform-circular; otherwise corners stay bare.

border-radius

wgpu-html implements the full border-radius specification with elliptical (horizontal/vertical) radii and per-corner expansion.

Uniform Radius

border-radius: 5px; /* all corners */
border-radius: 5px 10px; /* top-left+bottom-right, top-right+bottom-left */
border-radius: 5px 10px 15px; /* top-left, top-right+bottom-left, bottom-right */
border-radius: 5px 10px 15px 20px; /* top-left, top-right, bottom-right, bottom-left */

Elliptical Radius

The / separator specifies different horizontal and vertical radii:

border-radius: 10px / 5px; /* h=10px, v=5px all corners */
border-radius: 10px 20px / 5px 10px; /* different h/v per pair */

Per-Corner Longhands

Each corner has separate horizontal (H) and vertical (V) components:

border-top-left-radius: 10px 5px; /* H=10px, V=5px */
border-top-right-radius: 20px;
border-bottom-right-radius: 15px 10px;
border-bottom-left-radius: 5px;

Rendering

Rounded corners are rendered through the SDF (Signed Distance Field) quad pipeline. The shader evaluates per-pixel distance from the rounded rectangle shape for smooth anti-aliased corners. CSS3 corner-overflow clamping is applied: when the sum of two adjacent radii exceeds the box's dimension, both radii are scaled down proportionally.

Code Examples

Complete Box Model Example

.card {
box-sizing: border-box;
width: 300px;

margin: 16px auto; /* vertical 16px, horizontal centering */
padding: 20px 24px; /* vertical 20px, horizontal 24px */
border: 1px solid #ddd;

border-radius: 8px;

background-color: white;
background-clip: padding-box;
}

Layout Effect Diagram

┌────────── margin (16px) ──────────────┐
│ ┌────── border (1px) ───────────────┐ │
│ │ ┌── padding (20px/24px) ────────┐ │ │
│ │ │ │ │ │
│ │ │ content: 300px - 2×1 │ │ │
│ │ │ - 2×24 │ │ │
│ │ │ = 250px │ │ │
│ │ │ │ │ │
│ │ └────────────────────────────────┘ │ │
│ └────────────────────────────────────┘ │
└────────────────────────────────────────┘

margin_rect width: 300 + 32 = 332px
border_rect width: 300px
content_rect width: 300 - 2 - 48 = 250px

Border Style Combinations

.panel {
border-top: 3px solid #2196F3;
border-right: 1px solid #ddd;
border-bottom: 1px solid #ddd;
border-left: 1px solid #ddd;
border-radius: 4px;
}

Shorthand vs Longhand Cascade

.card {
border: 2px solid red; /* sets all four sides */
border-left: 4px dashed blue; /* overrides left side only */
border-top-color: green; /* overrides top color, width/style from shorthand */
}