Skip to main content

Published 2026-03-08 · 3 min read

By Akash Yadav · Frontend Engineer

Tailwind Sizing: Spacing, Type & Tokens

Translate design tokens into Tailwind-friendly thinking: spacing keys, arbitrary values vs scale, REM alignment, and when to bail out to CSS variables.

Tailwind spacing scale explained

Tailwind's spacing scale is deliberately dense at the low end. Most UI rhythm lives between 4px (t-1) and 48px (t-12), so the fine increments at the bottom are a feature. Memorise a handful of anchors and you can rough-cut any layout quickly:

KeyREMpx (at 16px root)Common use
10.25rem4pxIcon gap, tight badge padding
20.5rem8pxInline element gap
30.75rem12pxForm field internal padding
41rem16pxStandard component padding
61.5rem24pxCard padding, section gap
82rem32pxLarge section breathing room
123rem48pxHero spacer, large gap
164rem64pxSection-level vertical rhythm
246rem96pxPage-level section separation

Convert Figma px values to the nearest key with the Tailwind spacing converter. The tool shows both the exact REM value and the nearest standard step.

REM alignment in Tailwind

Tailwind v3 and v4 both output REM for spacing utilities. p-4 compiles to padding: 1rem, not padding: 16px. This is deliberate: it preserves user font-size preferences and zoom behaviour.

The common misconception is treating the numeric key as a pixel value. It is a scale step. The pixel equivalents in the docs (and on this page) assume a 16px root — your users' roots may differ.

<!-- This compiles to padding: 1.5rem (24px at default root) -->
<div class="p-6">…</div>

<!-- NOT 6 pixels — the number is a scale key, not a pixel value -->

When working in a monorepo where some code uses raw CSS and some uses Tailwind, run specs through the PX to REM converter to confirm your Tailwind key maps to the same token value your CSS uses.

Arbitrary values: when and when not

Arbitrary values (p-[13px], mt-[0.875rem]) are a pressure valve for one-off measurements that fall outside the scale. They are not a substitute for token discipline.

Good use of arbitrary values:

<!-- A specific border-radius for a brand logo shape, used in one place -->
<img class="rounded-[14px]" … />

<!-- A one-off negative margin to optically align an icon to a baseline -->
<svg class="-mt-[0.125rem]" … />

Signs you have overused arbitrary values:

  • The same [value] appears in more than two components
  • You have p-[24px] when p-6 compiles to the exact same value
  • Designers are asking "why doesn't it look like the mockup" despite the pixel value matching

Promote to config when repeated:

// tailwind.config.ts
export default {
  theme: {
    extend: {
      spacing: {
        "18": "4.5rem",   // 72px — used for a recurring section height
        "22": "5.5rem",   // 88px — sticky header height
      }
    }
  }
}

Design systems and CSS variables

The most maintainable approach for teams that have both a design system and a Tailwind config is to source-of-truth everything from CSS custom properties, then reference those variables in Tailwind:

/* tokens.css — single source of truth */
:root {
  --space-xs: 0.5rem;
  --space-s:  1rem;
  --space-m:  1.5rem;
  --space-l:  2.5rem;
  --space-xl: 4rem;
}
// tailwind.config.ts — reference without duplicating values
export default {
  theme: {
    extend: {
      spacing: {
        "xs": "var(--space-xs)",
        "s":  "var(--space-s)",
        "m":  "var(--space-m)",
        "l":  "var(--space-l)",
        "xl": "var(--space-xl)",
      }
    }
  }
}
<!-- Usage -->
<section class="py-l px-m">…</section>

This keeps marketing pages (Tailwind-heavy) and product surfaces (CSS module-heavy) aligned without duplication.

Typography plugin sizing

The @tailwindcss/typography plugin (prose classes) uses its own internal type scale. If your project has a custom type scale, configure the plugin to respect it:

// tailwind.config.ts
export default {
  theme: {
    extend: {
      typography: ({ theme }) => ({
        DEFAULT: {
          css: {
            "font-size": theme("fontSize.base"),
            "line-height": "1.7",
            h2: { "font-size": theme("fontSize.xl") },
            h3: { "font-size": theme("fontSize.lg") },
          }
        }
      })
    }
  }
}

Pair this with the fluid typography generator to generate clamp() strings for the key prose sizes, then inject them via CSS variables as shown above.

Scale reference table

The ten most-reached-for Tailwind classes and their compiled output:

UtilityCompiled CSSpx at 16px root
p-1padding: 0.25rem4px
p-2padding: 0.5rem8px
p-3padding: 0.75rem12px
p-4padding: 1rem16px
p-5padding: 1.25rem20px
p-6padding: 1.5rem24px
p-8padding: 2rem32px
gap-4gap: 1rem16px
gap-6gap: 1.5rem24px
gap-8gap: 2rem32px

Key takeaways

  • Tailwind spacing is REM-based, not px-based — the numeric key is a scale step, not a pixel count.
  • Memorise 1, 2, 4, 6, 8, 12, 16 as your daily anchors for typical UI rhythm.
  • Arbitrary values are acceptable for one-offs but should be promoted to config once used more than twice.
  • Source from CSS variables when bridging Tailwind and raw CSS in the same project.
  • Use the Tailwind spacing converter to translate design specs without mental arithmetic.

Pair this article with Why developers prefer REM units for the underlying CSS reasoning.

Frequently asked questions

Is Tailwind's default scale always px-based mentally?
Utility values compile to real CSS units; many teams layer REM at the config level. Map Figma px to keys with the Tailwind spacing converter to work in both mental models simultaneously.
Should I extend the Tailwind spacing scale or use arbitrary values?
Extend the config for design tokens used throughout the project. Use arbitrary values for truly one-off measurements. If you reach for the same arbitrary value more than twice, it belongs in the config.
How do I make Tailwind use REM instead of pixels?
Tailwind v3+ uses REM by default for spacing utilities (`p-4` = 1rem = 16px at default root). The pixel values shown in docs are convenient reference points, not the actual compiled output.
What is the Tailwind spacing scale formula?
Each spacing step equals 0.25rem (4px at 16px root). So `p-1` = 0.25rem, `p-4` = 1rem, `p-8` = 2rem. The scale is linear from 0 to 96 with a few exceptions.
Can I use CSS custom properties (variables) with Tailwind?
Yes. Use arbitrary value syntax: `p-[var(--space-m)]` or `text-[var(--color-heading)]`. For brand tokens shared between CSS and Tailwind config, expose them as variables and reference them in both places.
How do I handle one-off design specs that don't match Tailwind scale?
First verify the spec — many off-scale values are rounding errors or approximations. If the value is intentional and used once, use an arbitrary value. If used in more than two places, add it to your Tailwind config extension.