Adding Tailwind to a Jekyll site on Windows
06 Jul 2021
Table of Contents
I’ve been wanting to migrate one of my web sites from the Github Pages Jekyll to 11ty for a while so that I could use Tailwind CSS and facitate a redesign of the look and feel.
In the end, I realized that migrating old .md
files w/o breaking anchor links to subsections was going to be a regex nightmare, and I’d be better off figuring out how to add Tailwind to Jekyll.
Updates
- In 7/2021, Joel Varty asked, “For a Hugo site I was working on, i just used the new Tailwind CLI all on its own – then everything works including JIT – I wonder if that would work for your Jekyll site?” I haven’t tried this yet.
- In 9/2021, Maud de Vries pointed out that this article might be obsolete thanks to Liam Bigelow’s
jekyll-postcss-2
Ruby gem. I also haven’t tried this yet.
Minimum viable build
I put up my working code at Github, and here’s a live demo.
This is the first codebase I got working while implementing Steven Westmoreland’s and Marcin Doliwa’s directions to add Tailwind to this tiny Jekyll site.
I failed trying a million and a half more complex starters involving webpack, gulp, etc. I’m glad the solution turned out simple in the end (Ruby’s jekyll-postcss
plugin).
Clone it, run it, and play with the Tailwind classes in pages/index.md
yourself.
Issues
JIT
jekyll-postcss
works just fine, as long as you don’t expect Tailwind to work in JIT mode (bug report 1, bug report 2).
SCSS
I also haven’t gotten this architecture properly handling an assets/css/main.scss
(note Scss) file; just plain CSS.
Windows
If your localhost environment is on Windows, jekyll-postcss
will fail with an ENOEXEC
Exec format error
something like this:
...
Conversion error: Jekyll::Converters::PostCss encountered an error while converting 'assets/css/main.css':
Exec format error - C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/jekyll-postcss-0.4.1/bin/postcss '{"raw_content":"@import \"tailwindcss/base\";\n@import \"tailwindcss/components\";\n@import \"tailwindcss/utilities\";"}'
...
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/jekyll-postcss-0.4.1/lib/jekyll-postcss/socket.rb:20:in ``': Exec format error - C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/jekyll-postcss-0.4.1/bin/postcss '{"raw_content":"@import \\"tailwindcss/base\\";\\n@import \\"tailwindcss/components\\";\\n@import \\"tailwindcss/utilities\\";"}' (Errno::ENOEXEC)
...
You have to install the Windows Subsystem for Linux (WSL) as in Scott Hanselman’s instructions and run Jekyll from a WSL command line.
(Be sure to remember to run bundle install
and npm i
in WSL first to install the Ruby and Node.js codebases.)
Thanks to Veselin Romic and Brittney Postma for debugging my stacktrace.
Github Pages
Adding Tailwind to Jekyll requires moving the site off of GitHub Pages as a build engine, because GitHub Pages doesn’t let you use more than a few preapproved Jekyll plugins, and jekyll-postcss
isn’t one of them.
This migration will involve writing a Gemfile
and letting a less restrictive build engine + CDN, like Netlify, build and host the site instead.
(I mean, you could use a build engine and have it write output to GitHub and use GitHub Pages to host that output, but … why, now that services like Netlify exist?)
GitHub provides a github-pages
plugin that can be added to a Gemfile
to facilitate building sites written for their environment to a different build engine (it also helps w/ localhost
development, as ). It looks like github-pages-unscramble
might be handy, too, when the time comes.
Other notes
For convenience, my sample web site includes some package.json
commands that let you type less text to kick off Jekyll.
- Instead of running
NODE_ENV=production JEKYLL_ENV=production bundle exec jekyll build
- Instead of running
NODE_ENV=development JEKYLL_ENV=development bundle exec jekyll serve
you can runnpm run develop
ornpm run dev
.
Background (why Tailwind)
When I first encountered utility CSS class libraries like Tailwind, I hated them. Who on earth would want to take easy-to-read HTML and turn it into such a nightmare?
However, once I got used to it (so that I could start playing with copy-paste pre-styled page section component libraries like Tailwind UI), and once I got used to sectioning static site generator templates appropriately for page section components, suddenly the idea of styling components anywhere but within the file that the HTML lived in seemed disorganized & annoying.
As verbose as utility classes could be, at least they lived & died with their HTML, and that was comforting somehow.
I could add or remove page elements at will and not worry about breaking things or leaving behind confusing artifacts.
I’ve recently worked out how to add Algolia search to a Jekyll site, but the navigation bar on that site was a “don’t touch code you don’t understand” hot mess. I’ve worked out a navbar I trust over the last few months in Tailwind, and into which I’ve successfully put a search widget. I decided I’d be best off just rearchitecting the whole site’s theme to be componentized & to use Tailwind CSS, so that it’d be easy not only to add search, but anything else that might come up in the future.