CSS spacing pain points and Tailwind

I’ve recently began working with Tailwind, the popular utility first CSS framework, and I’m a big fan. It’s customisable, but it also comes with sensible defaults out-of-the-box. Coupled with the Intellisense plugin for VSCode, which adds helpful suggestions for class names which saves flicking back to the docs, I’m happy about how quickly I can build responsive and maintainable CSS without adding too much bulk to the bundle.

Why CSS spacing can be challenging

Max Stoiber (creator of styled-components) argued that we should ban margin from our components, as they break encapsulation.

I agree with the conceit that it often feels strange to give margin and padding to a particular element, as it should be the responsibility of the parent and it usually doesn’t seem right to have any element ‘owning’ the whitespace, as Josh Comeau discusses in his article advocating the return of the spacer to create a buffer between elements. (I’m intrigued by the concept of a spacer component, but I’ve never tried it out).

I’m pretty convinced by the argument that it’s more maintainable to avoid scattering margin on children. Mark Dalgleish argues that components should have as little surrounding whitespace as possible, as space between components should be handled exclusively by layout components.

How Tailwind helps

Alongside the expected padding and margin utility classes, we also have space-x-{amount} and space-y-{amount}utilities. This is one of the nicest features of Tailwind for layout and allows you to add consistent spacing between all children of an element rather than setting padding or margin on each child.

Tailwind spacing scale numbers are based on rems. If you’re more used to pixel values, the Intellisense plugin is helpful as it also shows the pixel value.

Another nice feature of the Tailwind docs is that next to each class you can see which CSS properties you are applying(no black box!). We can see below that the space-x and space-y classes are using margin-left and -right or margin-top and -bottom under the hood to calculate the spacing.

/* space-y-3 > * + *
--tw-space-y-reverse: 0;
margin-top: calc(0.75rem * calc(1 — var( — tw-space-y-reverse))); margin-bottom: calc(0.75rem * var( — tw-space-y-reverse));

We could set individual margin on each child element, but this means we would have to go in and edit each individual child if we wanted to change the spacing.

Another perk of Tailwind is its customisability, we can also edit the theme.spacing section of ourtailwind.config.js file to override the default spacing values.

// tailwind.config.js
module.exports = {
theme: {
spacing: {
'1': '8px',
'2': '12px',
'3': '16px',
'4': '24px',
'5': '32px',
'6': '48px',

By default this spacing scale is inherited by the padding, margin, width, height, maxHeight, gap, inset, space, and translate core plugins. We can extend the default values, too, by adding further keys and values to theme.extend.spacing (More information on Tailwind spacing overrides can be found here.)

The future

Recent updates to the CSS specification have added CSS gap to simplify spacing logic, however browser support is still a patchy. For now, I’m enjoying using Tailwind in my projects to help with the pain points of consistent spacing.

London-based developer