Protected

Password required

This work is shared selectively. Reach out at karleeboillot@gmail.com if you need access.

Incorrect password — try again

← Fluent Flex
5 min read

Fluent Flex · Chapter 04

Styling

Corner radius, elevation, and stroke — three families with three different internal logics. Radius is algorithmic and tied to component size. Elevation is ordinal because position on the scale matters more than the math between steps. Stroke has explicit role mapping.

11 → 7

Corner radius tokens — irregular progression replaced by 4px base × multiplier

4 → 3

Stroke width tokens — Thickest eliminated, focus ring pattern formally documented

6

Elevation levels — ordinal (lowest → highest), not mathematical

Overview

Three Families, Three Models

The Styling chapter covers three token families that each required a different internal logic. The governing principle from the Flex hub applies here: the naming convention for each family should match how that value is actually reasoned about by a designer.

For corner radius, the math matters — radius should scale with component size, and the relationship between nesting levels should be derivable. For elevation, position on the scale is what matters — whether something is above or below something else — not the specific shadow values between levels. For stroke, intent is what matters — whether a border signals interaction, focus, or decoration is more important than whether it's 1px or 2px.

Family 01

Corner Radius — Algorithmic

V9 had 11 corner radius tokens — borderRadiusNone (0) through borderRadiusCircular (10000px) — with 9 steps in between ranging from 2px to 40px. The progression wasn't consistent: steps were +2 at the small end, then +4, then +8. No formula connected them. Adding a new step required a judgment call, not a derivation.

V9 — Before

11 tokens, irregular progression

Pure size naming (Small, Medium, Large through 6XLarge) — no encoding of component role or nesting. Steps were +2, +4, then +8 — not a consistent ratio. No rule for which components belonged to which radius.

  • Values: 2, 4, 6, 8, 12, 16, 24, 32, 40px + none + circular (10000px)
  • No nesting rules — any component could use any step
  • AI couldn't infer correct radius from component context

Fluent Flex — After

7 tokens, 4px base × multiplier

Each step is a clear multiple of the 4px base unit. Nesting rules encoded in the system: parent containers always use a larger radius than their nested children (staircase principle).

  • Values: 4 (1×), 8 (2×), 12 (3×), 16 (4×), 24 (6×), 28 (7×), circular (9999px)
  • Staircase nesting rule documented — not just a style guide suggestion
  • Component size category → radius step is now inferable
Corner radius scale showing all 7 steps from 4px to circular (9999px), with component size categories labeled alongside each step and the 4px base unit relationship shown
Seven steps on a 4px base. The circular token dropped from 10000px to 9999px — the detail signals intentional derivation over an arbitrary large number.

The staircase principle

A parent container must always use a larger radius than its nested child. A card with rounded corners contains a button with tighter corners; a dialog with large radius contains inputs with smaller radius. This is encoded in the system documentation — not as a suggestion, but as a structural rule.

The before/after is immediately visible: Default Fluent theme uses radiusSmall=2px, Medium=4px, Large=6px, XLarge=8px. Copilot theme uses radiusSmall=6px, Medium=8px, Large=12px, XLarge=16px — the same components, rounder. The theme switch is a scale multiplier, not a redesign.

Button, dropdown, and input menu shown side by side in Default Fluent theme (sharp corners: 2/4/6/8px) and Copilot theme (rounder: 6/8/12/16px), demonstrating the visual difference a radius scale multiplier creates
Same components, two radius scales. Default vs. Copilot — the visual shift is immediate and consistent across every component at once.

"Karlee does an exceptional job at making the extremely ambiguous un-ambiguous. She always looks at a problem and sees how that impacts the system as a whole, building future-proof solutions — whether it be type, corner radii, colours, you name it."

System Shaper Award nomination · Microsoft, 2026

Family 02

Stroke Width — Role-Mapped

