Tailwind is a utility-based CSS framework. This is a lot different to something like Bootstrap where classes are used in specific circumstances. Tailwind opts for using small reusable classes that do one thing. This approach means once you learn a class and where it's used, you can use that anywhere. Let's take a simple scenario, we want to display some elements in a row with even spacing between them, we could do something like this:
<div class="flex space-x-4">
<div>01</div>
<div>02</div>
<div>03</div>
</div>
The flex
class adds display: flex
to the container and the space-x-4
adds a margin-left
to every child except the first.
Another cool thing that Tailwind strives for is good defaults and flexibility. You can easily add support for dark mode by prefixing a class with dark:
like dark:g-red-500
which will only apply a red background when in dark mode, so everything you know up until this point isn't wasted. You can do this with print:
for print layouts and responsive design like md:
, or lg:
for medium and large breakpoints respectively.
Tailwind can seem a bit daunting at first but with a little bit of time (even just 30 mins), you'll be able to learn roughly how it works. One of the benefits is good CSS knowledge to start with. The names of many of the tailwind classes are pretty close to their names in CSS so, if you're a CSS ninja then you've already got a head start. An example of this is the display
property, display: block;
becomes the block
class in Tailwind.
Here's the full list you can take a look at the docs for display:
Class | Properties |
---|---|
block | display: block; |
inline-block | display: inline-block; |
inline | display: inline; |
flex | display: flex; |
inline-flex | display: inline-flex; |
table | display: table; |
inline-table | display: inline-table; |
table-caption | display: table-caption; |
table-cell | display: table-cell; |
table-column | display: table-column; |
table-column-group | display: table-column-group; |
table-footer-group | display: table-footer-group; |
table-header-group | display: table-header-group; |
table-row-group | display: table-row-group; |
table-row | display: table-row; |
flow-root | display: flow-root; |
grid | display: grid; |
inline-grid | display: inline-grid; |
contents | display: contents; |
list-item | display: list-item; |
hidden | display: none; |
There are a few exceptions like commonly used utilities for margin and padding that become m-2
for margin on all sides or my-2
for margin just on the y-axis (left and right). Overall, once you know the most common classes, you'll be able to recreate designs more comfortably and do rapid prototyping.
The power really comes from composing these classes and creating very rich components like this modal in TailwindUI:
<div class="fixed z-10 inset-0 overflow-y-auto" aria-labelledby="modal-title" role="dialog" aria-modal="true">
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" aria-hidden="true"></div>
<!-- This element is to trick the browser into centering the modal contents. -->
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span>
<div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start">
<div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10">
<!-- Heroicon name: outline/exclamation -->
<svg class="h-6 w-6 text-red-600" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
</div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<h3 class="text-lg leading-6 font-medium text-gray-900" id="modal-title">
Deactivate account
</h3>
<div class="mt-2">
<p class="text-sm text-gray-500">
Are you sure you want to deactivate your account? All of your data will be permanently removed. This action cannot be undone.
</p>
</div>
</div>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button type="button" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">
Deactivate
</button>
<button type="button" class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
Cancel
</button>
</div>
</div>
</div>
</div>
This example shows use of responsive media queries, hover states and focus states. This is just a taste, I haven't seen anything that can't be recreated in Tailwind - I'm sure there is but in daily use, it hasn't come up yet.
Tailwind can be used anywhere, It's one of the most productive frameworks I've used in a long time and is easy to add anywhere including simple website, complex React projects and even component libraries. I think it's a good choice when you need something that isn't going to restrict you and if your team is onboard too.
One of the criticisms, you may have seen the example, is your markup gets very verbose. This usually isn't too much of an issue when paired with a component library like React or UI framework Svelte where common elements are grouped together. If you're using this methodology, the most verbose classes are hidden away in individual components.
I think the biggest challenge is the mental shift required. Tailwind can be very decisive, much like CSS-in-JS, it's using CSS in a way it was not originally intended for and that can create strong opinions. When I first saw it, I didn't really get it. I know CSS quite well and usually try using CSS modules and semantic naming if I had the choice. Over the past few months, I've been using Tailwind more and I really enjoy it but it's not for everyone. If you need old browser support, need full control over your CSS, browser-specific prefixes or experimental CSS - Tailwind probably won't be the best solution.