# Sanding the interface · Craft

<!-- https://learn-ui.com/chapters/craft/sanding-ui -->

Jim Nielsen describes how he develops in [Sanding UI](https://blog.jim-nielsen.com/2024/sanding-ui/) (September 2024): build something, click around a ton, tweak, click around more, until done. The clicking is the important part.

### Sand until no splinters

For a page transition that means going back and forth every way a person might: back button, context menu Back, in-app navigation, keyboard shortcut. He prefers the woodworking picture to QA: belt sander, then hand sander, then run your hand over it and feel for splinters, “until I finally cannot give myself any more splinters.” That is **sanding UI** (Jim Nielsen's name for using an interface over and over, tweaking after each pass, until no rough interaction remains: sand it, feel the grain, get a splinter, sand again, and repeat until smooth.).

His example: a radio and its label in a flexbox with `gap`, and the gap was a dead spot where clicking did not toggle the control. Removing the gap and padding the label made the whole thing clickable. “Lots of small splinters lead to an agonizing experience.” In [Sanding UI, pt. II](https://blog.jim-nielsen.com/2025/sanding-ui-pt-ii/) (February 2025) a thumbs up/down widget, clicked a lot, selects its SVG as if it were text; one fix is `user-select: none`.

> Figure. CSSJim Nielsen, Sanding UI

Aside

His [Job Screening Blog Post](https://blog.jim-nielsen.com/2024/design-engineer-job-screener/) (November 2024) is two GIFs of a button being clicked. In one the heading shifts up by 1px. “Can you tell the difference between them? Do you care? If not, we might not be a good fit.”

### Focus rings at the declaration level

Rauno Freiberg’s [Crafting the Next.js Website](https://rauno.me/craft/nextjs) sands at the level of CSS declarations. Tab through any site and you find rings in different colours and shapes. His model is the Discord web app: always a custom blue, matching the trigger’s radius, offset with padding, a radius even on links, never clipped by a container. One page is easy; the difficulty is a surface area shared by many teams.

His own **focus ring** (The visible outline a browser or a stylesheet draws around the element that currently has keyboard focus.) is two box-shadows on `:focus-visible`: the first pads the element in the page background colour, the second draws a 2px outline. It assumes the element sits on the app background, barely noticeable when false. `outline` would do, but Safari did not follow the radius until 16.4, and Safari updates are tied to macOS. For links, a 2px radius, 2px of padding, and a negative margin that cancels it improve the focus state even though the radius is invisible until focused.

> Figure. CSSRauno Freiberg, Crafting the Next.js Website

### Quote marks, data attributes, underlines

Two more from Rauno: testimonial quote marks set in Georgia rather than Inter, a detail from the Radix UI site, hung with `text-indent: -0.4em` (credited to Shu); and styling against a `data-variant` attribute instead of mapping variants to class names. Neither shows in a screenshot.

Paco Coursey’s [Custom text underlines](https://paco.me/writing/custom-text-underlines) (2020) sands a single line. With `text-decoration: underline` giving too little control while the CSS Text Decoration Module was pending, he draws the line as a `linear-gradient` background. Move it with `background-position` (`left 1.05em`), thicken it with the height (`100% 0.25em`), hide it around descenders with a `text-shadow` in the background colour (and `text-shadow: none` in `::selection`), dash it with a `repeating-linear-gradient` sized `1ch`, the width of the zero glyph. It wraps across lines.

> Figure. CSSPaco Coursey, Custom text underlines

His [px vs rem in font-size](https://paco.me/writing/px-vs-rem) (2022) turns the same care on a habit: since nearly every site hard-codes a size on `html` or uses `px`, “when browser scaling is ignored, there’s no a11y reason to use rem over px.” The unit is not the virtue; respecting the reader’s setting is.

### Good for who

Sanding has a direction, from Jim’s [Good Design](https://blog.jim-nielsen.com/2022/good-design/) (2022). Design is about intent, so ask: good for who? An unsubscribe button that dodges the cursor is good for whoever wants you subscribed and bad for you. Dribbble shots may be good design if the intent is likes, but “It’s hard to know whether a static picture depicting dynamic software helps a real-world human achieve a particular goal.” Where owner and user diverge, state a priority of constituencies.

So decide who you are sanding for, then use the thing the way they will, through every entry and exit. The agonizing experience is made of the splinters you skipped.
