CEM D3 Shape — Bend (Edge Softness & Corner Roundedness)

Status: Proposed (canonical CEM spec) Last updated: December 19, 2025

Taxonomy placement: D3. Shape & Bend (part of the 7-dimensional CEM token framework)

Companion specs:


Table of Contents

  1. Purpose and scope
  2. Why “bend” (token naming rationale)
  3. CEM alignment principles applied to shape
  4. Minimal bend basis (complexity-compliant)
  5. Semantic endpoints (product-facing contract)
  6. Shape mode knob (brand expression)
  7. Directional and asymmetric patterns
  8. Accessibility and inclusive design requirements
  9. Consumer vocabulary for “round ends” (capsules)
  10. Component mapping
  11. Notes on external systems (adapter-only)
  12. Quick adoption checklist
  13. Governance and versioning

Appendices


1. Purpose and scope

This spec defines shape tokens beyond actions — a consumer-semantic subsystem for edge softness and corner roundedness.

It:

Shape tokens communicate personality and help users understand UI boundaries, groupings, and interactive affordances.

Out of scope: layering/elevation (D4 — see cem-layering), stroke thickness (D5), spacing/insets (D1), and operable/touch geometry (D2) — though shape must integrate with them (see §8 Accessibility section).


2. Why “bend” (token naming rationale)

In CEM terms, bend names the degree to which an edge curves away from a sharp corner. This framing:

Rule: product code should use --cem-bend-* endpoints; implementation primitives (border-radius, elliptical radii, corner pairs, etc.) remain an adapter/implementation detail.


3. CEM alignment principles applied to shape

3.1 Semantic intent first

Developers should apply tokens like:

…and not value-centric names like radius-8 in component code.

This mirrors common design-token practice: values are “primitive/global,” while semantic/alias tokens name where/how a value is used. Keep product code semantic; keep value plumbing in the token layer.

3.2 Bounded variation

A small set of distinct, recognizable bend steps should cover most UI. The range goes from:

CEM applies a “bounded token budget” heuristic: avoid a long ladder of barely-distinguishable bend steps. If you need a new step, justify it by a perceptual difference that survives dense mode, high zoom, and high-contrast overrides.

3.3 Layering (basis → semantic endpoints → adapters)

This keeps complexity low while still supporting multiple libraries.


4. Minimal bend basis (complexity-compliant)

This is the smallest stable basis that supports most UIs without overfitting.

:root {
  /* Sharp = no bend */
  --cem-bend-sharp: 0;

  /* Smooth = small, friendly rounding; bind to D1 dimension scale */
  --cem-bend-smooth: var(--cem-dim-x-small); /* 0.5rem / 8px */

  /*
    Round ends (capsule / pill):
    Semicircle ends require bend = 0.5 * element height.
    Uses --cem-control-height from D2c Controls (cem-controls.xhtml) as default.
    Provide --cem-shape-height where --cem-control-height is not appropriate.
  */
  --cem-bend-round: calc(var(--cem-shape-height, var(--cem-control-height)) / 2);

  /* True circle (avatars): percentage is defined relative to the element box. */
  --cem-bend-circle: 50%;

  /* Active bend used by endpoints that want the "default feel" (mode-switchable). */
  --cem-bend: var(--cem-bend-smooth);
}

Cross-references:

cem-shape-basis
Token Value Description tier
--cem-bend-sharp 0 No bend (sharp corners) required
--cem-bend-smooth var(--cem-dim-x-small) Small, friendly rounding bound to D1 scale (0.5rem / 8px) required
--cem-bend-round calc(var(--cem-shape-height, var(--cem-control-height)) / 2) Round-ends (capsule); resolves to ½ control height required
--cem-bend-circle 50% True circle relative to element box (avatars, dots) required
--cem-bend var(--cem-bend-smooth) Mode-switchable active bend used by endpoints with default feel required

5. Semantic endpoints (product-facing contract)

These are the tokens components should consume.

