Recommended by @jejedurden
interface-cheat-sheet
Interface craft rules (UI, animation, typography, colors, accessibility, layout, UI writing) distilled from interfaces.dev/cheat-sheet.
v1, approved on Aug 30, 2026 · 1 file
- name
- interface-cheat-sheet
- description
- Interface craft rules (UI, animation, typography, colors, accessibility, layout, UI writing) distilled from interfaces.dev/cheat-sheet. Use whenever writing, reviewing, or refactoring frontend code, CSS, Tailwind classes, design tokens, components, forms, buttons, links, empty states, or any user-facing copy in a UI. Also use when the user says "interface cheat sheet", "interfaces.dev", "polish this UI", "check the craft", or "make this feel native".
Interface Cheat Sheet
Source: https://interfaces.dev/cheat-sheet (last synced 2026-08-21). Apply these rules when you write or review any UI. Where a rule conflicts with a house rule below, the house rule wins.
House overrides
- No em dash, ever in copy (global engineering rules). The cheat sheet allows one for asides; we do not. Curly quotes, en dash for ranges, and the single ellipsis character stay allowed.
- No gradients unless the project's design system explicitly uses them. The
in oklab/in oklchrule only applies if a gradient already exists. - All user-facing copy goes through i18n keys. Fix the wording in the translation files, never inline.
User Interface
- Use concentric border radius on nested elements (inner radius = outer radius minus the padding).
- Align for optical alignment, not geometric alignment.
- Give images a
1pxoutline, offset by-1px: black at8%opacity in light mode, white at8%in dark mode.
Animation
- Never use
transition: all(Tailwindtransition-all), name the exact properties that change instead. - Slightly scale down buttons to a value between
0.95and0.98when pressed withtransition: scale 200ms ease-out. - Cross-fade icons when they swap. The entering icon scales
0.25→1, opacity0→1and blur4px→0px. The exiting one reverses the same animation. - Use CSS transitions for interactions, because they can be interrupted. Use keyframes for sequences that only run once.
- Disable all transitions when changing theme from light to dark and vice versa.
- Use
will-changeonly for properties that are actually changing:transform,opacityandfilter. - When an element shifts randomly by 1-2px when animating, especially in Safari on iOS, add
will-change: transformto the element. - When animating entrance, stagger elements by group or by individual elements.
- Don't animate high-frequency interactions such as color change of an item on hover in a list.
Typography
- Always use
.woff2on the web, never.ttfor.otf. - Use
font-variant-numeric: tabular-nums(Tailwindtabular-nums) on every value that changes and in tables: timers, counters, prices, data columns. Skip if already monospace. - Cap long-form text at 60–75 characters per line.
- Use
text-wrap: balanceon headings,text-wrap: prettyon descriptions, neither in long-form text. - Use
overflow-wrap: break-wordwhere long words, links or IDs can escape;white-space: nowrapon labels and badges. -webkit-font-smoothing: antialiasedand-moz-osx-font-smoothing: grayscaleonce on the root, never per component.- Store copy in natural case and control the presentation with
text-transform. - Smart punctuation: curly quotes, an en dash for ranges, the single ellipsis character. (No em dash, see house overrides.)
text-underline-position: from-fontwithtext-decoration-skip-ink: auto, so underlines clear the descenders.- Truncated text keeps the full value reachable in a tooltip or an expanded view.
Colors
- Every step in a color palette should have a purpose: page background, component hover, border, solid fill, body text. Don't add steps that nothing uses.
- Components should use semantic tokens (
--color-text-secondary), never primitives (--blue-500). The primitive is the raw value, the token is how the value is used. - Never name a token for its appearance or its first use:
--color-accent-solid, not--color-blue-buttonor--color-sidebar-gray. - Reserve
accentfor the brand color soprimarynever means both the brand and the main body text. - Don't reuse a token from another role just because it's the right color. Add a token for the new role instead.
- Measure contrast against the background the element actually renders on, not the page background.
- Dark mode palette is not the light palette reversed.
- Pick one theme switching mechanism:
prefers-color-schemeor a.darkclass, and use it for every token. - If a gradient exists, you can define its interpolation space:
in oklabfor even brightness,in oklchfor more vivid middle tones, or neither (sRGB, muted midpoint).
Accessibility
- Use semantically correct native elements:
<button>for buttons,<a>for links, never a plain<div>when a native element exists. - Style
:focus-visible; neveroutline: none(Tailwindoutline-none) without a replacement. - Only use
tabindex="0"andtabindex="-1". Positive values break the natural tab order. - Give icon-only buttons a descriptive
aria-labeland never putaria-hidden="true"on a focusable element. - Write alt text by purpose:
alt="Search"on a search button, notalt="magnifying glass". Decorative images getalt="". - Give every input a real
<label>,typeandinputmode. - Never block paste; people paste passwords and one-time codes.
- A tooltip on a
disabledcontrol never opens for keyboard or touch. Put the explanation in visible text next to it, or usearia-disabled="true"to keep the control focusable. - Keep submit enabled until the request starts, then validate on submit:
aria-invalid="true",aria-describedbypointing at the error, focus on the first invalid field. - Use at least a
24x24pxhit-area,44x44pxon touch and40x40pxon desktop where possible. Extended hit areas never overlap. - Use
pointer-events: noneon decorative elements like glows so they never swallow clicks meant for a control. - Put hover styling behind
@media (hover: hover). On touch,:hoversticks after a tap and looks selected. (Tailwind v4 does this by default; v3 needs thehoverOnlyWhenSupportedfuture flag.) - Wrap motion in
@media (prefers-reduced-motion: no-preference)so it only plays for people who haven't asked to reduce it. - Use
role="status"for routine updates androle="alert"only for urgent errors. - For status changes add an icon, a label or an underline. Status changes never use color alone.
- The skip-to-content link is the first focusable element; add
scroll-margin-topon anchored headings.
Layout
- The gap between groups is at least twice the gap inside one:
8pxwithin,16px+ between. - Use logical properties like
margin-inline-startandpadding-inline-end(Tailwindms-/pe-) instead of left and right. - Don't use fixed widths or heights on text containers.
Writing
- Start button labels with a verb: "Save draft" or "Delete project", never "OK!" or a bare "Yes".
- Repeat the consequence in confirmation buttons: "Delete project" next to "Cancel".
- Pick one word per flow and keep it for every step: "Continue" or "Next", never both.
- Describe the destination in link text: "Read docs", never "Click here".
- Capitalize buttons, headings and labels the same way everywhere. Sentence case is the safer default.
- Label toggles with the state they turn on: "Send read receipts", never "Disable read receipts".
- Orient the reader in empty states and offer one next action instead of "No results".
- Address the reader as "you", not "the user".
Review procedure
When asked to apply or check this cheat sheet on a codebase:
- Grep the mechanical violations first, they are cheap and unambiguous:
transition-all,transition: alloutline-none,outline: nonewithout afocus-visiblereplacement next to ittabIndex={[1-9],tabindex="[1-9].ttf,.otffont loadsonClickondiv/spanwithoutroleand key handling<button>with only an icon child and noaria-labelfont-smoothingdeclared outside the root stylesheet<input type="email|tel|number|url|search">withoutinputMode- copy: "OK", "Oui", "Yes", "Click here", "Cliquez ici", "Disable …" as a toggle label, "No results" / "Aucun résultat" with no next action
- Add once, globally, in the root stylesheet if absent: font smoothing on the root,
h1–h3 { text-wrap: balance }, aprefers-reduced-motion: reduceblock,scroll-margin-topon[id]headings. - Fix targeted items by judgment:
tabular-numson prices, timers, counters and data columns;aria-labelon icon buttons;role="status"on live regions. - Leave the structural items (semantic tokens, logical properties everywhere, concentric radii) as a list for the user unless asked to refactor.
- Run lint and type-check before committing.
Use this skill in Claude
- Unzip it into .claude/skills/ in a project, or into ~/.claude/skills/. Claude Code loads it on the next run.
- On claude.ai, open Customize, then Skills, and upload the ZIP.