Updating a 6 year old Jekyll & Bootstrap website
By no stretch of imagination am I a frontend person. Graphic design is not my passion. I even got the colour blindness perk. I do like this little website I’ve written over the years and I kind of want it to look nice. And while the design I had created a few years ago still works, it’s also dependent on an outdated version of Jekyll, and it has a few technical issues. So please, follow a long, as a DevOps engineer tries to explain how to make a nice-looking website.
So in no particular order, let’s see what I actually discovered along the way and what things turned out to be useful.
Updating Bootstrap 4.6 to 5.2
Bootstrap has both changed a lot and not changed at all, which made the upgrade somewhat tedious. You can read the Bootstrap changelog for more details. For the most the most part, things were alright. A non-exhaustive list of things that bit me is
The official Sass compiler was changed from
libsassto Dart Sass. You can still compile Bootstrap with libsass, but now you will notice the bugs in the compiler that Bootstrap no longer works around. For example,
libsasshandles negative numbers incorrectly causing them to sometimes not be equal to themselves. It only causes minor issues like the pagination number boxes being rounded when they shouldn’t, so if you want to avoid Dart you can still go for it.
Many CSS classes have moved from outer element to the inner one. For example: items in the navigation bar in 4.6 would apply the
.activeclass to the outer
.nav-itemelement, but Bootstrap 5 requires you to apply it to the
Actually putting this all together is not too hard. Most things actually translated quite naturally. As part of updating the styling, I found that it was easier to remove my custom components and replace them with modified Bootstrap components.
Speaking of modifications: previously this site used the Superhero Bootstrap theme which worked
well enough but requires a bunch of scaffolding code and doesn’t really integrate into Bootrap, but
rather forces itself through. This has funny results like
$blue not being blue at all, though most
of the time it results in redundant code. Theming is now completely done with variable overrides,
and just 30 lines of overrides (including comments and whitespace) is enough to somewhat
consistently override default colours and “work around” assumptions of contrast between them.
The basics for this theming can be as simple as the snippet below. The only hard thing about it was choosing a proper color scheme. I found Coolors helpful to compensate for my less-than-stellar design skills. The linked colour scheme is not coincidentally a colour scheme I liked but didn’t actually go for. By all means use it.
1 2 3 4 5 6 7 8 9 10 @import "bootstrap/functions"; // Don't actually use these colors $body-bg: purple; $body-color: azure; $primary: ivory; $secondary: navy; $dark: thistle; // Import the rest of Bootstrap
Moving the build to Github Actions
While I was working on the the big refactor, Github first teased, then finally announced a solution to the much requested Jekyll 4 support in Github Pages. Seeing as I’ve been waiting for this feature ever since Jekyll came out1 I wasn’t really expecting anything, but it is now possible to manually build your site using Github Actions. That means that we can now have full control over the build process and can do anything we want.
The example workflows Github has provided are actually very simple and you can
mostly drop them in. I had one issue with them, which could be resolved by
--baseurl override, but this has since been resolved. Great issue response, guys!
It turns out that I don’t really want all that much. The only immediate thorn in my side that I
could fix was to update the default Sass compiler. Jekyll ships with
sassc by default, which
doesn’t handle negative numbers properly and causes a few miscompilations with Bootstrap. Luckily,
it also supports using the reference Dart Sass compiler. All that’s needed is adding the
sass-embedded gem and overriding the compiler preference:
1 2 3 # _config.yml sass: implementation: sass-embedded
Replacing the math renderer
My posts occasionally contain some maths and because I have been properly taught at some point in my life, I like to typeset that in .2 Regrettably, support for Latex in HTML is still not really a thing so you need to render it one way or another.
Kramdown by default comes with “MathJax support” but that mostly means that instances of
maths$$ are replaced with
\(some maths\). No actual rendering is done while building the site. To
then in turn marks up the text and loads some more fonts for the true Latex look and feel. This is
kind of slow and changes the page layout, so you get that much maligned layout shift effect.
You are familiar with this effect, but you might not know it was called like that. For a refresher, try clicking the green button in the demo below.
There is an official plugin for Kramdown that makes it use KaTex. You can simply
add the gem to your build, and enable with by adding the following to your
1 2 kramdown: math: katex
Unfortunately that doesn’t include the KaTeX CSS yet, so we still need to add that to the site. The recommended method appears to be to use the jsDelivr CDN, but public CDNs aren’t that great of an idea so I didn’t want to do that. Instead I wrote my own Jekyll plugin to automatically copy the relevant files from the KaTeX gem. This plugin can probably be done better by someone who actually knows how to write Ruby, but it gets the job done:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 require 'katex' require 'find' require 'pathname' module Jekyll module KatexBundle class KatexResource < Jekyll::StaticFile def destination(dest) File.join(dest, 'assets', 'katex', @dir, @name) end end class Generator < Jekyll::Generator def generate(site) @site = site @site.static_files << css_file @site.static_files.concat font_files end private def css_file() path = Pathname.new File.join(Katex.gem_path, 'vendor', 'katex', 'stylesheets', 'katex.css') source = path.dirname() file = path.basename() KatexResource.new @site, source, '', file end def font_files() assets_dir = File.join(Katex.gem_path, 'vendor', 'katex') fonts_dir = File.join(assets_dir, 'fonts') fonts =  Find.find(fonts_dir).each do |path| next if File.directory?(path) path = path.sub(fonts_dir, 'fonts') dir = File.dirname(path) file = File.basename(path) static_file = KatexResource.new(@site, assets_dir, dir, file) fonts << static_file end fonts end end end end
In the future I may decide to release this as a standalone plugin. The KaTeX gem also appears to support sprockets, so maybe I’ll try to get that to work instead. The Jekyll Assets plugin looks promising.
The main update is now a few months behind me and things work well enough. Now back to non-radical, incremental change. Or maybe I’ll rewrite it in Cobalt or Zola in a few months. Who knows? For now, the site can look like this for a while.