Question:
How to use Javascript to find all the elements on the page in which the text is written in black on a black background? At the same time, a black background/color can be assigned not to the element itself, but to a distant parent, but after all inheritances, the result is black on black.
We set the task: to make a version for the visually impaired on the site. One of the points is color inversion, that is, we display white text on a black background. I added a black background
to the body
, corrected the css for other containers, everything is fine, except for one thing. In the admin area of some pages in the WYSIWYG editor, the text color is explicitly black (in the style
attribute). As a result, this text is not visible on the page.
I want to find a solution that will solve the problem without changing the code of the pages .
For example, so that javascript automatically finds such text and changes its color to white. The question is how to find such elements.
So far, I see only the option of recursively passing through all DOM elements, remembering the background
of the parent and checking the color of the element itself.
But maybe there is an easier way, some solution in a couple of lines in jquery?
In other words, we need to ensure that in the example in the second div > p
the text is visible:
.orig {
background-color: #fff;
}
.invert {
background-color: #000;
}
<h2>Оригинал</h2>
<div class="orig"><p style="color: black">Текст</p></div>
<h2>Инверсия</h2>
<div class="invert"><p style="color: black">Текст</p></div>
Answer:
The thought occurred to me that the styles set in the editor would not necessarily set the text to black – it could be dark gray or some kind of brown. Text of this color on an inverted background will still be difficult for visually impaired people to read, so you need to determine the contrast of text and background.
The code is partially copied and pasted from Leah Veru 's contrast meter.
What happens in this code: getLuminance()
function returns relative luminance ; the getContrastRatio()
function returns the contrast ratio from the background and text color data entered there. We go through each paragraph inside the .invert
block, determine the contrast ratio , and if it is less than 7 (this is the WCAG requirement), we make the text white, and if it is more than 7, then we leave it as it is.
UPD : I rewrote the code to define the background color not for the parent, but for the element itself, for this you need to write a paragraph in CSS background-color: inherit
and assign the value of your own background color to the bg
variable: bg = $(item).css('background-color')
.
UPD : the final version , allowing you to do anything with elements that have insufficient contrast and without using background-color: inherit
.
Sources:
Relative luminance calculation formula: https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef .
Formula for calculating contrast ratio : https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef .
$(function() {
var color, bg, textLuminance, parentLuminance, cr;
$('.invert p').each(function(index, item) {
color = $(item).css('color'),
bg = $(item).css('background-color');
textLuminance = getLuminance(color);
parentLuminance = getLuminance(bg);
cr = getContrastRatio(textLuminance, parentLuminance);
if(cr <= 7) $(item).css('color', '#fff');
});
function getContrastRatio(l1, l2) {
l1 += .05,
l2 += .05;
var ratio = l1 / l2;
if (l2 > l1) {
ratio = 1 / ratio;
}
return ratio = Math.round(ratio, 1);
}
function getLuminance(color) {
var rgb = color.slice(4, -1).split(',').map(Number);
for (var i = 0; i < 3; i++) {
var rgbI = rgb[i];
rgbI /= 255;
rgbI = rgbI < .03928 ? rgbI / 12.92 : Math.pow((rgbI + .055) / 1.055, 2.4);
rgb[i] = rgbI;
}
return .2126 * rgb[0] + .7152 * rgb[1] + 0.0722 * rgb[2];
}
});
.orig {
background-color: #fff;
}
.invert {
background-color: #000;
}
.invert p {
padding: 5px;
background-color: inherit;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>Оригинал</h2>
<div class="orig">
<p style="color: black">Текст</p>
</div>
<h2>Инверсия</h2>
<div class="invert">
<p>Обычный текст без инлайновых стилей</p>
</div>
<div class="invert">
<div style="background-color: #fff">
<div style="background-color: #ff0">
<div>
<p style="color: black">Черный Текст</p>
</div>
</div>
</div>
</div>
<div class="invert">
<p style="color: brown; background: darkgrey">Коричневый Текст</p>
</div>
<div class="invert">
<p style="color: blue">Синий Текст</p>
</div>
<div class="invert">
<p style="color: yellow">Желтый Текст</p>
</div>
<div class="invert">
<p style="color: orange">Оранжевый Текст</p>
</div>