:root {
  /* Core roles */
  --cem-bend-control: var(--cem-bend);
  --cem-bend-surface: var(--cem-dim-small);       /* 0.75rem / 12px — perceptual container geometry */
  --cem-bend-overlay: var(--cem-bend);            /* menus, tooltips, small popovers */

  /* Common specializations (keep minimal) */
  --cem-bend-field:              var(--cem-bend-control);
  --cem-bend-control-round-ends: var(--cem-bend-round);  /* optional capsule control variant */
  --cem-bend-modal:              calc(var(--cem-dim-large) + var(--cem-dim-xx-small)); /* ~28px — larger overlays */

  /* Media */
  --cem-bend-media:  var(--cem-bend);
  --cem-bend-avatar: var(--cem-bend-circle);
}

Cross-references:

cem-shape-semantic
Token Value Description tier
--cem-bend-control var(--cem-bend) Primary control bend (buttons, segmented controls) required
--cem-bend-surface var(--cem-dim-small) Container/surface bend (cards, panels) — 0.75rem / 12px required
--cem-bend-overlay var(--cem-bend) Small overlays (menus, tooltips, popovers) required
--cem-bend-field var(--cem-bend-control) Text field / select geometry; usually equals control bend recommended
--cem-bend-modal calc(var(--cem-dim-large) + var(--cem-dim-xx-small)) Prominent overlays (dialogs, sheets) — ~28px recommended
--cem-bend-control-round-ends var(--cem-bend-round) Capsule control variant; use only if pill controls are consistent optional
--cem-bend-media var(--cem-bend) Media thumbnails / previews recommended
--cem-bend-avatar var(--cem-bend-circle) Avatar / persona geometry (circle) recommended

6. Shape mode knob (brand expression)

A shape mode knob is an optional product-level control that shifts bend across the UI to express a consistent brand personality. It is intentionally coarse-grained: three modes are usually enough.

6.1 Mode meanings

Mode Product intent Typical bend policy (what changes) Perceived feel
sharp Technical, precise, enterprise Default bend moves toward --cem-bend-sharp; surfaces/overlays may remain slightly bent to preserve grouping and layer separation Formal, authoritative
smooth Balanced, modern (default) Canonical defaults (base --cem-bend-smooth, surfaces at D1 “small”) Friendly, professional
round Consumer, welcoming, approachable Surfaces step up (e.g., D1 “medium”); optional capsule controls via --cem-bend-control-round-ends where the product uses them consistently Warm, inviting

Critical constraint: shape modes must not change meaning. A user should not need to infer state or priority from roundness alone (see §8 Accessibility section).

Implement modes via a theme selector (attribute or class) and override only the base and/or semantic endpoints. Avoid an in-CSS “mode selector variable” (e.g., --cem-shape-mode: round) because CSS cannot branch on it without a preprocessor; it also obscures where the mode is applied.

/* Default / smooth */
:root,
:root[data-cem-shape="smooth"] {
  --cem-bend: var(--cem-bend-smooth);
  --cem-bend-control: var(--cem-bend);
  --cem-bend-overlay: var(--cem-bend);
  --cem-bend-surface: var(--cem-dim-small);
}

/* Sharp */
:root[data-cem-shape="sharp"] {
  --cem-bend: var(--cem-bend-sharp);

  /* Minimum resilience policy (recommended): keep containers slightly bent unless the brand explicitly wants boxy UI */
  --cem-bend-surface: var(--cem-bend-smooth);
  --cem-bend-overlay: var(--cem-bend-smooth);
  --cem-bend-control: var(--cem-bend); /* sharp controls */
}

/* Round */
:root[data-cem-shape="round"] {
  /* Keep the default control bend unless capsules are a deliberate product-wide choice */
  --cem-bend: var(--cem-bend-smooth);

  --cem-bend-surface: var(--cem-dim-medium);
  --cem-bend-overlay: var(--cem-bend-smooth);

  /* Optional: enable capsules consistently (brand decision) */
  /* --cem-bend-control: var(--cem-bend-round); */
  /* --cem-bend-field:   var(--cem-bend-round); */
}

