DEVOURED
Interface Cheat Sheet (Website)
A concise collection of high-impact design engineering best practices for building robust and polished web interfaces.
What: The Interface Cheat Sheet provides specific technical guidance for UI development, including CSS animation techniques, typography standards like prioritizing .woff2, semantic accessibility practices, and robust color token naming conventions.
Why it matters: It codifies the 'last mile' of frontend development—the small, often overlooked technical details that separate professional-grade applications from amateur ones.
Takeaway: Adopt the tip to use 'will-change: transform' on elements that exhibit jittery movement during animations, especially in Safari/iOS.
Deep dive
- Use concentric border radius on nested elements for visual consistency.
- Implement a 1px image outline offset at 8% opacity to maintain clarity in light and dark modes.
- Use CSS transitions for interruptible interactions; reserve keyframes for one-off sequences.
- Disable transitions during theme switches to prevent jarring visual jumps.
- Standardize typography with font-variant-numeric: tabular-nums for data-heavy components.
- Use text-wrap: balance for headings to prevent orphans.
- Utilize semantic color tokens instead of primitive hex values to maintain a design system's integrity.
- Test contrast against the specific background an element renders on rather than a global page color.
- Replace plain divs with native semantic tags like and for better accessibility.
- Wrap motion effects in @media (prefers-reduced-motion: no-preference).
Decoder
- Concentric border radius: Calculating outer and inner corner radii so the gap between nested elements remains visually uniform.
- Semantic token: A design system variable representing a role (e.g., --color-text-secondary) rather than a static color (e.g., --blue-500).
Original article
User Interface
- Use concentric border radius on nested elements.
- 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, 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 you run into an issue with an element shifting 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 invidivual 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-numson every value that changes and in tables: timers, counters, prices, data columns. Skip if you're already using a monospace font. - 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, an em dash for asides, the single ellipsis character.
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. When that role's color changes your element changes with it, so 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. - You can define a gradient's interpolation space: use
in oklabfor even brightness,in oklchfor more vivid middle tones or neither which falls back to sRGB with a classic muted midpoint.
Accessibility
- Use semantically correct native elements:
<button>for buttons,<a>for links, never a plain<div>when you can use a native element. - Style
:focus-visible; don't useoutline: nonewithout 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. Make sure extended hit areas never overlap. - Use
pointer-events: noneon decorative elements like glows and gradients so they never swallow clicks meant for control. - Put hover styling behind
@media (hover: hover). On touch,:hoversticks after a tap and looks selected. - 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 should never use color alone.
- Make sure the skip-to-content link is the first focusable element and 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-endinstead 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”.
Explore all 68 articles in today's digest
Fresh dev news, AI-digested daily. Never miss a trend at devoured.fyi