I’ve been building things for the web since somewhere in the 90s, starting out with GeoCities, static HTML and CSS. Flash forward over 20 years, and the web is, well, radically different. Even with my decades of experience, there’s still always something new to learn – and when upskilling myself with the Laravel PHP framework, I’ve seen so many tweets and references to Tailwind CSS.
But what is Tailwind CSS? Tailwind CSS’s website says:
A utility-first CSS framework for rapidly building custom designs.
Great, awesome, that’s exactly what I do – build custom designs. This should be perfect!
At first quick glance, I’ll be honest, I found it rather hard to read – and was also concerned about the implications of referencing things (such as a class referencing a specific colour shade or font style) in your markup. I’ve always been one to find efficient ways to write reusable code, and this just felt so out of place. And yet, so many devs had such incredibly positive things to say about it. Even the 2019 State of CSS survey shows a huge interest rate and top-of-the-class satisfaction rate.
I felt I had to be missing something – after all, there is only so much you can get out of a framework by just reading about. But rather than just a plain “hello world” example (you know my thoughts on that), I wanted to see how Tailwind CSS could fit in to my current aim: developing a base admin interface that could be used for any sort of project.
Part of my exploration was to ensure that the setup was using the tools available to me, and be suitable for a production environment too – be that language tools or framework tools. So we have:
Laravel Mix to compile the source (and for a Laravel backend)
Additional SCSS for the ability to use “@apply” if/when needed
Purge CSS for cleaning up unused Tailwind utilities for production (more on this later)
So what was I going to build? A totally boring to look at (but actual skeleton) for an admin interface. Sure, it’s not the whole admin interface, but it is the foundation. Something like this:
There’s a menu, a nav bar, a footer, and a main area. And I wanted to have the menu collapse with different behaviours:
on mobile devices, have the menu invisible, and appear over the content
on larger devices, have the menu expand and contract (and contract and expand the content area)
So I built a simple Vue app, and in its template added the markup for this wireframe. I tinkered with Laravel Mix, and installed the Mix Purgecss plugin. I used my favourite Hamburgers package for some gorgeous hamburgering, and started to play with the desktop (aka “larger devices”) menu. Works a charm.
Even with responsive styles, I was able to effortlessly implement the menu behaviours for different screen sizes (basically medium and below, and above) based on the menu button click state.
And yes, it's not terribly pretty... but got me thinking about how to use Tailwind CSS for layout, for colours, fonts, padding, and even how to use its responsive helpers for more complicated behaviour for small vs large screen devices.
And I was able to get to this page without writing a single line of CSS.
Is this actually a good thing, or a bad thing? I’m still pondering this one.
On the plus side, the speed at which I could do exactly what I wanted to do (i.e. a custom interface) was phenomenal. Especially when you don’t have to override all of these other styles (I’m looking at you Bootstrap).
On the downside, would it make me a lazy CSS developer? Maybe, maybe not. I think what is unique about a utility-based framework is that it requires you to have solid knowledge of how CSS behaves in browsers, and what to use to create the desired result, but takes away the syntax knowledge requirement. So maybe that’s actually a plus too.
From reading the docs before playing, I knew Tailwind CSS had some weight to it – over 700kb actually. Even Tailwind CSS admits that it is heavy. But, and this is the cool part, Purgecss is able to run as part of the build, and remove unwanted CSS. You know, those thousands of utility classes that I’m not actually using. With a postcss config file, the build process is able to look at my code – such as all of my Vue components, and even tinkered with the recipe to look at any blade.php files too – and look at what classes I am actually using.
Dev build: over 67,600 lines of CSS code (1.04MB, uncompressed)
Prod build: 299 lines of CSS code (4.22kb, uncompressed)
And in both instances, I didn’t write a single line of CSS myself. I must admit that I’m a bit stoked at how simple it has been to not only build the wireframe I had intended, but also make it effortlessly responsive.
The next step would be to do a fairer comparison of code size when a build is actually complete: Bulma is what it is (and at times needs little to no adjusting, either through variables or through overriding/adding styles) so its size is more predictable. Tailwind CSS depends on what gets used - and how components get implemented to achieve this.
In my current Laravel build, I’ve been working with Bulma and Buefy – and it has been great to have quick access to mobile-friendly tables that can just work with creating a bit of a playground app in Laravel and Vue. Again, rather than just “Hello, World”, actually building different models (and relationships) with an interface and UX I’d be happy for my clients to experience. The biggest gap with Tailwind CSS: the lack of these sort of ready-to-go components. After years of doing things myself, from a team and productivity point of view, utilising tools that can assist with the speed, quality and reliability of development is now a primary factor: and the prospect of writing my own components isn’t terribly thrilling. But… Tailwind UI is due for release this week, with a collection of UI components ready-to-go – and I’m really keen to see what these entail and how they can be used to take the ease of Tailwind CSS development one step further.
From my exploration today getting my feet wet with building a layout using Tailwind CSS (albeit a bare-bones simple one), I’m actually thinking I could quite easily become a convert. Part of it just makes so much sense: (mostly) unopinionated (which I love), following some smart logic regarding spacing conventions, overriding (theming) ability. After having a play, I can safely say that I do actually get what all the fuss is about.
What I like:
ease of use and speed of implementation – I did so much more than I had anticipated with such little fuss
superb documentation (with fast and incredibly useful search – great for finding not only usage notes but also configuration tweaks)
incredibly lightweight (when built with Purgecss for production)
What I don’t like:
replicating so many declarations throughout the code – and “what if” one needs changing? That’s a lot of changes that need to be made at the source code level
readability can be a little vague at a glance (but even in my short play today, my familiarity with the naming conventions increased dramatically so started to make more sense)
Comparing to Bulma (note, not Buefy, just CSS):
with Tailwind CSS, I have to make my own layouts even for the basic components such as a navbar or footer – but also this level of freedom means I don’t need to override opinions that Bulma may set on me
Tailwind CSS provides a slimmer build (and is easier to implement than Bulma’s code-level import process)
Tailwind CSS’s freedom of implementation means that my Tailwind CSS site doesn’t look like everyone else’s Tailwind CSS site. Bulma, I feel, has the potential to fall in to this trap from a UI perspective – but definitely not as nasty as Bootstrap.
From the previews I’ve seen of Tailwind UI, I’m thinking that Tailwind CSS and UI might become my baseline for building custom interfaces. I really do love custom coding, and love being in control – and Tailwind CSS’s utility-first approach gives me the ability to custom design, and control my layout without thrusting its own opinions on style, layout or behaviour.