TailwindCSS, our great ally

Erwan Gereec
Doctolib
Published in
8 min readJun 29, 2023
Illustration by Gaëlle Malenfant

Tailwind CSS is an open source low-level CSS framework created in 2017 by Adam Wathan and Steve Schoger. It uses ‘utility” classes to create layouts. Tailwind CSS is frequently compared to other CSS frameworks like Bootstrap whereas they are quite different:

  • Traditional CSS framework like Bootstrap, Foundation or Materialize offers pre-built CSS components out of the box for you to use in your app (e.g: Buttons, Alerts, Modal, Header..)
  • For its part, Tailwind CSS provides classes as utilities that allow you to build your own custom components

So, there is no Alert, Button or Modal classes with a predefined design or something like that in Tailwind CSS by default. You decide what a component will looks like with the utilities classes that you’re given. This gives you the freedom to design and build all your components from scratch. Smart, isn’t it?

Note: It’s also important to mention that new libraries emerged recently like Flowbite that offers a set of components built on top of Tailwind CSS utility classes. But in that way, it’s comparable to what’s Bootstrap offers.

Why use it at Doctolib ?

There are many reasons to use Tailwind CSS:

  • We have our own design system, and we wanted to use existing utility classes provided by Tailwind CSS rather than create custom ones.
  • We wanted to reduce the number of lines created for custom CSS classes in a separate file
  • We wanted to improve maintenance
  • Tailwind CSS is highly customizable so it’s also a good choice for the future
  • Since v3.0, Tailwind CSS uses a stable JIT (Just-In-Time) engine increasing also the build times
  • We wanted to use the same stack on both slim views and React components, making it more easily reusable on pages that are not yet migrated to React

Learn More about the Utility classes

Utility classes are simple HTML classes typically scoped to a single and specific CSS property. This notion is called “utility-first” and allows to build complex components from a set of utility classes.

This offers many advantages:

  • Utility classes are named according to their purpose
  • From a developer standpoint it’s easy to remember, easy to understand and you stay in your HTML when coding
  • There is no more naming inconsistencies
  • It contributes to fast layout creation and testing
Usage of utility classes to build UI components
Rendering examples

You see the downside now: having one class per property can result in many classes being added to the HTML code itself, which can make it difficult to read and maintain.

  • To keep your code clean and readable, the best approach is, of course to favor component extraction. This is what is done if you have a design system for example, in which you can define small components that can be reused throughout your application. This will also help you decouple your code, create small components with a single scope and will encourage long-term maintenance.
  • The second way is to use the @layer directive that will help you to keep your added styles well organized and structured. For that purpose, you can rely on the base, components, and utilities layers and write your CSS rules inside one of them depending on the level of power you want to give to your added CSS rule.
  • The third way, to be used sparingly in my opinion especially when you have a design system, is to use the @apply feature offers by Tailwind CSS to create custom styles with a set of utility classes. It's a little more complicated to maintain over the long term, especially if you have a large codebase. (It’s even more true when dealing with colors for example)
Example of extracting repeated utility patterns into a custom CSS class

If you want to familiarize yourself with the different classes available in Tailwind CSS, feel free to use their Playground !

Responsive design at ease

In order to build adaptive UI interfaces, Tailwind CSS gives access to five breakpoints, that can be used directly in any HTML element. Forget the declaration of CSS media queries inside a separated CSS file, just add a breakpoint prefix before writing your utility class. In that way, the utility class will be applied only when the breakpoint will be reached.

Tailwind is highly customizable, so you can still customize the default breakpoint values or define new ones whenever you want inside the tailwind.config.js file.

Let’s jump in a concrete example: you have 4 UI cards displaying global counters:

One-column layout

The associated source code is the following. As you can see, the rendering will be the same on all screens: each UI card will be displayed one after the other in a one-column layout.

(For this example, all classes are added inline for readability purpose here)

4 UI cards displayed in a single column layout for all screens size

Let’s try now to adapt this piece of code in order to display those UI cards on the same row depending on the screen size.

With Tailwind CSS, this can be achieved quite easily just by declaring md and lg breakpoint prefixes and an associated grid-cols rule:

As a result, you get an adaptive UI interface:

Two-columns layout for medium screens | Three-columns layout for large screens

It’s no more complicated than that, and it works for all utility classes provided by Tailwind CSS.

Managing style based on element state

In order to add interactivity to your application without writing any custom CSS line, Tailwind CSS offers severals state variants (hover, focus, active, disabled, visited, last-child..) that can be added as prefixes before your utility classes. With this approach, you can easily change the style of your elements based on user interaction, once again without leaving your HTML code.

For example, if you want to apply a zoom and change the background color of the UI cards created above, you simply have to use those classes prefixes with the hover state variant:

Use of the ‘hover’ variant

You can even go further by combining responsive breakpoints and state variants together to change the style of an element on hover at a specified breakpoint:

Combining responsive breakpoint and state variant

Less known utility classes of Tailwind CSS

Line clamp out of the box

It’s not uncommon to need to truncate text to fill a certain area. With Tailwind CSS, you can simply use the line-clamp utility class to specify the number of lines you want to display and the text will be automatically truncated with an ellipsis.

Line height for font-size utilities

Since the version 3.3 of Tailwind CSS, it’s now possible to use a short syntax for specifying line heights for your font-size utilities. For example, if you want to set a greater line height for your text-lg font-size utility class, you can now use directly this shortcut:

Styling child elements on parent state

Something difficult to achieve in pure CSS is to apply styles on child elements when hovering the parent. With Tailwind, you can simply use the group utility class at the parent level and the group-hover at the child level to apply specific utility class. Those classes will be automatically used when the parent element is hovered.

The print modifier

Do you know that you can use the print modifier to control whether an element should be integrated is someone print your webpage ? Just add for example the print:hidden utility class on a specific HTML element and it will not be integrated if the webpage is printed.

Tailwind CSS ♥ VsCode

If you are a developer using VsCode, there is a must-have extension called Tailwind CSS IntelliSense. It will help you to significantly improve your productivity and will enhance your developer experience. If you just start using Tailwind CSS in your project, it will be also a good coach helping you to learn Tailwind and remember utility classes. Last but no least, as this extension is maintained by Tailwind community, you’re sure to benefit the most advanced features as well as a great support if you get any trouble to use it.

Still learning Tailwind CSS, another extension called Tailwind Docs will allows you to get access to the online documentation directly from the VsCode command-palette. This lets you stay focused in your editor without having to search with your browser.

By default, Tailwind comes with a large list of colors and their associated gradient. This is particularly useful if you don’t have your own color branding. As Tailwind is highly customizable, you can add your own colors inside the tailwind.config.js file. If you need to generate different shades from a given color (from 100 to 900), you can use the Tailwind CSS Shades extension that will generate the shades for you from a single Hex color code.

Wrap-up

Used wisely, Tailwind CSS can be a great tool for improving the quality and readability of your code. Easily configurable, you’ll be able to create your own components quickly and easily, while benefiting from high compile-time performance.

It is not a substitute for Bootstrap or other frameworks, which offer predefined components. It depends on you, your experience with CSS, the size of your project, and the developer experience you want to provide.

I hope these were useful to you, let try it out and share your experience!

Cheers

The purpose of the article is to present and share the work done by Doctolib’s tech team. The information contained in this article is provided for information purpose only (on an “as is” basis with no guarantees of completeness or accuracy) and does not constitute any legal advice, nor has a legal value. Therefore, it could not contradict in any manner whatsoever with any legal binding terms applicable to your relation with Doctolib

--

--