Introduction to TailwindCSS

The component-library are built on TailwindCSS. Though you do not necessarily have to have a deep understanding of Tailwind to be able to use the components, it's recommended to know the basics.

It's all about util-classes

The TailwindCSS-homepage does a great job of describing the whole idea behind the framework:

TailwindCSS is a utility-first CSS framework packed with classes like flex, pt-4 (padding) text-center and rotate-90 that can be composed to build any design, directly in your markup.

That's basically it; Tailwind is a whole lot of CSS-classes that lets you express most UIs directly from the markup. For us, that typically means directly from React/JSX, like so:

function MyComponent() {
return (
<p className="p-2 md:p-4 bg-blue text-white">
I'm blue daba dee daba die...
</p>
)
}

For good measure, lets quickly unpack the meaning:

  • p-2 is padding with a space value of "2" that resolves to 0.5rem
  • md:p-4 on medium screens, increase the padding to a space value of "4" that resolves to 1rem
  • bg-blue and text-white are self-explanatory (background-color and color)

As we are going to see in the next section, these util-classes are the base building blocks of the design system. It's not the components as you might expect.

But there is more!

You can also use Tailwind-utils inside CSS-files (via the Tailwind PostCSS-plugin).

The example over can also be written as follows:

.my-component {
@apply p-2 md:p-4 bg-blue text-white;
}

Here, the @apply operator injects the actual (raw) CSS behind the util-classes into the target class (.my-component).

Now, in our React-component we simply refer to the custom CSS-classname:

function MyComponent() {
return (
<p className="my-component">
I'm blue daba dee daba die...
</p>
)
}

The components becomes more self-contained, but at the price of duplicating code in the production-bundle (among other things).

For now, just know that it is a possibility. NTDS only uses this technique to create a few custom util-classes and not to extract whole components (we use React-components for that 😉).

Fun fact, though; this very page is styled with this technique. It can be easier to use this technique if you don't have access to the children -- say, when you get HTML generated from a CMS or from Markdown-file.

What about Bootstrap?

A great question! Bootstrap and TailwindCSS can't necessarily be compared directly, because Bootstrap is a "UI-toolkit" and TailwindCSS is a utility-only framework providing the "raw" building blocks to create your own.

Though bootstrap also have util-classes, they are not as fine-grained and customizable as in Tailwind.

Util-classes as design-tokens

First, let's remind ourselves what a design-token is. A design-token is just an inherent value of the design system like spacing, color, typography, shadows, breakpoints, among other things.

In Tailwind, the util-classes themselves become the design-tokens because they are configured and generated from a custom configuration representing the design system.

For example, consider the util-classes in the following example:

<p class="mb-4 text-blue">Look, look at the tokens!</p>

Here mb-4 and text-blue represent two design-tokens in the design system. The actual value behind them, 1rem and #0058ff respectively, are a configured in the Tailwind configuration-file in the design system.

Inspectable design-tokens in production!

A nice feature of using util-classes, is that the design-tokens can be inspected directly by viewing the source code in the browser -- also in production.

For example: Why does the padding look wrong in my component?

* OPENS DEVELOPER TOOLS *

<div class="p-2 lg:p-5">Some important block</div>

Aha! lg:p-5 should be lg:p-4. Fixed.

Design-tokens in other design systems

Perhaps the most common way to use design-tokens are through variables, for example through custom properties in CSS or through variables in SASS, like in the following example:

// design-tokens.scss
$color-blue: #0058ff;
// MyComponent/styles.scss
.my-component {
color: $color-blue;
}

Tailwind and configurability

Pretty much everything in Tailwind is customizable. You can add/remove/extend colors, padding, margins, breakpoints, spacing, height/width, among other things. These customizations are performed in the Tailwind configuration-file.

The key takeaway here is that the design system adds its design-tokens using this Tailwind-config. It is important to understand that the values presented in the official Tailwind documentation may or may not be there. This is especially true for colors.

Example: Add a color

In the following example, we add a new color pink to our theme.

// tailwind.config.js
// ...
config.theme.colors.pink = "#ff7ea9";

As a result of this, Tailwind will now generate a set of new util-classes that uses the color-property, like bg-pink, text-pink, border-pink, among other utils.

Actually, that not the whole story! For every util, Tailwind also generates so called variants for every util. A variant are states like, focus, hover and breakepoints. For example for the text-pink-util, we also get the following variants:

group-hover:text-pink
focus-within:text-pink
hover:text-pink
focus:text-pink
dark:text-pink
sm:text-pink
md:text-pink
lg:text-pink
xl:text-pink

Now we can add a hover-effect from the markup, like so:

<a class="text-pink hover:bg-pink hover:text-white" href="#">Click me</a>

TailwindCSS achieves all this through its PostCSS-plugin. It takes the configuration file and generate a CSS-file based on it.

See all util generated

For every utils listed under, there are multiple variants generated with them (like focus:text-pink, hover:text-pink, ...).

bg-pink
text-pink
border-pink
from-pink
via-pink
to-pink
placeholder-pink
divide-pink
ring-pink
ring-offset-pink
fill-pink

Note that the variants for different utils can vary. For example, text-pink (see above) have all variants generated, but placeholder-pink only have the breakpoint-variants generated (like sm:placeholder-pink, md:placeholder-pink, ...). This is done to limit unnecessary or unlikely variants to keep the CSS-size down in development. This is configurable for every util, though.