If you introduce more granular local aliases (e.g., card vs page surface), they may also be overridden by the mode selector, but only as pointers to existing endpoints. Do not mint a parallel “mode-specific” token family.

cem-shape-mode-sharp
Token Value
--cem-bend var(--cem-bend-sharp)
--cem-bend-control var(--cem-bend)
--cem-bend-surface var(--cem-bend-smooth)
--cem-bend-overlay var(--cem-bend-smooth)
cem-shape-mode-round
Token Value
--cem-bend var(--cem-bend-smooth)
--cem-bend-surface var(--cem-dim-medium)
--cem-bend-overlay var(--cem-bend-smooth)

6.3 Helper classes (optional; scoped overrides)

If you need one-off local overrides (e.g., a demo page or controlled experiment), helper classes are acceptable, but should not replace theme-level mode selectors.

.cem-bend-smooth { --cem-bend: var(--cem-bend-smooth); }
.cem-bend-round  { --cem-bend: var(--cem-bend-round);  }
.cem-bend-sharp  { --cem-bend: var(--cem-bend-sharp);  }

Prefer overriding semantic endpoints (--cem-bend-control, --cem-bend-surface) rather than the global --cem-bend when working inside components.


7. Directional and asymmetric patterns

7.1 Attachment pattern (one pattern, not many tokens)

When a surface is attached (sheet, drawer), do not round the attached edge.

:root {
  --cem-bend-attached-edge: var(--cem-bend-sharp);
  --cem-bend-free-edge:     var(--cem-bend-modal);
}

/* Example: bottom sheet */
.cem-bottom-sheet {
  border-radius:
    var(--cem-bend-free-edge)
    var(--cem-bend-free-edge)
    var(--cem-bend-attached-edge)
    var(--cem-bend-attached-edge);
}
cem-shape-pattern
Token Value Description tier
--cem-bend-attached-edge var(--cem-bend-sharp) Attached edge of asymmetric surface (drawer, sheet seam) recommended
--cem-bend-free-edge var(--cem-bend-modal) Free edge of asymmetric surface (drawer top, sheet free) recommended

7.2 When to use asymmetric corners

Use asymmetric bend only when it communicates composition:

Do not use asymmetric corners as the sole carrier of meaning or state (see §8 Accessibility section).

7.3 Implementation guidance

7.4 Common recipes

1) Popover attached to a trigger (attached on top, free on bottom)

.cem-popover--attached-top {
  border-start-start-radius: var(--cem-bend-attached-edge);
  border-start-end-radius:   var(--cem-bend-attached-edge);
  border-end-start-radius:   var(--cem-bend-overlay);
  border-end-end-radius:     var(--cem-bend-overlay);
}

2) Segmented / grouped controls (outer corners only)

.cem-segment {
  border-radius: 0; /* inner corners remain sharp */
}

.cem-segment:first-child {
  border-start-start-radius: var(--cem-bend-control);
  border-end-start-radius:   var(--cem-bend-control);
}

.cem-segment:last-child {
  border-start-end-radius: var(--cem-bend-control);
  border-end-end-radius:   var(--cem-bend-control);
}

3) Card header inherits top corners, body stays rectangular

.cem-card {
  border-radius: var(--cem-bend-surface);
  overflow: clip; /* ensure header background respects corners */
}

.cem-card__header {
  border-start-start-radius: var(--cem-bend-surface);
  border-start-end-radius:   var(--cem-bend-surface);
  border-end-start-radius:   0;
  border-end-end-radius:     0;
}

Optional local shorthand (avoid globals): If you need border-radius shorthand, keep it component-scoped and do not encode LTR assumptions into global --cem-bend-start/end variables.


8. Accessibility and inclusive design requirements

Bend is a secondary visual cue. It must never be the only carrier of state, meaning, or instructions.

8.1 Shape must not be the only signal

Do not encode meaning using bend alone (e.g., “rounded = primary” / “square = secondary”) unless there is a redundant cue (color, text, icon, pattern, or stroke).

