Gradientment, the Image Gradient Map Generator

Gradientment converts your 2D images into two overlapping 1D gradients & spits out the highly-compacted CSS used to generate these gradient maps, for perceived-faster progressive image loading or for artistic purposes. Sure, you could use a single flat average colour to represent the image until it loads… But that’s literally the bare minimum you could do, with zero spatial data represented. Gradient maps provide a little more definition, for as few extra bytes of bloat as possible. Only 100 extra bytes with the default settings! At higher values it transforms from a web tool into an art tool, creating interesting & unique plaid/tartan-like representations of images. Plaid-ify your images!

Drop image here or
4
5
Source image


– bytes

How to use Gradientment

If nothing works, you might need to disable your content blocker to let this page’s built-in JavaScript run.

  1. Select an image on your device.
  2. Adjust the number of Rows and Columns down as low as looks good for maximum compact representation, or all the way to the right for maximum artistic plaid representation.
  3. Turn on OKLCH mode if you want extra accuracy/more muted colours in exchange for slower processing & another 18 bytes.
  4. Copy the CSS into your project, either directly into the style tag on the specific image in your HTML (best option) or into your CSS matching the image’s ID tag (not as good but still a great option).
  5. Repeat for any other images you want gradient maps for and enjoy!

Quick privacy note: all processing happens locally in your browser through plain JavaScript; images & results are never uploaded or shared anywhere. I have generic Analytics on this website to track page views etc, but there’s nothing tracking how you use Gradientment or the images you select or the gradient maps you generate. In fact you “should” be able to save this page to your device to use Gradientment entirely offline.

Examples

