postcss-clampwind
Bring the power of clamp() to your utility classes
A Post CSS plugin that generates fluid, responsive CSS using the clamp()→ function, without making you touch the math behind it.
<main class="w-full p-[clamp(16px,96px)] ">
<div class="flex flex-col gap-[clamp(12px,48px)] ">
<div class="grid grid-cols-2 gap-[clamp(8px,24px)] ">
<img src="/src/img/house-1.jpg" width="300" height="300" alt="" class="size-full object-cover rounded-lg">
<img src="/src/img/house-2.jpg" width="300" height="300" alt="" class="size-full object-cover rounded-lg">
</div>
<div class="flex items-center justify-between">
<div class="flex flex-col">
<span class="text-gray-500 font-medium text-[clamp(14px,24px)] ">
Entire house
</span>
<h1 class="font-semibold text-[clamp(24px,68px)] leading-[124%]">
Beach house on Lake Charlotte
</h1>
</div>
<button class="flex items-center justify-center bg-blue-600 py-[clamp(8px,16px)] px-[clamp(12px,96px)] rounded-lg gap-[clamp(8px,16px)] cursor-pointer hocus:bg-blue-600/90 transition-colors duration-300 ease-in-out">
<svg class="stroke-gray-50 size-[clamp(18px,26px)] " xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-width="2" d="M20 10V7a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v3m16 0H4m16 0v.75M4 10v9a2 2 0 0 0 2 2h6M8 3v4m8-4v4M17.536 14v3.535m0 3.536v-3.536m0 0h3.535m-3.535 0H14" /></svg>
<span class="font-semibold text-gray-50 text-[clamp(16px,32px)] ">Book</span>
</button>
</div>
</div>
</main>
-
1
Use the square brackets to generate custom CSS. Write inside the brackets a clamp() function with only two values, instead of the regular
clamp(min, preferred, max)
syntax..text-\[clamp\(16px\,32px\)\] { font-size: clamp(16px, 32px); }
-
2
The PostCSS plugin finds all the occurrences in your CSS, converts everything to rems, and calculates the clamp() formula using the smallest and largest breakpoints as the range for the scaling.
.text-\[clamp\(16px\,32px\)\] { font-size: clamp(1rem, calc(1rem + 0.0121 * (100vw - 25rem)), 2rem); }
-
3
If the plugin finds any media query containing the clamp() function it will use these as the range bounds to calculate the scaling formula.
.md\:max-lg\:text-\[clamp\(16px\,32px\)\] { @media (width >= 48rem ) { /* 768px */ @media (width < 64rem ) { /* 1024px */ font-size: clamp(1rem, calc(1rem + 0.0625 * (100vw - 48rem)), 2rem); } } }
Install the PostCSS plugin with npm
npm install postcss-clampwind
-
Vite
If you are using Vite with
@tailwindcss/vite
, import the plugin and use it in your.postcss.config.js
file.// postcss.config.js import clampwind from "postcss-clampwind"; export default { plugins: [ clampwind() ] };
-
PostCSS
Add the plugin to the plugin list in your
.postcss.config.js
configuration file.// postcss.config.mjs import tailwindcss from "@tailwindcss/postcss" import clampwind from "postcss-clampwind" export default { plugins: [ tailwindcss(), clampwind(), ] }
-
Webpack
When using CommonJS-based build tools like Webpack, use the
require
syntax and add.default
to the import.// postcss.config.js module.exports = { plugins: { require("@tailwindcss/postcss"), require("postcss-clampwind").default } };
-
Clamp between two breakpoints
Use the native Tailwind syntax to clamp any CSS property value within a specific range by using breakpoint modifiers.
<div class=" md:max-lg:text-[clamp(16px,32px)] "></div>
-
Clamp from and to a single breakpoint
Add a single breakpoint modifier to generate the scaling formula from the defined breakpoint to the largest breakpoint. Use the
max-
modifier to clamp from the smallest breakpoint to the defined breakpoint.<div class=" max-md:text-[clamp(16px,24px)] "></div> <div class=" md:text-[clamp(24px,32px)] "></div>
-
Clamp between custom breakpoints
Generate one-off custom breakpoint size by writing the value inside brackets, use the
min-
andmax-
modifier. This works also with only one modifier.<div class=" min-[800px]:max-[1200px]:text-[clamp(16px,32px)] "></div>
-
Interchangeable px/rem units
Clamped values can use either px or rem interchangeably, the plugin will convert all values to rem.
<div class=" text-[clamp(16px,2rem)] "></div>
-
Unitless clamping
If no unit is specified, the calculation will multiply the value for your theme’s
--spacing
scale.<div class=" text-[clamp(16,32)] "></div>
-
Use Tailwind size variables
Clamp using Tailwind’s predefined size tokens.
<div class=" text-[clamp(var(--text-sm),32px)] "></div>
-
Use CSS custom properties
Clamp using CSS custom properties, make sure the custom properties are defined in the
:root
element.<div class=" text-[clamp(var(--custom-size),32px)] "></div>
-
Container query support
Clamp values based on container query breakpoints.
<div class=" @md:text-[clamp(16px,32px)] "></div>
-
Decreasing and negative ranges
Support clamped ranges that shrink or go below zero.
<div class=" mt-[clamp(32px,-16px)] "></div>
-
Error reporting in CSS comments
Output validation errors as CSS comments for easy debugging.
.text-\[clamp\(16%\,32px\)\] { font-size: clamp(16%, 32px); /* Invalid clamp() values */ }
This PostCSS plugin embraces a CSS-driven configuration, by scanning your generated CSS before generating all the clamp formula calculations.
-
Add custom breakpoints
Normally you can add new breakpoints in Tailwind v4 by defining them inside the
@theme
directive, but by default any custom properties that are not referenced directly will not be added to the final CSS file.
You need to use the@theme static
directive instead of@theme
to output all custom properties and make the PostCSS plugin aware of the custom breakpoints.@theme static { --breakpoint-4xl: 1600px; }
-
Set a default clamp range
You can set a default clamp range to use when only one, or no breakpoint modifier is used, instead of the default range from the smallest to the largest breakpoints.
To set a default clamp range you need to use the--breakpoint-clamp-min
and--breakpoint-clamp-max
custom properties, defining them inside the@theme static
directive.@theme static { --breakpoint-clamp-min: 600px; --breakpoint-clamp-max: 1200px; }
-
Pixel to rem conversion
Clampwind will convert all px values to rem. For the conversion it scans your
:root
element, looking for afont-size
property or for a--text-base
custom property.
If present, it will use the value to convert all pixel values to rem values, if it doesn't find any, it will use the default value of 16px.:root { font-size: 18px; /* 18px = 1.125rem */ }