8.2 High-contrast and forced-colors resilience

High-contrast modes can override fills/shadows and reduce the perceptibility of subtle shape differences. Treat bend deltas smaller than “sharp vs smooth” as non-essential. For critical distinctions:

8.3 Focus indicators must respect the target

Focus rings and outlines must align with the target’s bend, and must remain visible at high zoom and in forced-colors.

Practical guidance (cross-dimension):

Recommended robust pattern (shape-aligned ring in normal mode, resilient in forced-colors):

.cem-focusable:focus-visible {
  /* Baseline indicator that survives forced-colors */
  outline: var(--cem-stroke-focus, 2px) solid transparent;
  outline-offset: var(--cem-stroke-indicator-offset, 2px); /* D5 indicator placement */

  /* Primary ring for normal mode (shape-aligned) */
  box-shadow: 0 0 0 var(--cem-stroke-focus, 2px) currentColor;

  border-radius: var(--cem-bend-control);
}

8.4 Pointer target size and spacing (bend × D2 size × D1 separation)

Round controls can look smaller even when they meet minimum targets. Ensure:

8.5 Bend vs inset readability (bend × D1 padding)

High bend on compact surfaces increases corner curvature and can visually crowd content. When bend increases, step D1 inset up rather than pushing content into the curve.

8.6 Minimum test checklist

Validate under:


9. Consumer vocabulary for “round ends” (capsules)

Recommended consumer-perspective terms (descending literalness):

Canonical endpoint name in this spec: --cem-bend-control-round-ends

If you want an alias, make it a pointer:

--cem-bend-control-capsule: var(--cem-bend-control-round-ends);

10. Component mapping

This section provides a practical “where to bind bend” reference. It is intentionally role-first and maps components to existing CEM endpoints. If a component needs an internal override, implement it as a local alias (component scope), not as new global tokens.

10.1 Action binding

R-D3-ACTION is resolved: D3 Shape owns emission of the action border-radius binding because the value is geometry. D0 Action tokens own action color/state (background / text) only. The binding remains in the --cem-action-* namespace because it is consumed by action components, but its value aliases the D3 control bend endpoint.

:root {
  --cem-action-border-radius: var(--cem-bend-control);
}

.action, button {
  border-radius: var(--cem-action-border-radius);
}
cem-shape-action-bindings
Token Value Description tier
--cem-action-border-radius var(--cem-bend-control) Action component border-radius binding; emitted by D3 Shape because it is geometry required

10.2 Extended component mapping

The mapping below is consistent with common practices across modern systems:

Table: map components to CEM endpoints

Component family Recommended token / basis Rationale (consumer + system)
Buttons --cem-bend-control Standard interactive affordance (default feel)
Icon buttons (circular variants) Local alias → border-radius: var(--cem-bend-circle) Icon buttons often present as circles; use basis circle via local alias (do not mint a global “icon radius”)
FAB Circle variant → --cem-bend-circle; Extended FAB → --cem-bend-control-round-ends Prominent control; circular (classic FAB) or capsule (extended FAB)
Chips / Tags --cem-bend-control-round-ends “Capsule” shape signals lightweight, removable, filter-like affordance
Badges / Counters --cem-bend-smooth (or --cem-bend-control) Small rounding prevents harsh micro-shapes; keep subtle
Text fields / Select --cem-bend-field Field geometry should match the product’s primary control feel
Switches / Toggles Track: --cem-bend-round; Thumb: --cem-bend-circle Track is a pill; thumb is a circle (distinct affordance)
Cards / Panels --cem-bend-surface Container grouping and boundaries
Tables / Dense list rows --cem-bend-sharp (or none) Grid-aligned surfaces should remain formal/structural; avoid decorative rounding
Dialogs / Sheets --cem-bend-modal (+ attachment pattern for sheets) High salience overlays; larger bend supports “layered” reading and separation
Menus / Dropdowns / Popovers --cem-bend-overlay Transient overlays; match default bend feel
Tooltips --cem-bend-overlay Small transient overlay; keep consistent with menus
Snackbars / Toasts --cem-bend-overlay (policy may choose sharper) Notification surfaces should not demand attention via shape alone
Navigation rail / App bar --cem-bend-sharp Structural navigation regions read more stable with sharp edges
Tabs Underline tabs: --cem-bend-sharp; Pill tabs: --cem-bend-control-round-ends Keep minimal unless the design intentionally uses pill tabs
Avatars / Personas --cem-bend-avatar (50%) Circular identity affordance
Media thumbnails --cem-bend-media Gentle rounding to match overall feel without obscuring content edges

