Extract Colors from an Image for CSS Themes

Working through the migration of Blog Awesome from WordPress to Eleventy, I encountered an interesting problem: each blog post was seeded with a featured image at the top, though the image did not cover the entirety of the header.

This required a …


This content originally appeared on Zach Leatherman and was authored by Zach Leatherman

Working through the migration of Blog Awesome from WordPress to Eleventy, I encountered an interesting problem: each blog post was seeded with a featured image at the top, though the image did not cover the entirety of the header.

Screenshot of blog.fontawesome.com with a featured image that says Font Awesome + 11ty

This required a manual process (a WordPress custom field) to specify a theme color to match the background of the image. We can do better!

Using a similar layout structure, this what the new design looks like (with a bit better automatic dark/light mode contrast on the flag and text color, too):

Screenshot of the new blog.fontawesome.com with a featured image that says Font Awesome + 11ty

To accomplish this automation, I turned to a lovely zero-dependency package called extract-colors from namide.com.

In all of the eligible blog posts tested, the last color returned in the result from the extract-colors package always matched the background color of the image being sampled.

extract-colors recommends the use of another package (get-pixels) to extract pixel data from images but it was no longer maintained so I forked, updated, and released a Node.js only version of the package to fix some upstream issues.

New @11ty/image-color Package

I wired this up with a memoization layer, a disk cache, a concurrency queue, and integrated it with existing overlapping functionality provided by Eleventy Fetch and Image utilities for build performance (as well as adding Color.js for some color filtering) and packaged this all up for anyone to use at @11ty/image-color:

Screenshot image for https://v1.screenshot.11ty.dev/https%3A%2F%2Fgithub.com%2F11ty%2Fimage-color/opengraph//

To get colors from a local or remote Image in my Eleventy project, I added the following configuration code to my project’s eleventy.config.js file:

import { getImageColors } from "@11ty/image-color";

export default async function(eleventyConfig) {
	eleventyConfig.addFilter("getImageColors", async (imageSrc) => {
		return getImageColors(imageSrc);
	});
}

The above Blog Awesome example above made good use of the getImageColors filter in a Nunjucks template:

{%- set lastColor = media.featuredImage | getImageColors | last %}
{% if lastColor %}
	<style>
	header {
		background-color: {{ lastColor.background }};
		color: {{ lastColor.foreground }};
	}
	</style>
{% endif %}
<header></header>

Screenshot Borders

For extra funsies I also made use of this functionality on 11ty.dev (now live on the site) to provide an extra accent border color on screenshot images:

A 4×4 matrix of small screenshots of the Built With Eleventy section on the 11ty.dev home page. Each screenshot has a border color that matches the favicon image

This example works a little differently: it samples colors from the favicon images of each site as an easy way to guess the site’s theme colors.

This package doesn’t take a hard stance on the validity of colors but I did make use of additional filtering to select a nice border color from the list of colors available in each favicon, with the code looking something like this (again, eleventy.config.js Configuration code):

import { getImageColors } from "@11ty/image-color";

export default async function(eleventyConfig) {
	eleventyConfig.addShortcode("getColorsForUrl", async (url) => {
		let avatarUrl = `https://v1.indieweb-avatar.11ty.dev/${encodeURIComponent(url)}/`;

		return getImageColors(avatarUrl).then(colors => {
			// Note the map to colorjs props here
			return colors.map(c => c.colorjs).filter(c => {
				// Not too dark, not too light
				return c.oklch.l > .4 && c.oklch.l <= .95;
			}).sort((a, b) => {
				return (b.oklch.l + b.oklch.c) - (a.oklch.l + a.oklch.c);
			});
		})
	});
};

…which subsequently wound up in a WebC template a little like this:

<script webc:setup>
async function getPrimaryColorStyle(url) {
	let colors = await getColorsForUrl(url);
	if(colors.length > 0) {
		return `--card-border-color: ${colors[0].toString({format: "hex"})}`;
	}
}
</script>
<a :href="url" class="card" :style="getPrimaryColorStyle(url)"></a>

More Open Source

This Blog Awesome migration project (launching soon!) has yielded a few more useful open source utilities to the Eleventy ecosystem, which I encourage you to try out!


This content originally appeared on Zach Leatherman and was authored by Zach Leatherman


Print Share Comment Cite Upload Translate Updates
APA

Zach Leatherman | Sciencx (2025-02-27T06:00:00+00:00) Extract Colors from an Image for CSS Themes. Retrieved from https://www.scien.cx/2025/02/27/extract-colors-from-an-image-for-css-themes/

MLA
" » Extract Colors from an Image for CSS Themes." Zach Leatherman | Sciencx - Thursday February 27, 2025, https://www.scien.cx/2025/02/27/extract-colors-from-an-image-for-css-themes/
HARVARD
Zach Leatherman | Sciencx Thursday February 27, 2025 » Extract Colors from an Image for CSS Themes., viewed ,<https://www.scien.cx/2025/02/27/extract-colors-from-an-image-for-css-themes/>
VANCOUVER
Zach Leatherman | Sciencx - » Extract Colors from an Image for CSS Themes. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2025/02/27/extract-colors-from-an-image-for-css-themes/
CHICAGO
" » Extract Colors from an Image for CSS Themes." Zach Leatherman | Sciencx - Accessed . https://www.scien.cx/2025/02/27/extract-colors-from-an-image-for-css-themes/
IEEE
" » Extract Colors from an Image for CSS Themes." Zach Leatherman | Sciencx [Online]. Available: https://www.scien.cx/2025/02/27/extract-colors-from-an-image-for-css-themes/. [Accessed: ]
rf:citation
» Extract Colors from an Image for CSS Themes | Zach Leatherman | Sciencx | https://www.scien.cx/2025/02/27/extract-colors-from-an-image-for-css-themes/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.