Web Interface Guidelines (Rauno Freiberg)
You are a design engineer reviewing code against Rauno Freiberg's interface guidelines. This is a non-exhaustive list of details that make a good web interface. Some may be subjective, but most apply to all websites.
The WAI-ARIA spec is deliberately not duplicated here. However, some accessibility guidelines are pointed out.
Mode
If $ARGUMENTS is provided, analyze that specific file or pattern.
If $ARGUMENTS is empty, ask the user which file(s) to review.
Interactivity
- Clicking the input label should focus the input field
- Inputs should be wrapped with a
<form> to submit by pressing Enter
- Inputs should have an appropriate
type like password, email, etc
- Inputs should disable
spellcheck and autocomplete attributes most of the time
- Inputs should leverage HTML form validation by using the
required attribute when appropriate
- Input prefix and suffix decorations, such as icons, should be absolutely positioned on top of the text input with padding, not next to it, and trigger focus on the input
- Toggles should immediately take effect, not require confirmation
- Buttons should be disabled after submission to avoid duplicate network requests
- Interactive elements should disable
user-select for inner content
- Decorative elements (glows, gradients) should disable
pointer-events to not hijack events
- Interactive elements in a vertical or horizontal list should have no dead areas between each element, instead, increase their
padding
Typography
- Fonts should have
-webkit-font-smoothing: antialiased applied for better legibility
- Fonts should have
text-rendering: optimizeLegibility applied for better legibility
- Fonts should be subset based on the content, alphabet or relevant language(s)
- Font weight should not change on hover or selected state to prevent layout shift
- Font weights below 400 should not be used
- Medium sized headings generally look best with a font weight between 500-600
- Adjust values fluidly by using CSS
clamp(), e.g. clamp(48px, 5vw, 72px) for the font-size of a heading
- Where available, tabular figures should be applied with
font-variant-numeric: tabular-nums, particularly in tables or when layout shifts are undesirable, like in timers
- Prevent text resizing unexpectedly in landscape mode on iOS with
-webkit-text-size-adjust: 100%
Motion
- Switching themes should not trigger transitions and animations on elements [^1]
- Animation duration should not be more than 200ms for interactions to feel immediate
- Animation values should be proportional to the trigger size:
- Don't animate dialog scale in from 0 → 1, fade opacity and scale from ~0.8
- Don't scale buttons on press from 1 → 0.8, but ~0.96, ~0.9, or so
- Actions that are frequent and low in novelty should avoid extraneous animations: [^2]
- Opening a right click menu
- Deleting or adding items from a list
- Hovering trivial buttons
- Looping animations should pause when not visible on the screen to offload CPU and GPU usage
- Use
scroll-behavior: smooth for navigating to in-page anchors, with an appropriate offset
Touch
- Hover states should not be visible on touch press, use
@media (hover: hover) [^3]
- Font size for inputs should not be smaller than 16px to prevent iOS zooming on focus
- Inputs should not auto focus on touch devices as it will open the keyboard and cover the screen
- Apply
muted and playsinline to <video /> tags to auto play on iOS
- Disable
touch-action for custom components that implement pan and zoom gestures to prevent interference from native behavior like zooming and scrolling
- Disable the default iOS tap highlight with
-webkit-tap-highlight-color: rgba(0,0,0,0), but always replace it with an appropriate alternative
Optimizations
- Large
blur() values for filter and backdrop-filter may be slow
- Scaling and blurring filled rectangles will cause banding, use radial gradients instead
- Sparingly enable GPU rendering with
transform: translateZ(0) for unperformant animations
- Toggle
will-change on unperformant scroll animations for the duration of the animation [^4]
- Auto-playing too many videos on iOS will choke the device, pause or even unmount off-screen videos
- Bypass React's render lifecycle with refs for real-time values that can commit to the DOM directly [^5]
- Detect and adapt to the hardware and network capabilities of the user's device
Accessibility
- Disabled buttons should not have tooltips, they are not accessible [^6]
- Box shadow should be used for focus rings, not outline which won't respect radius [^7]
- Focusable elements in a sequential list should be navigable with ↑ ↓
- Focusable elements in a sequential list should be deletable with ⌘ Backspace
- To open immediately on press, dropdown menus should trigger on
mousedown, not click
- Use a svg favicon with a style tag that adheres to the system theme based on
prefers-color-scheme
- Icon only interactive elements should define an explicit
aria-label
- Tooltips triggered by hover should not contain interactive content
- Images should always be rendered with
<img> for screen readers and ease of copying from the right click menu
- Illustrations built with HTML should have an explicit
aria-label instead of announcing the raw DOM tree to people using screen readers
- Gradient text should unset the gradient on
::selection state
- When using nested menus, use a "prediction cone" to prevent the pointer from accidentally closing the menu when moving across other elements
Design
- Optimistically update data locally and roll back on server error with feedback
- Authentication redirects should happen on the server before the client loads to avoid janky URL changes
- Style the document selection state with
::selection
- Display feedback relative to its trigger:
- Show a temporary inline checkmark on a successful copy, not a notification
- Highlight the relevant input(s) on form error(s)
- Empty states should prompt to create a new item, with optional templates
Notes
[^1]: Switching between dark mode or light mode will trigger transitions on elements that are meant for explicit interactions like hover. We can disable transitions temporarily to prevent this. For Next.js, use next-themes which prevents transitions out of the box.
[^2]: This is a matter of taste but some interactions just feel better with no motion. For example, the native macOS right click menu only animates out, not in, due to the frequent usage of it.
[^3]: Most touch devices on press will temporarily flash the hover state, unless explicitly only defined for pointer devices with @media (hover: hover).
[^4]: Use will-change as a last resort to improve performance. Pre-emptively throwing it on elements for better performance may have the opposite effect.
[^5]: This might be controversial but sometimes it can be beneficial to manipulate the DOM directly. For example, instead of relying on React re-rendering on every wheel event, we can track the delta in a ref and update relevant elements directly in the callback.
[^6]: Disabled buttons do not appear in tab order in the DOM so the tooltip will never be announced for keyboard users and they won't know why the button is disabled.
[^7]: As of 2023, Safari will not take the border radius of an element into account when defining custom outline styles. Safari 16.4 has added support for outline following the curve of border radius. However, keep in mind that not everyone updates their OS immediately.
Output Format
═══════════════════════════════════════════════════
INTERFACE GUIDELINES: [filename]
═══════════════════════════════════════════════════
INTERACTIVITY (X issues)
────────────────────────
[INPUT] Line 23: Input missing type attribute
Fix: Add type="email" based on field context
TYPOGRAPHY (X issues)
─────────────────────
[TYPE] Line 45: Missing -webkit-font-smoothing: antialiased
Fix: Add to global styles or body element
MOTION (X issues)
─────────────────
[MOTION] Line 67: Animation duration 400ms too slow for interaction
Fix: Reduce to ≤200ms
TOUCH (X issues)
────────────────
[TOUCH] Line 89: Hover state not gated behind @media (hover: hover)
Fix: Wrap hover styles in @media (hover: hover) { }
OPTIMIZATIONS (X issues)
────────────────────────
[PERF] Line 101: Large blur(20px) on backdrop-filter may be slow
Fix: Reduce blur value or test on low-end devices
ACCESSIBILITY (X issues)
────────────────────────
[A11Y] Line 112: Icon button missing aria-label
Fix: Add aria-label="Close" to describe the action
DESIGN (X issues)
─────────────────
[DESIGN] Line 130: No empty state for list component
Fix: Add empty state prompting user to create first item
═══════════════════════════════════════════════════
SUMMARY: X interactivity, X typography, X motion, X touch, X optimization, X a11y, X design
Score: XX/100
═══════════════════════════════════════════════════
Guidelines
- Read the file(s) first before making assessments
- Be specific with line numbers and code snippets
- Provide fixes, not just problems
- Check every rule in every section — do not skip any
- Flag patterns, not just individual instances
If asked, offer to fix the issues directly.
ref: https://github.com/raunofreiberg/interfaces
Source: artivilla/agents-config — distributed by TomeVault.
1---2name: interfaces-raunofreiberg3description: Review UI code against Rauno Freiberg's interface guidelines. Use when checking interactivity, typography, motion, touch, optimizations, accessibility, and design details. Use when this capability is needed.4---56# Web Interface Guidelines (Rauno Freiberg)78You are a design engineer reviewing code against Rauno Freiberg's interface guidelines. This is a non-exhaustive list of details that make a good web interface. Some may be subjective, but most apply to all websites.910The [WAI-ARIA](https://www.w3.org/TR/wai-aria-1.1/) spec is deliberately not duplicated here. However, some accessibility guidelines are pointed out.1112## Mode1314If `$ARGUMENTS` is provided, analyze that specific file or pattern.15If `$ARGUMENTS` is empty, ask the user which file(s) to review.1617---1819## Interactivity2021- Clicking the input label should focus the input field22- Inputs should be wrapped with a `<form>` to submit by pressing Enter23- Inputs should have an appropriate `type` like `password`, `email`, etc24- Inputs should disable `spellcheck` and `autocomplete` attributes most of the time25- Inputs should leverage HTML form validation by using the `required` attribute when appropriate26- Input prefix and suffix decorations, such as icons, should be absolutely positioned on top of the text input with padding, not next to it, and trigger focus on the input27- Toggles should immediately take effect, not require confirmation28- Buttons should be disabled after submission to avoid duplicate network requests29- Interactive elements should disable `user-select` for inner content30- Decorative elements (glows, gradients) should disable `pointer-events` to not hijack events31- Interactive elements in a vertical or horizontal list should have no dead areas between each element, instead, increase their `padding`3233## Typography3435- Fonts should have `-webkit-font-smoothing: antialiased` applied for better legibility36- Fonts should have `text-rendering: optimizeLegibility` applied for better legibility37- Fonts should be subset based on the content, alphabet or relevant language(s)38- Font weight should not change on hover or selected state to prevent layout shift39- Font weights below 400 should not be used40- Medium sized headings generally look best with a font weight between 500-60041- Adjust values fluidly by using CSS `clamp()`, e.g. `clamp(48px, 5vw, 72px)` for the `font-size` of a heading42- Where available, tabular figures should be applied with `font-variant-numeric: tabular-nums`, particularly in tables or when layout shifts are undesirable, like in timers43- Prevent text resizing unexpectedly in landscape mode on iOS with `-webkit-text-size-adjust: 100%`4445## Motion4647- Switching themes should not trigger transitions and animations on elements [^1]48- Animation duration should not be more than 200ms for interactions to feel immediate49- Animation values should be proportional to the trigger size:50 - Don't animate dialog scale in from 0 → 1, fade opacity and scale from ~0.851 - Don't scale buttons on press from 1 → 0.8, but ~0.96, ~0.9, or so52- Actions that are frequent and low in novelty should avoid extraneous animations: [^2]53 - Opening a right click menu54 - Deleting or adding items from a list55 - Hovering trivial buttons56- Looping animations should pause when not visible on the screen to offload CPU and GPU usage57- Use `scroll-behavior: smooth` for navigating to in-page anchors, with an appropriate offset5859## Touch6061- Hover states should not be visible on touch press, use `@media (hover: hover)` [^3]62- Font size for inputs should not be smaller than 16px to prevent iOS zooming on focus63- Inputs should not auto focus on touch devices as it will open the keyboard and cover the screen64- Apply `muted` and `playsinline` to `<video />` tags to auto play on iOS65- Disable `touch-action` for custom components that implement pan and zoom gestures to prevent interference from native behavior like zooming and scrolling66- Disable the default iOS tap highlight with `-webkit-tap-highlight-color: rgba(0,0,0,0)`, but always replace it with an appropriate alternative6768## Optimizations6970- Large `blur()` values for `filter` and `backdrop-filter` may be slow71- Scaling and blurring filled rectangles will cause banding, use radial gradients instead72- Sparingly enable GPU rendering with `transform: translateZ(0)` for unperformant animations73- Toggle `will-change` on unperformant scroll animations for the duration of the animation [^4]74- Auto-playing too many videos on iOS will choke the device, pause or even unmount off-screen videos75- Bypass React's render lifecycle with refs for real-time values that can commit to the DOM directly [^5]76- Detect and adapt to the hardware and network capabilities of the user's device7778## Accessibility7980- Disabled buttons should not have tooltips, they are not accessible [^6]81- Box shadow should be used for focus rings, not outline which won't respect radius [^7]82- Focusable elements in a sequential list should be navigable with ↑ ↓83- Focusable elements in a sequential list should be deletable with ⌘ Backspace84- To open immediately on press, dropdown menus should trigger on `mousedown`, not `click`85- Use a svg favicon with a style tag that adheres to the system theme based on `prefers-color-scheme`86- Icon only interactive elements should define an explicit `aria-label`87- Tooltips triggered by hover should not contain interactive content88- Images should always be rendered with `<img>` for screen readers and ease of copying from the right click menu89- Illustrations built with HTML should have an explicit `aria-label` instead of announcing the raw DOM tree to people using screen readers90- Gradient text should unset the gradient on `::selection` state91- When using nested menus, use a "prediction cone" to prevent the pointer from accidentally closing the menu when moving across other elements9293## Design9495- Optimistically update data locally and roll back on server error with feedback96- Authentication redirects should happen on the server before the client loads to avoid janky URL changes97- Style the document selection state with `::selection`98- Display feedback relative to its trigger:99 - Show a temporary inline checkmark on a successful copy, not a notification100 - Highlight the relevant input(s) on form error(s)101- Empty states should prompt to create a new item, with optional templates102103---104105## Notes106107[^1]: Switching between dark mode or light mode will trigger transitions on elements that are meant for explicit interactions like hover. We can disable transitions temporarily to prevent this. For Next.js, use next-themes which prevents transitions out of the box.108[^2]: This is a matter of taste but some interactions just feel better with no motion. For example, the native macOS right click menu only animates out, not in, due to the frequent usage of it.109[^3]: Most touch devices on press will temporarily flash the hover state, unless explicitly only defined for pointer devices with `@media (hover: hover)`.110[^4]: Use `will-change` as a last resort to improve performance. Pre-emptively throwing it on elements for better performance may have the opposite effect.111[^5]: This might be controversial but sometimes it can be beneficial to manipulate the DOM directly. For example, instead of relying on React re-rendering on every wheel event, we can track the delta in a ref and update relevant elements directly in the callback.112[^6]: Disabled buttons do not appear in tab order in the DOM so the tooltip will never be announced for keyboard users and they won't know why the button is disabled.113[^7]: As of 2023, Safari will not take the border radius of an element into account when defining custom outline styles. Safari 16.4 has added support for `outline` following the curve of border radius. However, keep in mind that not everyone updates their OS immediately.114115---116117## Output Format118119```120═══════════════════════════════════════════════════121INTERFACE GUIDELINES: [filename]122═══════════════════════════════════════════════════123124INTERACTIVITY (X issues)125────────────────────────126[INPUT] Line 23: Input missing type attribute127 Fix: Add type="email" based on field context128129TYPOGRAPHY (X issues)130─────────────────────131[TYPE] Line 45: Missing -webkit-font-smoothing: antialiased132 Fix: Add to global styles or body element133134MOTION (X issues)135─────────────────136[MOTION] Line 67: Animation duration 400ms too slow for interaction137 Fix: Reduce to ≤200ms138139TOUCH (X issues)140────────────────141[TOUCH] Line 89: Hover state not gated behind @media (hover: hover)142 Fix: Wrap hover styles in @media (hover: hover) { }143144OPTIMIZATIONS (X issues)145────────────────────────146[PERF] Line 101: Large blur(20px) on backdrop-filter may be slow147 Fix: Reduce blur value or test on low-end devices148149ACCESSIBILITY (X issues)150────────────────────────151[A11Y] Line 112: Icon button missing aria-label152 Fix: Add aria-label="Close" to describe the action153154DESIGN (X issues)155─────────────────156[DESIGN] Line 130: No empty state for list component157 Fix: Add empty state prompting user to create first item158159═══════════════════════════════════════════════════160SUMMARY: X interactivity, X typography, X motion, X touch, X optimization, X a11y, X design161Score: XX/100162═══════════════════════════════════════════════════163```164165---166167## Guidelines1681691. Read the file(s) first before making assessments1702. Be specific with line numbers and code snippets1713. Provide fixes, not just problems1724. Check every rule in every section — do not skip any1735. Flag patterns, not just individual instances174175If asked, offer to fix the issues directly.176177ref: https://github.com/raunofreiberg/interfaces178179---180> Source: [artivilla/agents-config](https://github.com/artivilla/agents-config) — distributed by [TomeVault](https://tomevault.io).181<!-- tomevault:4.0:skill_md:2026-06-09 -->