tailwindcss-calc
Built for Tailwind CSS v4

Design once. It fits every screen.

Write the pixel values from your mockup — w-100, p-20, text-32 — and every one of them scales with the viewport. Pure CSS, no config, no JavaScript.

$ npm install tailwindcss-calc
See how it works →

How it works

01

Set two numbers

Your mobile and desktop design widths. That is the entire configuration.

02

Write mockup pixels

A 100px box is w-100. No conversion, no md: ladder for sizing.

03

Everything scales

One shared ratio drives every utility, and caps at your design width.

property: calc(value * clamp(0px, 100vw, max-width) / base-width);

See it move — resize the window

Four different values, one shared ratio. Drag the window narrower and they shrink together, keeping the proportions of your mockup.

Past 1440px they stop growing — the base width is the cap.

w-20
w-40
w-60
w-80
viewport
base
w-100 renders as

One number set, two mockups

The same markup at both design references. Sizes come from the mockup as written — p-32, size-56, text-32 — and only the layout gets an md: variant.

mobile · base 375 · 1:1
acme menu
Scales without breakpoints
Every value in this card is a mockup pixel, multiplied by one ratio.
Get started →
desktop · base 1440 · shown at 45%
acme work · about · contact
Scales without breakpoints
Every value in this card is a mockup pixel, multiplied by one ratio.
Get started →

Swipe to compare the two artboards →

Implement it — two imports, two numbers

@import "tailwindcss";
@import "tailwindcss-calc";

@layer theme {
  :root {
    --window-width: 375; /* mobile mockup */
  }
  @variant md {
    :root {
      --window-width: 1440; /* desktop mockup */
    }
  }
}

✓ Use @variant md

Mobile-first, and stays in sync with your theme's --breakpoint-md.

✕ Avoid max-width: 768px

Desktop-first fights the plugin and hard-codes a value that can drift.

! Keep paragraphs in rem

Scaled font sizes ignore the reader's browser font-size preference. Use scaled text-* for display type and chrome.

What scales

w-* h-* size-* min-w-* max-w-* min-h-* max-h-* p-* px-* py-* m-* mx-* my-* gap-* gap-x-* gap-y-* rounded-* text-* leading-* tracking-* word-spacing-* top-* left-* inset-* translate-x-* translate-y-* border-w-* outline-offset-* container -m-* -mt-* -mx-* -top-* -left-* -inset-* -translate-x-* -tracking-*

Violet chips also accept a negative value.