Tailwind CSS
A discussion of the benefits of building websites with a utility class system like Tailwind CSS compared to using a UI framework such as Foundation or Bootstrap.
Jump To Section
Intro
This week I launched the redesign of the site you are currently reading. This redesign was also the second project that I worked in Tailwind CSS and during this development I have decided that all my future projects will be using it. Learn why by reading on.
As a web developer you are probably familiar with Frameworks such as Bootstrap and Foundation. These are popular starting points for many developers because it's quick and easy to build websites with either framework.
The many components with javascript already built in such as the navbar, tabs, modals etcetera are appealing. However they come with a couple of downsides: The sites often look similar because both bootstrap and foundation are very opinionated about how your html/css should be coded. And if you want to do it differently then there is a lot of pain overriding classes - I know because I've been there and done that.
As an example the previous version of this site was using Foundation 6.4 and to style the navigation which was essentially the same as the current site I had 103 lines of sass, most of which were ridiculously long due to specificity.
However with Tailwind I have 36 lines of sass. 11 lines of which are not necessary as I have extracted css into @apply
rules on the nav items. More on @apply
below.
// nav logo
.main-logo {
height:50px;
width:280px;
@screen md {
max-width: 170px;
max-height:40px;
}
@screen lg {
max-width:100%;
max-height:100%;
}
}
.main-nav-item {
@apply flex-no-grow flex-no-shrink relative py-2 px-0 my-3 leading-normal text-black no-underline flex items-center uppercase self-center text-2xl;
@screen md {
// @apply flex;
@apply self-auto text-base py-2 px-4 my-0;
}
}
.main-nav-item:hover,
.main-nav-item:focus {
@apply text-orange;
}
.main-nav {
height: calc(100vh - 75px);
@screen md {
@apply h-auto;
}
}
.hamburger-icon,
.close-icon {
width: 40px;
}
Extract Components to @apply
Tailwind CSS allows you to extract components which is essentially creating a new class and inserting any number of tailwind classes into that class. This is excellent for elements of your site that get repeated and should have a the same look. I use it for buttons, nav list items and sections as I want each of these to have the exact same styles applied to them.
There is additional flexibility here in that if you have one component that needs a style overridden or added to it you can easily add new classes to that component.
For example I have sections set up as a component like this:
section {
@apply z-10 bg-white;
&.circle-block {
z-index:20 !important;
}
&:first-of-type {
margin-top:75px;
// only for medium
@screen md {
margin-top:67px;
}
// reset to basic when above medium
@screen lg {
margin-top: 75px;
}
}
&:last-of-type {
@apply shadow;
}
If however I wanted to have a section with a different background color I could easily change that by coding it like this <section class="bg-grey-light">...</section>
This particular section now has a light grey background.
It's important to note with Tailwind components that the responsive classes which are prefixed by sm:px-8 md:px-12 lg:px-4
ectetera cannot be added directly to your component you need to nest them with @screen
Customizable and Flexible
When you set up tailwind you create a tailwindconfig.js
file which contains all the code and defaults necessary to use Tailwind out of the box. However you'll want to customize it so your colors, fonts, and more match what you want. You can also remove options that are necessary.
For example there are 70 colors that the default config comes with. but for this site I removed what I didn't need, changed the remaining and I now have 17 colors
let colors = {
'transparent': 'transparent',
'black': '#1c1c1e',
'grey-darkest': '#252c31',
'grey-darker': '#606f7b',
'grey-dark': '#8795a1',
'grey': '#b1b5c5',
'grey-light': '#D3D5DE',
'grey-lighter': '#F0F1F4',
'grey-lightest': '#f8fafc',
'white': '#ffffff',
'orange-dark': '#d4420d',
'orange': '#f15a23',
'orange-light': '#f47e53',
'green': '#b7fae9',
'red': '#dd1144',
'accent-color': '#B7FAE9',
'text-color': '#333333',
}
You can make similar adjustments to font sizes, breakpoints, font-weights, leading, width/height options, and more. Additionally there are plugins available that you can add for extra functionality. One that I added in gives the option to have your colors with transparency values: Check out Tailwind RGBA.
Purgecss Gulp Task
With Tailwind CSS the generated filesize is rather large. For this site my unminified filesize is 747KB. Fortunately there is PurgeCSS with plugins available for your favorite taskrunner, grunt, gulp, or webpack. Also see the official Tailwind docs for other strategies to reduce your filesize.
I'm currently using gulp and setting up purge worked almost out of the box. I did however run into one issue where my entire site had mobile styles even at desktop resolution.
A little searching and I discovered that you need to add a custom extractor to purgecss due to the unique class names. I found the gulp solution here.
My purgecss gulp task is below.
/**
* Custom PurgeCSS Extractor
* https://gist.github.com/taylorbryant/91fc05b12472a88a8b6494f610647cd4
*/
class TailwindExtractor {
static extract(content) {
return content.match(/[A-z0-9-:\/]+/g);
}
}
gulp.task("purge",() => {
$.fancyLog("-> purging unused css");
return gulp.src(pkg.paths.dist.css + '*.css')
.pipe($.purgecss({
content: [pkg.paths.templates + "/**/*.{html,htm,twig}", pkg.paths.templates + "/**/**/*.{html,htm,twig}", pkg.paths.templates + "*.{html,htm,twig}"],
// whitelister module ensures this css is not extracted
whitelist: whitelister('./node_modules/sal.js/dist/sal.css'),
extractors: [
{
extractor: TailwindExtractor,
extensions: ["html", "htm", "twig"]
}
]
}))
.pipe($.if(["*.css", "!*.purge.css"],
$.rename({
suffix: ".purge"
})
))
.pipe(gulp.dest(pkg.paths.dist.css))
});
You can see the extractor at the top. Additionally I added a whitelist of all classes in the sal.js file. To do that I added in the purgecss whitelister npm package. If I didn't whitelist these class the animations that sal.js takes care of wouldn't run correctly.
Benefits
The main benefit is faster development. Once you are set up you will be writing very little CSS. Not having to switch between twig or html templates and css files makes things go so much smoother and faster.
Now I can easily change and update classes in one file and watch the changes happen almost instantly instead of writing scss, waiting for it to compile, and then waiting for the page to reload. I update classes in my html/twig file and the gulp reload task loads it faster than it takes for me to move my eyes from my editor to the browser.
Developing with Tailwind is much faster and easier than using a full UI framework such as bootstrap or foundation in my opinion.
The only downside is that if you need IE11 support, it may not be the right choice for your project. If I need IE11 support I'll likely continue to use Foundation, but for everything else I'll be using Tailwind.