V9 had 4 stroke width tokens: Thin, Thick, Thicker, Thickest. Comparative naming without a stated reference point — thick compared to what? Thicker by how much? The names communicate order but not system logic.

Without a governing scale, each component's border weight was a judgment call. The same "Thin" token appeared on interactive borders, dividers, and focus rings — three semantically different uses with no naming distinction between them.

V9 — Before

4 tokens, comparative names

Thin, Thick, Thicker, Thickest — no explicit pixel values, no role mapping. Any token could appear on any surface with no structural signal about appropriateness.

  • No role mapping: interactive borders, dividers, and focus rings shared tokens
  • No explicit values — comparative only
  • Adding a component required a judgment call on every stroke

Fluent Flex — After

3 tokens, role-mapped

Thin (1px), Thick (2px), Thicker (3px). Thickest eliminated. Focus ring pattern formally documented: outer ring = thick (2px), inner ring = thin (1px). The two-layer pattern is baked into the system spec.

  • Thin (1px) — dividers, subtle borders, inner focus ring
  • Thick (2px) — interactive borders, outer focus ring, emphasis
  • Thicker (3px) — strong emphasis, selected state indicators
Stroke width role mapping diagram showing Thin (1px) used for dividers and inner focus ring, Thick (2px) for interactive borders and outer focus ring, and Thicker (3px) for strong emphasis — with the two-layer focus ring pattern illustrated
Each stroke level has a defined role. The two-layer focus ring (2px outer, 1px inner) is formally documented — accessibility intent encoded in the structure.

Focus ring accessibility

The two-layer focus ring pattern — outer ring at thick (2px), inner ring at thin (1px) — creates two-tone contrast between the focus indicator and whatever surface it appears on. This pattern is now formally specified in the system doc, making the accessibility intent explicit in the naming and structure rather than left to per-component interpretation.

Family 03

Elevation — Ordinal

Elevation uses six levels with ordinal naming: lowest through highest. The naming convention here is intentionally different from corner radius — because what matters for elevation isn't the math between steps (the exact shadow values), it's position on the scale. Whether a surface is above or below another surface is the decision; the specific box-shadow values are an implementation detail.

This is the Flex principle applied specifically: the naming convention should match how the value is actually reasoned about. Designers think in terms of layer order ("this panel floats above the content"), not in terms of shadow blur radii. Ordinal names encode the design intent. Mathematical names would encode implementation.

Lowest Inset surfaces, pressed states, recessed regions
Low Cards, contained panels, subtle raised surfaces
Medium Popovers, tooltips, dropdowns
High Dialogs, modals, overlays that fully block the page
Higher Notification toasts, transient layers above modals
Highest Application chrome, top-of-stack persistent surfaces

Under the hood

Shadow Layer Composition

Each elevation level is a composite of up to three rendering layers, emitted as a comma-joined box-shadow value. Every level has a contour and a key; ambient is added from Low upward because the two shallowest tiers are too slight to displace the surrounding scene.

Layer Present at Role
Contour All 6 levels Tight outline hugging the edge — anchors the shape so it reads as discrete even against busy backgrounds
Ambient Low → Highest Soft diffuse halo simulating indirect bounced light — gives the surface volume rather than a flat cast
Key All 6 levels Directional shadow simulating overhead light — the layer that most strongly signals "this surface is floating"

One intentional detail: highest reuses higher's ambient geometry — only the key layer grows between those two. The single shadow color anchor (--gnrc-color-shadow, pure black) means overriding it once retints every shadow in the system.

Corner radius

Valid Nesting Pairs

The staircase principle is formally documented as a nesting table, not just a style guide suggestion. Parent containers must always use a larger radius than their nested children — these are the valid pairings:

Outer radius Valid inner radii
base-300 (12px) base-100 (4px), base-200 (8px)
base-400 (16px) base-100, base-200, base-300
base-600 (24px) base-100, base-200, base-300, base-400
base-700 (28px) base-100, base-200, base-300, base-400, base-600

Looking ahead

What's Next