Add support for WCAG3 contrast using APCA
meodai opened this issue · 8 comments
Would love to see this in culori to be able to play with it.
Given APCA's license requirements around accuracy, correctness and up-to-dateness, as well as its current status as a work in progress, I don't see it as a good fit for inclusion in culori at the moment, but since culori itself is mostly a collection of functions, interoperation is fairly simple.
To obtain the Y (luminance) to pass to the contrast algorithm, you can use the wcagLuminance()
function.
import { wcagLuminance } from 'culori';
import { APCAcontrast } from 'apca-w3';
const textY = wcagLuminance('black');
const backgroundY = wcagLuminance('tomato');
const contrast = APCAcontrast(textY, backgroundY);
Note that culori's wcagLuminance
function is a bit different (but not fundamentally) from the equations proposed in apca-w3. You can use apca-w3
's sRGBtoY()
as an alternative computation that matches the exact formula.
@danburzo thanks! I was not aware of the "non commercial" license. Such a strange decisions, especially for something like that
@danburzo looks like there is a different license for the w3 version, that is more permissive: https://github.com/Myndex/apca-w3
I was actually referring to the license for the w3 version :-).
To give an example, since some of the math — such as conversion between color spaces, luminance computation etc. — is already in our codebase, we would want to use that code. apca-w3 uses slightly different constants & formulas (see this w3c/silver issue), which would make our implementation non-compliant (I think!).
It really sounds like this should remain a separate library, at least until it gets merged in some form in w3 specs.
Makes total sense. Thanks for clarifying.
...since some of the math — such as conversion between color spaces, luminance computation etc. — is already in our codebase, we would want to use that code. apca-w3 uses slightly different constants & formulas.... which would make our implementation non-compliant (I think!).
Yes, APCA does not use the sRGB to XYZ of IEC, instead, APCA calculates "Estimated Screen Luminance" Which is intended to more correctly model a calibrated sRGB monitor. And this is important for some yet unreleased feaures that more specifically accommodate certain color vision issues.
As far as color spaces, as it is perceptual contrast, It's based around color spaces of physical monitors as opposed to theoretical spaces.
We have been talking about ways to reconcile with the "math convenience" methods, But I'm currently very swamped with other pressing matters.
IN THE MEANTIME
There is a variant that is designed to work with existing standard color maths—convert the color to
It is not polarity aware, and is a more general contrast math, But it is also much much simpler. Here's the repo:
@Myndex thanks for the pointer! So that would basically be:
import { lab65 } from 'culori';
/*
Delta Phi Star perceptual lightness contrast by Andrew Somers:
https://github.com/Myndex/deltaphistar
*/
const PHI = 0.5 + Math.sqrt(1.25);
function dpsContrast(a, b) {
const dps = Math.abs(Math.pow(lab65(a).l, PHI) - Math.pow(lab65(b).l, PHI));
const contrast = Math.pow(dps, 1/PHI) * Math.SQRT2 - 40;
return contrast < 7.5 ? 0 : contrast;
}