I love visual consistency and have a lot of appreciation for things that fit together. Especially, when multiple unrelated things are adjusted just for this purpose.

I was fortunate enough to catch an era when it was still mainstream to give your computer a personality. Even the laziest people spent some time to choose a wallpaper for their desktop. Some went above and beyond tweaking everything about the appearance of the system, making it truly their own. I was one of those people.

Nowadays, I don’t spend a lot of time customizing my desktop. If I do, it is mainly related to productivity, and not around the look and feel. However, the bare minimum that I still do is periodically changing a wallpaper. I guess that makes me the laziest by my own measure.

Sometime ago, I discovered wallhaven.cc, which is a treasure trove of desktop backgrounds. It has minimal interface, infinite scroll for results and provides all images in full res without any fuss. More websites should be like that.

There I found my next wallpaper in above-4k resolution, satisfying my strange affection for hexagons.

Hex universe wallpaper wallhaven.cc/w/3zg3xd

Changing a wallpaper, though, created a cascading problem with the visuals of my desktop. You see, I have this strange compulsion of having a nice and clean styling of new tabs in the browser. So I had no choice but to update how my new tab looks.

I had a feeling that a blurred version of the original wallpaper would work well. It’s not the same, so I wouldn’t get tired of it. Yet it’s similar enough, so they fit together visually. Also, my new tab works best, when all the content is embedded into a single HTML file. Fortunately, there are many ways to compress a blurred image so that it can be embedded in the page source.

I heard about BlurHash, and thought it would be a perfect tool for the job. Its original purpose is to make image placeholders on your website look very close to actual images while those are loading. It does that by encoding a blurred version of an image as a short string. Your backend can always send the short string along with the fast-to-load textual content. The UI can then show the blurred image while the crispy original is fetched in the background.

Here is how it looks in action when I apply it to the wallpaper:

BlurHash flow Blurring an image

My initial idea was to include the blur hash value into the page HTML, and also inline a copy of the BlurHash decoder to unwrap the hash. Then I realized that I don’t actually need the hash nor the decoder in the page. I can decode the hash manually once and use the result directly.

The actual output of the decoded blur hash is a tiny image of 32x32 pixels. This whole image can be encoded in a data URL and embedded in the page as a string. But how would that look if we use such a small image stretched as a background of a page?

CSS
.background {
  width: 100%;
  height: 100%;
  background-size: 100% 100%;
  background-image: url(data:image/png;base64,<actual data>)
}

I guessed that it would be pixelated, but I was wrong. It turns out that background-images are smoothly interpolated when stretched to fill the dimensions. Moreover, it does not even matter if the proportions of the stretch target are completely different.

Stretched background image Rendered page on a 3174 × 1596 screenshot

As a result, I have a new tab page that is under 2Kb in size and renders nicely for any window size, even on 4K display.

Here is the full code for the page in the last screenshot:

HTML
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <style>
      html,
      body {
        margin: 0;
        height: 100%;
        padding: 0;
        background: #C5E0F0;
      }
      .background {
        width: 100%;
        height: 100%;
        background-size: 100% 100%;
        background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAjxJREFUWEetVk0rRFEYPu/SH7CXqSmapGbJblJKSspiFpowCjPNZCEbFhYsFCVKE80oZSElSZJE+Fuu5n6ce88578e5cWtqOu9znvd5v845ULv6DhT5gWMJV9xlAyeYTSwlgCeJrRlQHqdZBbDEZoDOjUEiwRh1sNL7YkogMcvlkCoGq73Pvwnw0MhBYK37wQuwrP+tFjYu33NwmlCvjQIImhdvXjwqg4r+eiZOEtDqvLIQbXRQAS0h8JanoH3+ggoIFwlphusYQ0URYrmjrn32jMRG9K3mSrdgGUJLROiA1smTt4AASYu95DgXygHN40dDAKUGiVlFgtIvEoMhbVBaFVg/fLB50Pzb0dupNyInonakBUpB/eBemCe3213n5oxihJrFMkJt785vDDNTYdcZLUXS+sKUQHXnFqukLgPWE+ZaHJuZBLeMyASFF9X89g1fArOvEGFpwfHUc4dmoGBm8xoVkGeW3TFCd6PNDZVGl8wAMvZ0acJM0cmkLDBR7zAZkE5E3E7eEognKC+eyj1g+2Hbln5+YI6gtHAkCpAv3wiRP5VKQXF230sAFlfejWgGClO73jxeQPEtYIYCw5NbXrxuGfBtetWTFQrlhic0Uu7OvHUb0j2oCbIcUBxdZoeXU4fNPXd2YM0MI0NV04fFQKXUcWSf9RlWrixQGpxLoUi4xjsgtusDL8EnzhNDf12vuY+R7HEKYwPTuICYJCl8yN3//aS3k60XI5IaDMZVhcRgBvu48XEaYXA3v3OfInWteFJtAAAAAElFTkSuQmCC);
      }
    </style>
  </head>
  <body>
    <div class="background"></div>
  </body>
</html>