Category: Design

  • Spacing is a decision. Make it once.

    Spacing is a decision. Make it once.

    Open the stylesheet of almost any young product and search for padding values. You will find 12px, 14px, 15px, 18px, 20px and 22px, often within the same screen. No one chose them. They are the residue of a hundred small eyeball adjustments.

    Each adjustment looked reasonable at the time. Together they make an interface that feels slightly off in a way nobody can name. This article covers how to stop that: define spacing once, as tokens, and let everything else reference it.

    Why eyeballing fails

    Eyeballing works for one page. It breaks when a second page, a second developer, or a mobile layout shows up. Without a shared set of values, every new screen restarts the negotiation.

    The cost is not just visual. A redesign becomes a search-and-replace across hundreds of one-off values. A founder asks for “a bit more room” and a developer has to guess how much, and where.

    A spacing scale removes the guessing. There are only so many valid distances, and you pick from them.

    Why we use a Fibonacci-based scale

    In the Crystal Design System, spacing follows this sequence:

    0, 4, 8, 16, 24, 40, 64, 104, 168, 272

    Look at the pattern. Starting from 8 and 16, each value is the sum of the two before it: 8 + 16 = 24, 16 + 24 = 40, 24 + 40 = 64, and so on. It is the Fibonacci sequence (1, 2, 3, 5, 8, 13, 21, 34) multiplied by a base of 8. The 4 is a half-step for tight spots like an icon next to its label.

    We use it for two practical reasons:

    • Steps grow with size. The gap between 8 and 16 is small. The gap between 104 and 168 is large. Small spaces stay precise, and large spaces separate sections without a dozen near-identical options.
    • Every value relates to the others. Because each step is built from the two before it, neighboring values sit together well, and mixing them on one screen rarely looks arbitrary.

    You do not need Fibonacci specifically. You need a scale with a rule behind it. A plain 4px or 8px multiple scale is a fine choice and far better than no scale.

    How to pick your base unit

    Start with the smallest distance you need to apply consistently. For most products, that is the gap between an icon and its label, or between a label and its input. In our case it is 8px, with 4px as the half-step.

    Then check three things:

    • Does the base divide cleanly into your body line height and your component heights?
    • Does it hold up on a phone, where space is scarcer?
    • Can everyone on the team remember the first four or five values without looking them up?

    If the answer to all three is yes, you have your base. Write it down and stop debating it.

    Write the scale into CSS variables

    Here is the scale as tokens, with a second layer that gives the values meaning:

    :root {
      /* Primitive scale */
      --ac-space-0: 0;
      --ac-space-1: 4px;
      --ac-space-2: 8px;
      --ac-space-3: 16px;
      --ac-space-4: 24px;
      --ac-space-5: 40px;
      --ac-space-6: 64px;
      --ac-space-7: 104px;
      --ac-space-8: 168px;
      --ac-space-9: 272px;
    
      /* Semantic layer */
      --ac-card-padding: var(--ac-space-4);
      --ac-stack-gap: var(--ac-space-3);
      --ac-section-padding: var(--ac-space-7);
    }
    
    .card {
      padding: var(--ac-card-padding);
    }
    
    .section {
      padding-block: var(--ac-section-padding);
    }
    
    .stack {
      display: grid;
      gap: var(--ac-stack-gap);
    }

    The primitive layer holds the scale. The semantic layer says what each value is for. Components only reference the semantic layer.

    Now suppose cards feel cramped. You change --ac-card-padding from --ac-space-4 to --ac-space-5. Every card updates, and nothing else moves. That is what “a change happens in one place” means in practice.

    If you later want a different base, you edit the primitive values and the whole product follows.

    Mistakes we see most in early-stage products

    • One-off values. A 13px here, an 18px there. If a value is not on the scale, either the scale is missing something or the value is wrong. Decide which, then fix it.
    • Tokens named after pixels. A token called --space-16 breaks the moment 16 becomes 18. Use ordinal names like step-3 or semantic names like card-padding.
    • Only defining small values. Teams tokenize padding and forget section spacing. The big gaps between sections drift the most, and they shape the page rhythm.
    • Outer margins on components. A button with built-in margin-top only works in the one place it was first used. Let the parent control spacing with gap or a stack layout.
    • Too many steps. Twenty values is not a scale, it is a free-for-all. Ten is plenty.
    • Copying design-tool numbers verbatim. If a mockup says 22px, round it to the nearest step. The mockup was eyeballed too.

    Make the decision once

    A spacing scale is a small piece of work with a long payoff. An afternoon spent defining ten values and a handful of semantic tokens saves every later conversation that starts with “can we add a little more space here?”

    If you are building a product and the spacing already feels inconsistent, start with an audit. List every distinct padding and margin value in your stylesheet, and see how many you actually need. The answer is usually far fewer than you have.

    If you want a second set of eyes on your tokens, that is work we do at Artasce. Start by sending us your stylesheet.