10.3 Local alias pattern (preferred for variants)

.cem-icon-button {
  /* local alias: do not mint a global "icon radius" */
  border-radius: var(--cem-bend-circle);
}

.cem-chip {
  border-radius: var(--cem-bend-control-round-ends);
}

11. Notes on external systems (adapter-only)

Many systems use a bounded corner scale and recommend applying it by role:

CEM consumes these patterns at the adapter layer but keeps product code consumer-semantic.


12. Quick adoption checklist

Use this checklist to adopt the bend system with minimal churn and predictable outcomes.

  1. Confirm prerequisites (D1 + D2 are present)

  2. Adopt the bend basis (--cem-bend-*)

  3. Map semantic endpoints to the basis (role-first)

  4. Bind components to semantic endpoints (no raw values)

  5. If needed, introduce a shape mode knob (sharp | smooth | round)

  6. Validate in accessibility and “hard mode” rendering

  7. Lock in governance


13. Governance and versioning

This spec is intended to be adopted as a stable contract between design, engineering, and component libraries. Treat changes using semantic versioning (MAJOR.MINOR.PATCH) with explicit deprecation when feasible.

13.1 What counts as breaking (MAJOR)

Treat as major (breaking) if you:

Business rationale: these changes can silently alter UI boundaries, focus geometry, and density-mode behavior across many components at once.

13.2 What is non-breaking (MINOR / PATCH)

Treat as minor/patch if you:

13.4 Canonical token summary (contract surface)

The table below distinguishes required CEM contract tokens from optional adapter aliases.

Token Category Required Notes
--cem-bend-sharp Bend basis Yes No bend (sharp corners)
--cem-bend-smooth Bend basis Yes Small bend; binds to D1 --cem-dim-x-small
--cem-bend-round Bend basis (geometry) Yes Round-ends (capsule): ½ height
--cem-bend-circle Bend basis (geometry) Yes Circle: 50%
--cem-bend Active alias Yes Mode-switchable default bend
--cem-bend-control Semantic endpoint Yes Primary control bend
--cem-bend-surface Semantic endpoint Yes Primary container/surface bend
--cem-bend-overlay Semantic endpoint Yes Small overlays (menus/tooltips/popovers)
--cem-bend-field Semantic endpoint Recommended Usually equals control bend
--cem-bend-modal Semantic endpoint Recommended Prominent overlays (dialogs/sheets)
--cem-bend-control-round-ends Semantic endpoint (variant) Optional Use only if capsules are a consistent product pattern
--cem-bend-media Semantic endpoint Recommended Media thumbnails/previews
--cem-bend-avatar Semantic endpoint Recommended Avatar/persona geometry (circle)
--cem-bend-attached-edge Pattern token Recommended For asymmetric attachment patterns
--cem-bend-free-edge Pattern token Recommended For asymmetric attachment patterns
--cem-action-border-radius Component binding Yes Action border-radius binding emitted by D3 Shape

Adapter-only (optional) aliases

The following “M3-parity” aliases may be exposed for compatibility, but must not be required by product component code:

If these aliases exist, treat them as adapter surface: renames/removals are breaking for adapter consumers, but should not affect product components if semantic endpoints are followed.


Appendix A — Material 3 shape scale reference (adapter mapping)

This appendix is non-normative: it exists to help adapters map Material 3 shape scales into the CEM bend basis and semantic endpoints.