A standup comedy stage lit by blue and purple light A gradient map of a standup comedy stage
“Standup Stage” – background:linear-gradient(90deg,#1278,#1028,#1128,#1148,#0018,#0018),linear-gradient(#208,#70c,#207,#104,#104,#84e,#102,#000); (127 bytes)

Mars the cat hiding under a red blanket A gradient map of Mars the cat hiding under a red blanket
“Mars Kitty” – background:linear-gradient(90deg,#a458,#6128),linear-gradient(#c24,#712,#644); (78 bytes)

The Riven Journals Temple The Riven Journals gradient map
“Riven Journals” – background:linear-gradient(in oklch,#3228,#3228,#3228,#4328,#3228,#3328),linear-gradient(90deg in oklch,#321,#432,#322,#432,#322,#432,#322); (140 bytes)

DeLorean Display Brisbane City Hall DeLorean Display Brisbane City Hall Gradient Map
“Brisbane DeLorean” – background:linear-gradient(90deg,#8458,#7448),linear-gradient(#543,#654,#633,#a66,#746,#634,#834); (98 bytes)

Gehn's Holographic Imager from the game Riven. It's currently running, and depicting an image of Mike Ando aka riumplus aka RIUM+ dressed as a mad scientist on the Andotrope holographic display. Andotrope Gradient Map
“Andotrope” – background:linear-gradient(#7648,#7648,#7658,#ddd8,#eee8,#eee8,#a998,#9748,#7528,#9858,#cb78,#ba88,#8738,#7648,#7538,#7638,#8738,#3228,#0118,#1118,#1128,#1128,#3468,#26c8,#38d8,#0128,#1258,#1138,#2238,#4678,#5778,#4558,#4548,#3448,#4788,#5ad8,#5ae8,#6ae8,#6be8,#6ae8,#6ae8,#6ae8,#6ae8,#6ae8,#5ae8,#2468,#0118,#1128,#2118,#4328,#6428,#6438,#6538,#7648,#2118,#2118,#3328,#1118,#ccb8,#bbb8,#bbb8,#aaa8,#aaa8,#a998,#a998,#8768,#9868,#7658,#9868,#a868,#a868,#a868,#8758,#a868,#a968,#a978,#a868,#a868,#a868,#a868,#9868,#7668,#9888,#9888,#9888,#8888,#8778,#6548,#1118,#2118,#2118,#3218,#7528,#a828,#b838,#b838,#b938,#b948,#c948,#b948),linear-gradient(90deg,#111,#111,#111,#111,#111,#111,#111,#111,#111,#111,#111,#111,#111,#111,#111,#111,#111,#111,#111,#111,#111,#211,#321,#321,#321,#322,#322,#322,#432,#331,#542,#752,#642,#532,#431,#642,#431,#432,#432,#322,#221,#211,#853,#122,#113,#013,#124,#124,#024,#123,#854,#212,#112,#111,#222,#333,#432,#975,#752,#642,#a95,#763,#421,#753,#753,#542,#532,#432,#532,#532,#532,#532,#532,#532,#532,#532,#432,#432,#432,#542,#532,#543,#543,#764,#876,#875,#876,#987,#997,#997,#a98,#a98,#a98,#a98,#a98,#a98,#a98,#a98,#998,#a98); (1151 bytes)

Fiji Beachouse Fiji Beachouse Gradient
“Fiji Beachouse” – background:linear-gradient(#acd8,#bcd8,#bcd8,#cde8,#dee8,#dee8,#cde8,#bcd8,#cde8,#cde8,#cde8,#acd8,#bcd8,#cdd8,#cdd8,#bcd8,#cdd8,#dde8,#9a98,#99a8,#8898,#7888,#9998,#7788,#8888,#8898,#8898,#7788,#8888,#8898,#8898,#8898,#8898,#9898,#8888,#8898,#9888,#7648,#6548,#6548,#6548,#6548,#6658,#6648,#7658,#6658,#6658,#7658,#4338,#5438,#8768,#8768,#b988,#9878,#5548,#8758,#3448,#3798,#48a8,#2798,#2798,#49b8,#4ab8,#4ab8,#4ab8,#39b8,#39b8,#39a8,#3ab8,#39a8,#39a8,#3ab8,#4ab8,#3ab8,#3ab8,#39a8,#39a8,#39b8,#4ab8,#9cd8,#acd8,#acd8,#9cd8,#8cc8,#6bc8,#5bc8,#5bc8,#5bc8,#5bc8,#4ab8,#4ab8,#4ab8,#4ab8,#4ab8,#4ab8,#3ab8,#4ab8,#4ab8,#4ab8,#4ab8),linear-gradient(90deg,#442,#442,#641,#887,#764,#442,#998,#885,#673,#331,#221,#221,#671,#9b2,#9a2,#a76,#944,#843,#532,#522,#b98,#623,#caa,#b98,#983,#994,#993,#892,#772,#433,#543,#533,#533,#452,#452,#442,#341,#442,#664,#653,#875,#885,#451,#562,#662,#a85,#976,#553,#332,#755,#654,#643,#432,#322,#211,#322,#433,#985,#873,#533,#221,#432,#421,#322,#543,#876,#675,#452,#232,#232,#231,#231,#774,#986,#543,#575,#453,#332,#451,#342,#454,#433,#433,#433,#332,#332,#342,#462,#674,#452,#443,#222,#212,#444,#9a8,#564,#443,#322,#432,#321); (1151 bytes)

Hospital Food Hospital Food Gradient Map
“Hospital Food” – background:linear-gradient(#ccc8,#ccc8,#ccc8,#ccc8,#ccc8,#ccc8,#ccc8,#ccc8,#ccc8,#5668,#3458,#4568,#99a8,#dee8,#dde8,#ddd8,#ddd8,#7988,#4638,#8988,#5838,#4628,#5728,#7938,#7938,#7938,#7938,#7938,#7938,#3618,#4628,#3618,#3428,#3328,#4538,#8968,#7728,#8948,#7828,#6828,#7828,#7718,#8848,#8738,#a318,#b318,#b318,#c418,#c418,#c418,#c418,#c418,#c418,#d518,#c418,#c418,#c318,#9218,#b318,#c418,#c418,#c418,#c418,#c418,#7018,#b318,#b318,#b318,#a318,#a318,#9218,#9218,#8218,#7218,#7118,#7118,#6118,#6118,#6118,#6218,#6218,#5118,#5118,#5218,#5218,#6218,#6448,#6568,#6568,#6668,#6668,#6668,#6678,#6778,#6778,#5568,#2238,#0018,#0018,#1118),linear-gradient(90deg,#334,#345,#456,#223,#334,#456,#112,#233,#334,#345,#345,#122,#234,#334,#334,#345,#334,#345,#234,#556,#eee,#dee,#dee,#dee,#dee,#dee,#dee,#dee,#ddd,#ddd,#ddd,#dbb,#d52,#d51,#c41,#c41,#b31,#c31,#c31,#c41,#c42,#b41,#c31,#c31,#b21,#a01,#c31,#c31,#b21,#c41,#c31,#c31,#c41,#c41,#c41,#cba,#bba,#b98,#a75,#a85,#a86,#865,#a98,#976,#975,#986,#a97,#a97,#b98,#b96,#b86,#cba,#cba,#cba,#cba,#c85,#b98,#9a9,#bba,#ddc,#ddd,#ddd,#564,#563,#b43,#b64,#c75,#db9,#dee,#dee,#eee,#eee,#eee,#bcc,#223,#223,#223,#223,#334,#334); (1151 bytes)

Additionally, you can see the gradient maps in action in a real-world test scenario on a live website (along with some progressive-encoded AVIF images if your browser supports them) in the first section of the Riven Journals, in the main temple and the close-ups of any journal before you open the book. I’ve also added gradient maps to the first/hero images of every article on this riumplus.com website.

But why?

As of mid 2026, modern web image formats like WEBP and AVIF have lackluster progressive rendering in web browsers. For WEBP, its progressive rendering is a suboptimal top-to-bottom style and it takes a while to show anything, waiting until both chroma channels have been downloaded first (and Safari shows no progressive rendering at all). For AVIF, standard-encoded images have no progressive rendering and only pop into view when fully downloaded. The AVIF spec does support progressive rendering though (except progressive AVIF rendering is currently broken on Firefox), and it is possible to generate files that do it, but it’s not the easy default “save from Photoshop” option (there’s a good article here about the state of progressive images which also details how to create progressive AVIFs if you’re interested). In short, actually seeing a flash of a progressively-loaded image is not as common as it used to be with an old-fashioned progressively-encoded JPEG.

But even if you stick with progressively-encoded JPEGs, there can still be a delay in seeing something if there’s a delay between your HTML parsing and your image’s data packets arriving. Like if you have a slow or intermittent internet connection, a poor/flakey WiFi or cellular signal, you’re running a faraway VPN or TOR connection, or if you’re connected to a slow web server on shared hosting. With a gradient map, you see something vaguely resembling your image straight away before your image has started to display – no matter the format and no matter how long the image takes to load. It doesn’t decrease the actual loading speed of your website (in fact it very slightly increases it), but it does increase your website’s perceived loading speed a little, so it feels faster.

Tools like Blurhash are great, but they fill a different, more complex niche – they usually require server-side processing of some kind, the delay of a round-trip packet to the server, and downloading/running more JavaScript. This is a solution that runs with pure CSS (old CSS that’s been supported for years, too), that usually displays within tens of milliseconds.

Why not just embed a base64-encoded image?

A 3×3 well-compressed PNG base64-encoded amounts to 168 bytes, and that’s not much definition at all; larger images are even bigger. A 3×4 gradient map is 100 bytes with each additional colour sample adding only another 5-6 bytes, even less when the page gets gzipped. What would you do to save a few bytes? Or to put it another way… For 100 extra bytes to your first/hero image or two, why not use gradient maps to have better perceived loading?

Hey I never said turning a 2D image into two overlapping 1D gradients was a practical idea in all scenarios, but I couldn’t find any evidence of anyone trying this technique before (though it must’ve been attempted by someone out there). So I created this tool, Gradientment, to easily generate them.

Consider it an interesting art experiment to make plaid versions of your images that’s fun to play around with if you don’t want to seriously use it on a website.

What’s OKLCH mode?

This enables linear OKLCH processing on both the gradient generation step as well as appending the tag to use OKLCH blending in the final CSS. Combined with the way pixel averaging is already performed manually by a box filter instead of using your browser’s built-in rescaler to make sure it’s done right, this produces much more perceptually-accurate colours. This matters the most in highly-saturated images. However it’s off by default because it’s much slower to compute, produces much more muted results, & takes up another 18 bytes in the final CSS. If you want, you can check the box to use OKLCH processing and manually remove the extra CSS tags to get the processing accuracy without the CSS “bloat”. It’s interesting to see how much of difference this checkbox makes on the final gradient map, though – even when the colours are compressed down to 3-character #RGB codes.

npm/pip/Wordpress plugins?

Sorry, I am an artist & inventor, not a coder. This is all you’ll get from me. Feel free to implement this technique yourself in whatever framework/language/system you like; I’m not about to claim ownership of the basic CSS used in gradient maps or anything! I’d love to add a link to your repo here.

Any other usage tips?

Gradient maps work best when an image has large, low-frequency changes in brightness or colour in either straight horizontal or vertical directions. Otherwise they can look a bit muddied and might not be worth implementing.

Adding decoding=”async” to any images used with this technique helps make sure any progressive version of the actual image will display as soon as possible on all browsers. In my experience, that’s an extra 15-30ms. Go on, you can spare a few more bytes for a few more milliseconds; look at how much you just saved by using a gradient map that uses compressed 3-character #RGB colour codes instead of those hugely-wasteful 6-character #RRGGBB colour codes!

I also advise against doing this technique as a blanket optimisation to every image on your entire website due to the CPU overhead of generating a huge number of blended gradients. Doing it to just the hero images displayed above the fold should be good enough.

Speaking of tips

Like Gradientment? Donate to my Ko-fi, comment below or drop me a line to say thanks! The more donations/encouragement I receive, the more likely I am to release more guides & tools like this in the future.


Similar Posts

New Andotrope Website

New Andotrope Website

This is just a quick update to say that I’ve launched a new website for my Andotrope omnidirectional displays! Having a dedicated space to promote them makes it easier to share them with others. Plus,...
Andotrope v2 – Smaller, Faster, Quieter, Cheaper

Andotrope v2 – Smaller, Faster, Quieter, Cheaper

Since completing the first Andotrope proof-of-concept, I’ve been refining & improving the technology. Here’s version 2 – a lot has changed! I built v1 as a work of art, but I designed v2 to sit...
Gehn’s Holographic Imager/​Andotrope

Gehn’s Holographic Imager/​Andotrope

For my secret project for Mysterium 2023, I’ve spent the past 8 months making a replica of one of Gehn’s holographic Imagers from the game Riven: The Sequel to Myst… And thanks to some patent-pending...

There are no comments yet, add one below.

Leave a Reply


Name (required)

Email (required)

Website