#javascript #jquery #css
Как с помощью Javascript найти на странице все элементы, в которых текст написан черным цветом по черному фону? При этом черный фон/цвет может быть прописан не у самого элемента, а у далекого родителя, но после всех наследований в результате получается черный по черному. Поставили задачу: сделать на сайте версию для слабовидящих. Один из пунктов - инверсия цвета, то есть выводим белый текст на черном фоне. Я прописал черный background у body, поправил css для прочих контейнеров, все хорошо, за исключением одного но. В админке у некоторых страниц в редакторе WYSIWYG явно прописан черный цвет для текста (в атрибуте style). В результате этот текст не виден на странице. Я хочу найти решение, которое позволит решить проблему, не изменяя код страниц. Например, чтобы javascript автоматически находил такой текст и менял его цвет на белый. Вопрос в том, как найти такие элементы. Пока я вижу только вариант рекурсивного прохода по всем элементам DOM с запоминанием background родителя и проверкой цвета самого элемента. Но может, есть способ проще, какое-нибудь решение в пару строк на jquery? Иными словами, нужно добиться, чтобы в примере во втором div > p текст был виден: .orig { background-color: #fff; } .invert { background-color: #000; }Оригинал
Текст
Инверсия
Текст
Ответы
Ответ 1
Пришла в голову мысль, что стили, заданные в редакторе, совсем не обязательно будут задавать тексту черный цвет — это может быть и темно-серый и какой-нибудь коричневый. Текст такого цвета на инвертированном фоне слабовидящим людям будет по-прежнему тяжело прочесть, потому надо определять контрастность текста и фона. Код частично скопипастил с определителя контрастности Лии Веру. Что происходит в этом коде: функция getLuminance() возвращает relative luminance; функция getContrastRatio() возвращает contrast ratio из введенных туда данных о цвете фона и текста. Проходим по каждому параграфу внутри блока .invert, определяем contrast ratio и если он меньше 7 (таково требование WCAG) — делаем текст белым, а если больше 7, то оставляем как есть. UPD: переписал код для определения цвета фона не у родителя, а у самого элемента, для этого надо прописать параграфу в CSS background-color: inherit и переменной bg присваивать значение собственного цвета фона: bg = $(item).css('background-color'). UPD: итоговый вариант, позволяющий делать что угодно с элементами, имеющими недостаточную контрастность и без использования background-color: inherit. Источники: Lea Verou, contrast ratio. Формула подсчёта relative luminance: https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef. Формула подсчета 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; }Оригинал
Текст
Инверсия
Обычный текст без инлайновых стилей
Черный Текст
Коричневый Текст
Синий Текст
Желтый Текст
Оранжевый Текст
Ответ 2
Может быть так: $('p').each(function(){ var $this = $(this), wrap = $this.parent('div'), color = $(this).css('color'), bg = wrap.css('backgroundColor'); console.log(color + ' ' + bg); if(color === bg) { $this.css({'color':'#ffffff'}); } }); .orig { background-color: #fff; } .invert { background-color: #000; }Оригинал
Текст
Инверсия
либо так: $('p').each(function(){ var $this = $(this), wrap = $this.closest('.invert'), color = $(this).css('color'), bg = wrap.css('backgroundColor'); console.log(color + ' ' + bg); if(color === bg) { $this.css({'color':'#ffffff'}); } }); .orig { background-color: #fff; } .invert { background-color: #000; }Текст
Оригинал
Текст
Инверсия
Текст
Ответ 3
Может с фильтром invert? .orig { background-color: #fff; } .invert { background-color: #000; } .invert p { filter: invert(100%); }Оригинал
Текст
Инверсия
Текст
Ответ 4
Любопытно. Можно при изменении текстовой ноды (MutationObserver) проверять её цвет, сравнивать его с чёрным и, если слишком тёмный, делать его светлее. При сохранении, обходить дерево (TreeWalker), ставить тексту принудительно цвет.Ответ 5
Если хотите сделать быстро и просто, то сделайте на нативном CSS с помощью свойства mix-blend-mode: p { color: #fff !important;; mix-blend-mode: difference; }Оригинал
Текст
Инверсия
Текст
mix-blend-mode
Текст
Комментариев нет:
Отправить комментарий