Using Display-P3 colour
source link: https://darn.es/using-display-p3-colour/?ref=sidebar
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Using Display-P3 colour
Wednesday, 15th June, 2022
My personal site uses Ghost under the hood, which gives me a number of features to enrich my content. One of these features is accent colours. I can apply an accent colour to the whole site or to tags. You'll notice even on this page there's an accent colour affecting the links, icons and header.
<style>
:root {
--color-accent: {{ site.accent_color }};
}
</style>
Example of how I use accent colours in my site
The above code is lifted straight from my site. I use custom properties throughout to expose the accent colour to my CSS. The double curly brackets are for Nunjucks, the templating language I use with Eleventy to expose content from Ghost and build my site.
Display-P3Direct link to Display-P3
But of course that wasn't enough for me. I didn't want bright accent colours, I wanted really bright accent colours. Display-P3 is a colour gamut which extends further than other colour spaces such as sRGB. The WebKit blog goes into much finer detail on the subject.
At the time of writing the only way to access this extended colour space in CSS is by using the color()
function and viewing the page in Safari. In addition, Ghost's accent colour feature is limited by hexadecimal colour codes and is therefore bound to the sRGB colour space. However, in typical fashion, I double down on the commitment to that hotter pink.
Converting hex to P3, the cheap wayDirect link to Converting hex to P3, the cheap way
Thankfully the route to that hotter pink is somewhat short. The steps I've worked out are based on the fact that Display-P3 written in a color()
function is made up of red, green and blue channels. So in theory I could convert my hexadecimal colours into RGB values and then convert those into Display-P3 compatible values. Even though RGB channels range from 0 to 225 and Display-P3 0 to 1 it's not going to take much work to do the maths.
I mentioned before that I use Eleventy to build my site. It's an extremely flexible tool, so flexible that I can build in my own filters in vanilla JavaScript to manipulate content. Here's the function I've put together to turn my hex colours into Display-P3 colour channels:
const hexToP3 = (string) => {
const aRgbHex = string.replace("#", "").match(/.{1,2}/g);
const aRgb = [
(parseInt(aRgbHex[0], 16) / 255).toFixed(2),
(parseInt(aRgbHex[1], 16) / 255).toFixed(2),
(parseInt(aRgbHex[2], 16) / 255).toFixed(2),
];
return `color(display-p3 ${aRgb.join(" ")})`;
};
Hex to P3 colour function
…and when I say "I've" I mean I based my function on the one shown here from Converting Colors:
I can then use this custom filter to convert the hexidecimal colours coming from Ghost into color(display-p3 …)
colours.
<style>
:root {
--color-accent: {{ site.accent_color | hexToP3 }};
}
</style>
Updated example code with the hex to P3 colour filter added
CompatibilityDirect link to Compatibility
As mentioned earlier, the color()
function only works in Safari, which means I need to provide some sort of fallback for the other browsers. I really hoped something like this would work:
<style>
:root {
--color-accent: {{ site.accent_color }};
--color-accent: {{ site.accent_color | hexToP3 }};
}
</style>
This does not work! Don't use this
I'd seen this method here on CSS Tricks but in both FireFox and Chrome the last property and value is applied but isn't understood as a colour, resulting in either no colour or black. I suspect this method did work at some point but has now changed, or is incompatible with custom properties.
PolyfillingDirect link to Polyfilling
The other route is to make use of a CSS query, specifically the @supports
query, to check if the browser supports the color()
CSS colour function. The resulting CSS would look something like this:
:root {
--color-accent: {{ site.accent_color }};
}
@supports (color: color(display-p3 1 1 1)) {
:root {
--color-accent: {{ site.accent_color | hexToP3 }};
}
}
This is fine, but not ideal. It's not so bad for when I'm using this accent colour for the whole page but I also use accent colours on particular elements.
<li style="--color-accent: {{ post.tags[0].accent_color }}">
<svg class="icon icon--{{ post.icon }}" aria-hidden="true">
<use xlink:href="#{{ post.icon }}"></use>
</svg>
<div>
<h2><a href="{{ post.url }}">{{ post.title }}</a></h2>
<p>{{ post.excerpt }}</p>
</div>
</li>
Here I'm setting an accent colour on a particular element, which overwrites the one on the page for just this element and all it's children. You can see the results of this on my homepage and related posts at the bottom of this page, there's a different accent colour for each post which gets applied to the icon and the heading link. This would get really messy if it was a whole <style>
block with two blocks of CSS and an @supports
.
Ideally I'd abstract that @supports
synatax into my main CSS file and leave the pure colour values, both hex and P3, inline in my HTML. And I can do that thanks to CSS custom properties!
Let's change some stuff around. Firstly the inline colours, let's abstract them away from the main --color-accent
property into their own specifically named ones.
--color-accent-hex: {{ accent_color }};
--color-accent-p3: {{ accent_color | hexToP3 }};
The accent_color
variable here could be the site colour or the tag colour.
This, while a bit long winded, can be neatly used within an inline style
attribute as well as inside a :root
CSS block.
Next I need to designate which one of these custom properties is used for the actual --color-accent
custom property depending on what the browser supports.
* {
--color-accent: var(--color-accent-hex);
}
@supports (color: color(display-p3 1 1 1)) {
* {
--color-accent: var(--color-accent-p3);
}
}
The clever part about this is the use of the wildcard selector. Using *
means I'm selecting every single element on the page and telling it which custom property, hex or P3, to use as the actual --color-accent
value. This catches not only the :root
element but also all the elements which have --color-accent-hex
and --color-accent-p3
set inline.
:root
block as well incase all these values are suddenly not available.All done! Now I have my really bright colours in the browsers that support Display-P3 and nice fallbacks for those that don't.
I hope you enjoyed this exploration into using Display-P3 on the web!
Recommend
-
138
zenburn-theme for Emacs About Zenburn for Emacs is a direct port of the popular Zenburn theme for vim, developed by
-
153
Solarized for Emacs Solarized for Emacs is an Emacs 24bit theme making use of of the Solarized palette, developed by Ethan Schoonover. You can find several screensh...
-
72
colour - Colour Science for Python
-
71
README.md vim-monokai-tasty Monokai forever! ? Inspired by Sublime Text's interpretation of monokai, this colour is both gui- and cterm-supported. It w...
-
34
GDB Colour Filter colourify backtrace output in GDB with Python API Overview GDB Colour Filterimplements frame filter for GDB Python API. There could be several chained filters. GDB calls t...
-
82
Preface I know, many of you were expecting a next post on RxVMS but you will need a bit more patience. I didn’t have time for most of this year due to projects and my repeatedly manifesting depression. I’m very...
-
41
Accent Colour Creator XDA Developers was founded by developers, for developers. It is now...
-
31
The Xiaomi and Redmi brands collectively released 13 smartphones in 2019. While Xiaomi has six devices, Redmi has seven. According to recent reports, two of Redmi’s 2019...
-
10
title date category tags Honouring the user's preferred colour scheme in CSS 2020-03-23T03:32 css colour-scheme...
-
9
Using details/summary and colour coding on GitHub pages Wednesday, January 24th, 2024 at 9:35 pm As CODE100...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK