Let’s begin by looking at a common responsive design pattern in Tailwind CSS:
< div class = "m-3 p-2 md:m-4 md:p-4 xl:m-6 xl:p-6" >
< h1 class = "mb-2 text-base md:mb-4 md:text-xl xl:mb-6 xl:text-2xl" >Title</ h1 >
< p class = "text-sm md:text-lg xl:text-2xl" >Lorem ipsum dolor sit amet.</ p >
</ div >
copied = true);
$el.setAttribute('data-checked', 'true');
$el.firstElementChild.classList.add('starting:scale-0', 'starting:opacity-0');
setTimeout(() => $el.removeAttribute('data-checked'), 2500);
" @mouseleave.debounce.1000ms="copied && (copied = false)" @keydown.enter.debounce.1000ms="copied && (copied = false)" @keydown.space.debounce.1000ms="copied && (copied = false)" @touchstart.debounce.1000ms="copied && (copied = false)" class="group flex items-center justify-between gap-2 rounded p-2 select-none hover:bg-surface-3 hover:text-brand focus-visible:ring-ring focus-visible:ring-1 focus-visible:outline-none motion-safe:transition-colors text-foreground-2 absolute top-0 right-0">
Tailwind Breakpoints can be a double-edged sword. It’s convenient to handle all our
breakpoints inline; however, this results in bloated HTML…
Considering responsive design is required, how to do we solve this problem while still leveraging Tailwind CSS? Fluid
Responsive Design !
Fluid Responsive Design is a responsive design pattern that leverages CSS Clamp instead of the traditional
breakpoint media queries.
In short, CSS Clamp is a CSS function that allows us to define a range of values (minimum, preferred, maximum). Based on
the viewport size, the preferred value will then scale automatically within the minimum and maximum.
Let’s now bring CSS Clamp into our Tailwind CSS configuration. To begin, we’ll add clamps for our font sizes:
These clamps were configured using a tool called Utopia . I highly recommend this tool for building out
your clamps!
tailwind.config.js /** @type {import('tailwindcss').Config} */
module . exports = {
...
extend: {
fontSize : {
'fluid-1' : 'clamp(1.89rem, calc(1.48rem + 2.03vw), 2.93rem)' ,
'fluid-2' : 'clamp(3.27rem, calc(2.31rem + 4.79vw), 5.72rem)' ,
}
}
...
}
copied = true);
$el.setAttribute('data-checked', 'true');
$el.firstElementChild.classList.add('starting:scale-0', 'starting:opacity-0');
setTimeout(() => $el.removeAttribute('data-checked'), 2500);
" @mouseleave.debounce.1000ms="copied && (copied = false)" @keydown.enter.debounce.1000ms="copied && (copied = false)" @keydown.space.debounce.1000ms="copied && (copied = false)" @touchstart.debounce.1000ms="copied && (copied = false)" class="group flex items-center justify-between gap-2 rounded p-2 select-none hover:bg-surface-3 hover:text-brand focus-visible:ring-ring focus-visible:ring-1 focus-visible:outline-none motion-safe:transition-colors text-foreground-2 absolute top-0 right-0">
When using these new fluid font size classes, the clamp will grow/shrink the font size in relation to the viewport. No
need to worry about multiple breakpoints anymore! text-base md:text-xl xl:text-2xl
→ text-fluid-2
Now that we have fluid font sizes, let’s add clamps for our fluid spacing. By setting Tailwind
Spacing , we gain fluid spacing for padding, margin, width, height, maxWidth, maxHeight, gap, inset,
space, and translate. p-2 m-3 md:p-4 md:m-4 xl:p-6 xl:m-6
→ p-fluid-1 m-fluid-2
These are also generated from Utopia .
tailwind.config.js /** @type {import('tailwindcss').Config} */
module . exports = {
...
extend: {
...
spacing: {
'fluid-1' : 'clamp(1.31rem, calc(0.65rem + 3.29vw), 3.00rem)' ,
'fluid-2' : 'clamp(1.31rem, calc(0.07rem + 6.22vw), 4.50rem)' ,
}
}
...
}
copied = true);
$el.setAttribute('data-checked', 'true');
$el.firstElementChild.classList.add('starting:scale-0', 'starting:opacity-0');
setTimeout(() => $el.removeAttribute('data-checked'), 2500);
" @mouseleave.debounce.1000ms="copied && (copied = false)" @keydown.enter.debounce.1000ms="copied && (copied = false)" @keydown.space.debounce.1000ms="copied && (copied = false)" @touchstart.debounce.1000ms="copied && (copied = false)" class="group flex items-center justify-between gap-2 rounded p-2 select-none hover:bg-surface-3 hover:text-brand focus-visible:ring-ring focus-visible:ring-1 focus-visible:outline-none motion-safe:transition-colors text-foreground-2 absolute top-0 right-0">
With our fluid responsive design configured, lets jump back to our original HTML to remove those breakpoints:
< div class = "m-fluid-2 p-fluid-1" >
< h1 class = "text-fluid-2 mb-fluid-2" >Title</ h1 >
< p class = "text-fluid-1" >Lorem ipsum dolor sit amet.</ p >
</ div >
copied = true);
$el.setAttribute('data-checked', 'true');
$el.firstElementChild.classList.add('starting:scale-0', 'starting:opacity-0');
setTimeout(() => $el.removeAttribute('data-checked'), 2500);
" @mouseleave.debounce.1000ms="copied && (copied = false)" @keydown.enter.debounce.1000ms="copied && (copied = false)" @keydown.space.debounce.1000ms="copied && (copied = false)" @touchstart.debounce.1000ms="copied && (copied = false)" class="group flex items-center justify-between gap-2 rounded p-2 select-none hover:bg-surface-3 hover:text-brand focus-visible:ring-ring focus-visible:ring-1 focus-visible:outline-none motion-safe:transition-colors text-foreground-2 absolute top-0 right-0">
As you can see, the HTML becomes far less bloated. The font sizes, paddings, and margins only need to be defined once
without having multiple breakpoints. All while keeping the conveniences of Tailwind CSS!
Bonus! If your using Utopia, there’s a tailwindcss plugin for it. Check it out here:
tailwindcss-utopia
tailwindcss-fluid-responsive-design
This project is a showcase of Fluid Responsive Design within Tailwind CSS.
Introduction