I have been experimenting with Tailwind CSS and trying to find an approach which fits my development workflow and approach to writing HTML and CSS.
Tailwind is a “utility-first CSS framework for rapidly building custom designs”. It provides a config driven set of classes that can be applied directly in to your HTML. Their documentation provides a good overview of traditional approach vs using utility classes;
<button class="bg-blue-500 text-white font-bold font-xl my-2 py-2 px-4 rounded max-w-md">
<button class="bg-green-500 text-white font-bold font-sm my-2 py-1 px-2 rounded max-w-sm">
Even in this simple example you probably think this HTML is becoming unwieldy and this is a light example of the classes you might apply to a single element. Colleagues I have shared these snippets with have raised concerns about the approach.
If you have a table listing with two buttons on each row, for example “view” and “edit”, and 10 rows, the HTML soon grows exponentially*. And if you have buttons throughout the page, each one will need to be updated manually if something changes.**
Personally, I don't find this approaching to writing HTML and CSS appealing. There are definitely benefits to this approach, including rapid development (matching their strapline). However, once you have built out a few pages, you soon see a lot of duplication.
You can combine Tailwind’s config-driven, decent presets and the opinionated naming conventions with approaches to writing reusable components and maintainable HTML. A lot of people (including me!) seem to have missed the section in the Tailwind documentation which helps you achieve this.
I am a fan of the Block Element Modifier (BEM) methodology and Tailwind can easily be used with this approach.
Firstly, you define your component;
<button class="button button--primary button--small">
Then, you can use
@apply to use the Tailwind utilities directly in your SCSS.
@apply text-white font-bold font-xl my-2 py-2 px-4 rounded max-w-md;
@apply font-sm py-1 px-2 max-w-sm;
The Tailwind documentation on Extracting Components has a section on using
@apply in this way. In their examples, they include the
@tailwind components; and
@tailwind utilities; but if you don't plan on using the utilities and stick strictly to the BEM component methodology you don't need to include them.
I am a big fan of Tailwind, with the flexibility config and opinionated naming conventions but not of the HTML use many people first see and stick with. If you're the same, I hope this primer on using Tailwind with BEM methodology shows the benefits of the approach and how you can achieve this with your projects.
* Gzipping helps reduce the HTTP payload (due to the repetitive nature of the classes).
** There are approaches with componentising everything, but this can be a step to far for smaller projects and adds another burden on the developer and workflow.