13 KiB
Non-Color Styling Hooks Guide
Reference for replacing hardcoded spacing, sizing, typography, border, radius, and shadow values with SLDS 2 styling hooks. These hooks use numbered scales with straightforward mappings — unlike color hooks, they rarely require context-based decisions.
Pattern for all replacements:
property: var(--slds-g-[hook], originalValue);
Important: Only replace values that match a hook's actual rendered value. If a hardcoded value falls between two hooks (e.g., 3px when hooks offer 4px and 8px), leave it unchanged. The linter auto-fix handles exact matches; manual fixes should only apply when there's a clear correspondence. Forcing a non-matching value into the nearest hook changes the component's visual appearance.
Critical Rule: Never Invent Hooks
Only use hooks that actually exist in SLDS 2. The linter is the source of truth for which hooks exist and what values they map to. Do not:
- Guess hook names — Hooks like
--slds-g-spacing-medium,--slds-g-font-weight-bold,--slds-g-radius-largedo NOT exist. SLDS 2 uses numbered scales only (e.g.,--slds-g-spacing-4,--slds-g-font-weight-7). - Extrapolate patterns — If you see
--slds-g-spacing-1through--slds-g-spacing-12, do not assume--slds-g-spacing-13exists. Each category has a fixed scale defined by the design system. - Invent semantic names — There are no
--slds-g-spacing-page,--slds-g-font-heading, or--slds-g-shadow-modalhooks. Hooks are numeric, not semantic.
When unsure whether a hook exists: Run the linter (npx @salesforce-ux/slds-linter@latest lint --fix .). It will suggest valid hooks for flagged values. If the linter doesn't flag a value or doesn't suggest a hook, leave it hardcoded.
Table of Contents
- Spacing Hooks
- Sizing Hooks
- Typography Hooks
- Border Width Hooks
- Border Radius Hooks
- Shadow Hooks
- Uplift Decision Tree
- Common Mistakes
- Accessibility Notes
Spacing Hooks
Prefix: --slds-g-spacing-*
Use for: margin, padding, gap, row-gap, column-gap
Do NOT use for: width, height, or other dimension properties (use sizing hooks)
Scale range: 1–12. There is no --slds-g-spacing-13 or higher. If a value exceeds 5rem/80px, leave it hardcoded.
Density-Aware Spacing
For components that adapt between comfy and compact display density, use density-aware variants:
| Hook Pattern | Applies To |
|---|---|
--slds-g-spacing-var-* |
All sides (margin, padding) |
--slds-g-spacing-var-block-* |
Vertical only (top/bottom) |
--slds-g-spacing-var-inline-* |
Horizontal only (left/right) |
Use density-aware hooks for data tables, forms, cards, tabs, and navigation components that need to respond to the user's density preference.
Examples
/* Before */
.card-body { padding: 1rem; }
.list-item { margin-bottom: 0.5rem; }
.grid { gap: 1.5rem; }
/* After — hook names come from the linter, not guesswork */
.card-body { padding: var(--slds-g-spacing-4, 1rem); }
.list-item { margin-bottom: var(--slds-g-spacing-2, 0.5rem); }
.grid { gap: var(--slds-g-spacing-5, 1.5rem); }
/* Multi-value shorthand */
.button { padding: var(--slds-g-spacing-2, 0.5rem) var(--slds-g-spacing-4, 1rem); }
Sizing Hooks
Prefix: --slds-g-sizing-*
Use for: width, height, min-width, max-width, min-height, max-height
Do NOT use for: margin, padding, gap (use spacing hooks)
Scale range: 1–16. There is no --slds-g-sizing-17 or higher.
Examples
/* Before */
.icon { width: 32px; height: 32px; }
/* After */
.icon { width: var(--slds-g-sizing-9, 32px); height: var(--slds-g-sizing-9, 32px); }
Typography Hooks
Font Scale
Prefix: --slds-g-font-scale-* (and --slds-g-font-size-base for 13px)
Use for: font-size
Scale range: neg-4 through 10, plus base (0.8125rem/13px). Negative values (neg-1 to neg-4) are for small/caption text. There is no --slds-g-font-scale-11 or higher.
Density-aware variant: --slds-g-font-scale-var-* (also 1–10) — adapts between comfy and compact.
Font Weight
Prefix: --slds-g-font-weight-*
Use for: font-weight
Scale range: 1–7. Maps to CSS weight values 100–700. There is no --slds-g-font-weight-8 or higher.
Weight pairing guidance in SLDS 2:
- Display text (large scale) → lighter weight
- Titles/headings → regular weight
- Buttons/small body titles → semi-bold weight
- Inline emphasis within body → bold weight (sparingly)
Line Height
Prefix: --slds-g-font-lineheight-*
Use for: line-height
Scale range: 1–6. Values range from 1 to 2. There is no --slds-g-font-lineheight-7 or higher.
Font Family
| Hook | Use Case |
|---|---|
--slds-g-font-family |
Default font family |
--slds-g-font-family-base |
Base font family |
--slds-g-font-family-monospace |
Code snippets |
Content Width
Prefix: --slds-g-sizing-content-* and --slds-g-sizing-heading-*
Use for: max-width on text containers (uses ch units for readable line lengths)
Scale range: content 1–3, heading 1–3.
Typography Examples
/* Before */
.title { font-size: 18px; font-weight: bold; line-height: 1.25; }
.body { font-size: 14px; font-weight: normal; line-height: 1.5; }
/* After — let the linter confirm the correct scale numbers */
.title {
font-size: var(--slds-g-font-scale-4, 18px);
font-weight: var(--slds-g-font-weight-4, bold);
line-height: var(--slds-g-font-lineheight-2, 1.25);
}
.body {
font-size: var(--slds-g-font-scale-1, 14px);
font-weight: var(--slds-g-font-weight-4, normal);
line-height: var(--slds-g-font-lineheight-4, 1.5);
}
Border Width Hooks
Prefix: --slds-g-sizing-border-*
Use for: border-width, border, border-top, etc. (the width component)
Scale range: 1–4. Maps to 1px–4px. There is no --slds-g-sizing-border-5 or higher.
Border widths are NOT density-aware — they stay constant regardless of comfy/compact settings.
SLDS 2 philosophy: Use borders sparingly. Prefer spacing or shadows for visual separation. Use borders purposefully for structure, interactivity indication, and state communication.
Examples
/* Before */
.input { border: 1px solid #ccc; }
/* After */
.input { border: var(--slds-g-sizing-border-1, 1px) solid var(--slds-g-color-border-2, #ccc); }
Border Radius Hooks
Prefix: --slds-g-radius-border-*
Use for: border-radius
Scale range: 1–4 plus special values circle and pill. There is no --slds-g-radius-border-5 or higher.
Choose radius by component type, not by matching px values. The hook resolves to the design-system value; the original value is preserved as fallback only.
| Hook | Components |
|---|---|
--slds-g-radius-border-1 |
Badges, checkboxes |
--slds-g-radius-border-2 |
Text inputs, comboboxes, text areas, tooltips |
--slds-g-radius-border-3 |
Menus, popovers |
--slds-g-radius-border-4 |
Cards, modals, docked composers |
--slds-g-radius-border-circle |
Buttons, button icons, avatars, radios, pills |
--slds-g-radius-border-pill |
Pill-shaped elements |
Border radius hooks are NOT density-aware.
Examples
/* Before */
.card { border-radius: 8px; }
.button { border-radius: 50%; }
/* After — chosen by component type, not px value */
.card { border-radius: var(--slds-g-radius-border-4, 8px); }
.button { border-radius: var(--slds-g-radius-border-circle, 50%); }
Shadow Hooks
Prefix: --slds-g-shadow-*
Use for: box-shadow
Scale range: 1–6. Directional variants (-block-start-*, -block-end-*, -inline-start-*, -inline-end-*) use range 1–4. Focus variants (-outline-focus-*, -outset-focus-*, -inset-focus-*, -inset-inverse-focus-*) only have 1.
Match shadow depth to the element's stacking order — higher shadows for elements visually above others:
| Hook | Components |
|---|---|
--slds-g-shadow-1 |
Page headers, joined tables, filter panels, dropdowns, inline edit, slider handles |
--slds-g-shadow-2 |
Menus, docked form footer, docked utility bar, color picker, notifications |
--slds-g-shadow-3 |
Panels, docked composer, tooltips, toasts |
--slds-g-shadow-4 |
Modals, popovers, App Launcher |
Directional Shadows
For components positioned against screen edges:
| Hook Pattern | Direction |
|---|---|
--slds-g-shadow-block-start-* |
Upward |
--slds-g-shadow-block-end-* |
Downward (inherits from base) |
--slds-g-shadow-inline-start-* |
Left |
--slds-g-shadow-inline-end-* |
Right |
Focus Shadows
| Hook Pattern | Use Case |
|---|---|
--slds-g-shadow-outline-focus-* |
Simple outline focus |
--slds-g-shadow-outset-focus-* |
Double ring outset focus (white inner, brand outer) |
--slds-g-shadow-inset-focus-* |
Single ring inset focus |
--slds-g-shadow-inset-inverse-focus-* |
Double ring inset focus (brand inner, white outer) |
SLDS 2 philosophy: Don't apply shadows to base-level components that sit on a surface without covering other components.
Examples
/* Before */
.modal { box-shadow: 0 4px 8px rgba(0,0,0,0.1); }
.dropdown { box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
/* After */
.modal { box-shadow: var(--slds-g-shadow-4, 0 4px 8px rgba(0,0,0,0.1)); }
.dropdown { box-shadow: var(--slds-g-shadow-1, 0 2px 4px rgba(0,0,0,0.1)); }
Uplift Decision Tree — Non-Color
When the linter flags a non-color hardcoded value, follow this process:
Step 1: Run the Linter First
Always run npx @salesforce-ux/slds-linter@latest lint --fix . before manual fixes. The linter handles exact value-to-hook matches automatically. Only proceed to manual fixes for values the linter flags but cannot auto-fix.
Step 2: Density-Aware or Standard?
Only use density-aware hooks if the original value was a variable density token:
--lwc-varSpacingMedium→--slds-g-spacing-var-4--lwc-spacingMedium→--slds-g-spacing-4(non-variable, use standard hook)
Step 3: No Exact Match — Should You Replace?
Shadow: If a shadow hook is nearly identical (e.g., offset differs by 1px), replace with the closest equivalent. Otherwise, leave as-is.
Border Radius: Replace by component type (see table above), not by px value. If the element doesn't match a known component type, leave hardcoded.
Typography: If between two scale values, use the closest. If far outside the available range, leave as-is.
Spacing/Sizing: If within 10% of a hook value, update to the closest hook. Otherwise leave as-is.
Hardcoded numerical/structural values: Never change or remove values like width: 100%, height: 50%, max-width: 200px, flex: 1, height: auto, display: none, line-height: 1.5, or 0. These are layout and structural values, not candidates for hooks. Leave them exactly as they are in the source CSS.
Common Mistakes
-
Inventing hooks that don't exist — This is the most common and damaging mistake. Named hooks (
--slds-g-spacing-medium) and out-of-range numbered hooks do not exist. Always verify with the linter. -
Confusing spacing and sizing — Spacing is for margins/padding/gaps. Sizing is for width/height/dimensions. Using the wrong one makes the value density-unaware or disrupts the grid system.
-
Replacing or removing hardcoded numerical values — Never change
width: 100%,height: 50%,max-width: 200px,flex: 1,height: auto,display: none,line-height: 1.5, or0. These are structural/layout values — do not replace them with hooks and do not remove them. -
Missing fallback values — Always include the original value as fallback:
var(--slds-g-spacing-4, 1rem). Without fallbacks, the component breaks if the hook is unavailable. -
Ignoring density-aware variants — For data-dense components (tables, forms, lists), use
--slds-g-spacing-var-*and--slds-g-font-scale-var-*so spacing and text adapt to comfy/compact settings. -
Using
--slds-c-*or--slds-s-*hooks — Only--slds-g-*(global) hooks are valid for migration. Component and scoped hooks are not for direct use in CSS.
Accessibility Notes
Touch Targets
- Minimum 24x24 CSS pixels for pointer inputs (WCAG 2.2 Level AA)
- Minimum 44x44 for touch inputs (industry standard)
- Use spacing hooks for padding to achieve target sizes on interactive elements
Typography Readability
- Use body-level font scale or larger for primary body text
- Default base font size (13px) is at the lower limit for comfortable reading
- Use a line height of 1.5 as default for body text (WCAG 1.4.12)
- Optimal line length: 45-75 characters (use content width hooks for max-width)
Focus Visibility
- Use appropriate border-width hooks for focus state borders
- Use
--slds-g-shadow-outset-focus-*for focus rings (double-ring pattern visible on any background) - Focus borders must maintain 3:1 minimum contrast with adjacent surfaces
Border Contrast
- Borders must maintain 3:1 contrast ratio with adjacent surfaces
- Use higher-contrast border color hooks for interactive elements
- Use lower-contrast border color hooks for decorative/non-interactive borders