Material Design 3 defines a corner-radius scale with canonical steps (0/4/8/12/16/28 + “full”), and also introduces additional “increased” steps for larger containers in newer guidance.

A.1 Canonical M3 --md-sys-shape-corner-* steps → CEM

M3 token Typical value CEM mapping (adapter-only) Prefer applying via CEM endpoints Perceived quality
--md-sys-shape-corner-none 0 --cem-bend-sharp attached edges, structural bars (--cem-bend-sharp) Sharp, formal, technical
--md-sys-shape-corner-extra-small 4dp var(--cem-dim-xx-small) rare micro-bend (badges, subtle containers) Barely rounded, subtle
--md-sys-shape-corner-small 8dp --cem-bend-smooth --cem-bend-control, --cem-bend-overlay Slightly soft
--md-sys-shape-corner-medium 12dp var(--cem-dim-small) --cem-bend-surface Balanced friendliness
--md-sys-shape-corner-large 16dp var(--cem-dim-medium) --cem-bend-surface-strong (if you expose it) Noticeably rounded
--md-sys-shape-corner-extra-large 28dp --cem-bend-modal --cem-bend-modal Very soft, approachable
--md-sys-shape-corner-full pill / 50% --cem-bend-round (capsule) and/or --cem-bend-circle (circle) chips, capsule controls, avatars Playful, highly rounded

A.2 Optional M3-parity aliases (adapter-only)

If you want to expose M3-like short aliases for compatibility, define them as aliases to CEM basis and D1 tokens. These are not intended for product component code.

:root {
  --cem-bend-none: var(--cem-bend-sharp);
  --cem-bend-xs:   var(--cem-dim-xx-small); /* ~4dp */
  --cem-bend-sm:   var(--cem-dim-x-small);  /* ~8dp */
  --cem-bend-md:   var(--cem-dim-small);    /* ~12dp */
  --cem-bend-lg:   var(--cem-dim-medium);   /* ~16dp */
  --cem-bend-xl:   var(--cem-bend-modal);   /* ~28dp */

  /* "full" depends on geometry: capsule vs circle */
  --cem-bend-full: var(--cem-bend-round);
}
cem-shape-adapter-aliases
Token Value Description tier
--cem-bend-none var(--cem-bend-sharp) M3-parity: corner-none adapter
--cem-bend-xs var(--cem-dim-xx-small) M3-parity: corner-extra-small (~4dp) adapter
--cem-bend-sm var(--cem-dim-x-small) M3-parity: corner-small (~8dp) adapter
--cem-bend-md var(--cem-dim-small) M3-parity: corner-medium (~12dp) adapter
--cem-bend-lg var(--cem-dim-medium) M3-parity: corner-large (~16dp) adapter
--cem-bend-xl var(--cem-bend-modal) M3-parity: corner-extra-large (~28dp) adapter
--cem-bend-full var(--cem-bend-round) M3-parity: corner-full (capsule) adapter

These rows are not emitted by the default generator output. They are visible to tooling under an explicit adapter opt-in flag. Do not consume these names from product code.

A.3 Notes on validation vs “current” libraries


14. Token manifest index

Source table Section Description
cem-shape-basis §4 Bend basis: --cem-bend-{sharp,smooth,round,circle} plus the active alias --cem-bend
cem-shape-semantic §5 Semantic endpoints: --cem-bend-{control,surface,overlay,field,modal,control-round-ends,media,avatar}
cem-shape-pattern §7.1 Asymmetric pattern tokens: --cem-bend-attached-edge, --cem-bend-free-edge
cem-shape-action-bindings §10.1 Action component geometry binding: --cem-action-border-radius
cem-shape-mode-sharp §6.2 data-cem-shape="sharp" overrides (generator-only; no new tokens)
cem-shape-mode-round §6.2 data-cem-shape="round" overrides (generator-only; no new tokens)
cem-shape-adapter-aliases §A.2 M3-parity aliases (tier adapter; emitted only behind opt-in)

Generator derivation rules:


References

Primary sources

Additional ecosystem references (non-normative)

Local CEM documentation