When I was a teenager, I would redesign my website about once every month. Once every fucking month. These days, I have a lot less time and motivation – but I still enjoy using my site as a playground to try out new stuff, and it always bothers me if it's outdated. So inspired by the #newwwyear hashtag started by Jen Simmons, I decided to give my blog a little makeover.

I still really love the duotone look of the previous version, but I was ready for something new. I refactored all markup and CSS, threw out a bunch of old, messy code, tidied up the content and gave the typography a fresh makeover. Even though it feels more complex, the code actually ended up much simpler. Below, some notes on the new stuff I tried this time.

This website is written in Pug, a markup language that compiles to HTML, Sass. It's compiled using Harp. All code is open-source and available on GitHub.


One of the main reasons I was excited to refactor my site was to finally have another excuse to play around with CSS Grids. The site now uses a very simple grid to ensure consistent alignment – but it also works fine in older browsers, powered by a few short @supports queries. Developing and debugging the grid ended up being really easy, thanks to the amazing Firefox Grid Inspector (which, by the way, was also created by Jen Simmons). It's enabled by default in the developer edition, and can be toggled via the "Layout" pane in the Inspector.

Screenshot of the Firefox Grid Inspector

Colour Themes

I don't mind theming invidual posts – I don't blog often enough to make this a hassle, and considering I already spend time on picking out a header image, I might as well pick an accompanying colour. The post's theme color is used in the overview of lastest posts, as well as link underlines, inline code and other accents across the post. Colour theming is implemented using CSS Custom Properties, allowing simple inline overrides for both parent and child components:

<div class="teaser" style="--theme: #8e8ec5"></div>
.teaser {
    background-color: var(--theme);

    a {
        border-color: var(--theme);

The site still supports art-directed posts, like my travel blogs, and I'd love to experiment more with this in the future.


In the new design, finally got to use another typeface from the amazing Grilli Type collection. I've been using GT Walsheim for years now, and supporting text as well as code is now set in GT Pressura Mono. When designing the site, I only played around with the free trial version – so I didn't notice the suboptimal glyphs for curly braces, which are hard to distinguish from round brackets: {} (). Luckily, unicode-range offers a simple fix for this via a custom font family:

@font-face {
    font-family: "Code Custom";
    src: local("Monaco"), local("Menlo"), local("Courier New"); /* etc. */
    unicode-range: U+007B, U+007D;

If the character is part of the specified unicode range – in this case, curly braces – the custom font family is used. Otherwise, the font used for code defaults to the first fallback, GT Pressura Mono:

font-family: "Code Custom", "GT Pressura Mono"; /* etc. */

The unicode-range property is pretty well-supported. Browsers that don't support it will simply ignore the declaration and use the specified font for all text – which is an okay compromise in this case.

Speaking of typography: all body text is now set in the sans-serif Signika font by Anna Giedryś. I've been seeing it around for a while now, but I only just discovered that it's part of the free Google Fonts collection.

"Widow" hack for large headlines

One problem with large headlines is that it's hard to control possible line breaks. This can easily lead to so-called "widows" like this one:

Example of widow in headline: 'AI' of 'Explosion AI' ends up alone on a new line

While the problem is easy to fix in print stylesheets using the widows property, it's impossible to solve on the screen using only CSS. Inline text is fluid and how it's rendered depends on too many factors. However, a common workaround is to add a non-breaking space &nbsp; between the last two words, usually in JavaScript. Instead of doing it on the client, I've added a function to my static site generator:

function formatHeadline(text) {
    text = text.replace("'", "’");             // typographic apostrophes
    const words = text.split(' ');             // split text on whitespace
    const last = words[words.length - 1];      // get the last word
    if (last.length > 4) return text;          // possible widow is okay
    return words.slice(0, words.length - 1).join(' ') + '&nbsp;' + last;

When the Pug templates are compiled, all headlines are processed to replace regular apostrophes with typographic ones and add a non-breaking space between the last two words if the last word is 4 characters or less.

Example of no widow in headline: 'Explosion AI' ends up on a new line

The solution isn't perfect, but it generally produces better results. The overhead added to the compile time is pretty minimal, too.

Gooey headlines and navigation

Ever since I've discovered gooey SVG filters, I've been mildly obsessed with them. I've also used them for the gooey bubble buttons and their hover effects on the Prodigy website. Here's a CodePen demo of the effect:

Supported by Chrome and Firefox, patchy in Safari.

The filter causes elements close to each other to merge with smooth edges. Animated, it makes the navigation elements appear to emerge from within the logo. The effect also works well for headlines and other text elements with an inline background, to smooth out the sharp edges:

Edit the text in the demo to see how the effect adapts!

The filter can be added to any element by referencing its ID in CSS. The filter will then affect all children of the parent element.

.goo {
    filter: url("#goo")

Because my site's stylesheet is fairly compact, I run a simple Node script to inline all CSS after compiling the HTML. This also solves an issue with the relative url("#goo"), which I've mostly noticed in older versions of Firefox.


CodePen is still my go-to tool for quick UI experiments. The live editor can be used straight from the browser and supports various pre-processors for HTML, CSS and JavaScript. Many of my ideas start off with a private pen before I port them over to whichever technology I'll be working with later on. The Prodigy UI started this way, and so did the spaCy redesign and even the displaCy visualiser – and of course, this site.

Join #newwwwyear! If you feel inspired, I hope you'll check out the hashtag and join in. (The original plan includes posting your timeline and goals first, and updating about the progress – but I wasn't sure how it'd go, so before I was able to think about a plan, I was already pretty much done.)

About the author
Ines Montani

I'm a digital native, programmer and front-end developer working on Artificial Intelligence and Natural Language Processing technologies. I'm the co-founder of Explosion AI and a core developer of spaCy and Prodigy.