Как стать автором
Обновить
89.84
Skillfactory
Онлайн-школа IT-профессий

CSS сolor-сontrast(): пошаговое руководство

Уровень сложностиСредний
Время на прочтение15 мин
Количество просмотров5.6K
Автор оригинала: Aman Mandal


Если вы испытывали раздражение из-за невозможности легко перемещаться по сайту, с высокой вероятностью вы столкнулись с недоступностью в том или ином виде. Недоступность и неприятные впечатления от использования схожи. Если вам сложно прочитать мелкий шрифт, то человеку с нарушениями зрения, возможно, вообще не прочитает его.


Функция color-contrast() используется для удобства чтения, придания необходимого контраста между текстом и фоном на веб-странице. Это особенно важно для людей с нарушениями зрения, которым трудно прочитать текст с низким контрастом.


color-contrast() — экспериментальная функция, с помощью которой можно выбрать наиболее контрастный цвет. Она принимает три аргумента: основной цвет, список цветов и (опционально) целевую степень контрастности. Эта функция сравнивает основной цвет со списком цветов и возвращает самый контрастный цвет.


В этом руководстве я расскажу о том, как свойство CSS сolor-contrast() помогает разрабатывать доступные пользовательские интерфейсы.


А если вы дизайнер и создаете сайт с подходящим размером шрифта, вы также создадите приятное впечатление и сделаете сайт доступнее, в том числе для людей с нарушениями зрения. Свойство color-contrast() поможет пользователям с легкостью получить доступ к информации и услугам и использовать их.


Учитывая нужды людей с нарушениями зрения и инвалидностью в процессе разработки дизайна, можно создавать понятные всем сайты, по которым легко перемещаться. Для этого пишите четкий и лаконичный текст, указывайте альтернативный текст для изображений и применяйте понятные, структурированные макеты.


Что такое доступность?


«Доступность» — это подход к веб-дизайну, ориентированный на всех пользователей, независимо от их языка, местоположения, возможностей и устройств просмотра интернета. Создание доступного дизайна — это не просто привлечение внимания к людям с инвалидностью, но и удобство для всех пользователей. Доступность — ключ к приятным впечатлениям для всех пользователей, включая людей с физическими ограничениями.


Согласно опросу Всемирной организации здравоохранения, около 16% людей в мире имеют ту или иную форму инвалидности. Скорее всего, из-за старения населения это число будет расти. а значит, большое количество пользователей интернета при работе с традиционными сайтами столкнутся со сложностями.


Доступные сайты увеличивают потенциальную клиентскую базу и работают на репутацию бренда.


Один из способов достичь доступности — следовать Руководству по обеспечению доступности веб-контента (WCAG), разработанному Консорциумом Всемирной паутины (W3C). В этом руководстве содержатся конкретные рекомендации для создания доступного цифрового контента, в том числе и рекомендации по контрасту текста.


Рекомендуемая WCAG минимальная степень контрастности между текстом и фоном составляет 4,5:1. Так текст легко может прочитать любой человек, в том числе и имеющий нарушения зрения.


Почему доступность в интернете важна?


Раньше многие дизайнеры думали, что доступность неплохо бы учитывать при создании дизайна, но сейчас она больше не считается необязательной, а для многих организаций стала необходимостью. Согласно отчету организации WebAIM, на 96,8% домашних страниц не соответствуют WCAG2.


Но прописывать альтернативный текст для картинок или label для элемента ввода данных — это одно, а использовать цветовые палитры принудительно — совершенно другое. Поэтому давайте посмотрим, как здесь поможет color-contrast().



Обзор CSS-функции color-contrast()


На момент написания материала color-contrast() — экспериментальная функция CSS Color Module Level 5. Сейчас она доступна только в технологическом превью Safari. Включить ее можно в меню Develop и Experimental Features.



Источник


Примеры CodePen могут не работать, если вы работаете не в технологическом превью Safari.

Основная цель данной функции — выбор лучшего контрастного цвета из списка при сравнении с основным цветом.



Синтаксис:


color: color-contrast(#505050 и #fff, #000)

В этой статье первый параметр называется основным цветом, а второй — списком цветов. Функция color-contrast() принимает любые поддерживаемые браузером CSS-форматы цветов, а именно:


  • HEX (#ff3300);
  • RGB (rgb(255, 0, 0));
  • RGBA (rgba(25, 32, 65, 0.86));
  • HSL (hsl(120, 100%, 125%)).

Третий, опциональный параметр — целевой контраст, о нем поговорим позже.


Начало работы с color-contrast()


Выступление Рэйчела Эндрю на AxeCon 2022 «Новый CSS с учетом доступности» раскрыло большое влияние CSS на мир доступного дизайна. Рэйчел продемонстрировал новую функцию, когда задавал цвета текста, основываясь на цветах фона. Здесь находится пример работы color-contrast() на CodePen.


Давайте взглянем на эту функцию. Зададим определенные цвета текста и фона:


:root {
        --primary-background: #1e1e1e;
      }

      .content {
        background-color: var(--primary-background);

        color: color-contrast(var(--primary-background) vs #fff, #000);
      }

Задано пользовательское свойство --primary-background — оттенок темно-серого, #1e1e1e. Затем то же свойство используется для основного цвета в функции color-contrast(). Это свойство сравнивается с каждым цветом в списке для нахождения наибольшего контрастирующего значения.


Попробуем поэкспериментировать. Можно связать функции color-contrast(), просто применяя результат основного цвета из другой функции. Звучит сложно, но давайте возьмем из предыдущего примера только .content и попытаемся связать функции!


:root {
        --primary-background: #5e5c5c;
        --primary-color: color-contrast(
          var(--primary-background) vs #fff,
          #000
        );
      }

      .content {
        background-color: var(--primary-background);

  color: var(--primary-color);
      }

      .content > p {
        color: color-contrast(var(--primary-color) vs #fff, #000);
      } 

В этом коде задано пользовательское свойство --primary-background. То же пользовательское свойство используется как основной цвет в функции color-contrast(). Затем оно сравнивается с элементами в списке цветов, к примеру, с белым и черным, и сохраняется в пользовательской переменной --primary-color. После в классе .content цвет фона и цвет используются как переменные, но здесь есть кое-что интересное!


В классе содержимого меняем цвет текста всех параграфов (элементов p), связывая функции. Используем --primary-color, то есть цвет, полученный с помощью color-contrast(), который был задан в root как основной. Он сравнивается с элементами в списке цветов.


Вот полный пример.


HTML:


<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Blog</title>
  </head>
  <body>
    <div class="container">
      <h2>CSS color-contrast() demo</h2>

      <div class="content">
        <p>
          A simple paragraph example for the css color contrast function! Lorem ipsum, dolor sit amet consectetur adipisicing elit. Minima molestias
        ullam voluptas et obcaecati sapiente veritatis fugit exercitationem
          dolorem illo quidem sit soluta, tempore
        </p>
      </div>
    </div>
</body>
</html>

CSS:


:root {
        --primary-background: #505050;
        --primary-color: color-contrast(
          var(--primary-background) vs #fff,
          #000
        );
        /* --primary-color: white; */
      }

      body {
        margin: 0;
        padding: 0;
      }

      .container {
        width: 450px;
        margin: 0 auto;
        margin-top: 50px;
        border: 1px solid gray;
        font-family: "Franklin Gothic Medium", "Arial Narrow", Arial, sans-serif;
      }

      .container > h2 {
        padding-left: 20px;
        font-size: 2rem;
      }

      .content {
        background-color: var(--primary-background);
        color: var(--primary-color);
        padding: 20px;
      }

      .content > p {
        line-height: 1.4rem;
        font-size: 1.2rem;
        margin: 0;
        color: color-contrast(var(--primary-color) vs #fff, #000);
      }


Это пример применения color-contrast() для минимальной рекомендованной контрастности цвета текста согласно WCAG. Функция color-contrast() применяется для сравнения степени контрастности между цветом текста и цветом фона. Если степень контрастности не подходит, тексту присваивается новый класс. Такой подход помогает убедиться, что текст подходит всем пользователям, в том числе людям с нарушениями зрения.


С color-contrast(), можно автоматизировать проверку контрастности. Код выше — пример внедрения доступности. А псевдоэлемент ::selection поможет пойти еще дальше:


<div class="container">
      <h1>CSS Color-Contrast() ::Selection</h1>

      <article class="article article-top">
        <h2>Selenium Test Automation Cloud</h2>
        <p>
          A reliable, scalable, secure, and high performing test execution cloud
          that empowers development and testing teams to accelerate their
          release cycles. Test in parallel and cut down test execution by more
          than 10x.
        </p>
      </article>

      <article class="article article-bottom">
        <h2>Cypress Automation Testing</h2>
        <p>
          Run end-to-end tests on a blazing fast Cypress test execution cloud. A
          reliable, scalable, secure and high performing test execution platform
          built for scale. Test on 40+ different browser and browser versions
          including headless versions.
        </p>
      </article>
    </div>

    .content {
        --content-bg: #eef5ff;
        --content-color: color-contrast(var(--content-bg) vs #fff, #000);

        background: var(--content-bg);
        color: var(--content-color);
        padding: 0.5rem 1rem;
        border: 1px solid black;
        border-radius: 12px;
        margin-bottom: 12px;
      }

      .content:last-of-type {
        --content-bg: #4992af;
      }

      .content::selection {
        @supports (background: color-contrast(#000 vs #fff, #eee)) {
          background: color-contrast(var(--content-color) vs #8fc8de, #595959);
        }
      }

      :root {
        --body-base: #fbf8cc;
        --color-primary: #8fc8de;
        --scrollbar-bg: #222;
      }

      body::-webkit-scrollbar {
        width: 10px;
      }
      body {
        scrollbar-width: thin;
        scrollbar-color: var(--color-primary) var(--scrollbar-bg);
      }
      body::-webkit-scrollbar-track {
        background: var(--scrollbar-bg);
      }
      body::-webkit-scrollbar-thumb {
        background-color: var(--color-primary);
        border-radius: 6px;
        border: 3px solid var(--scrollbar-bg);
      }

      html,
      body {
        color: #000;
        font-family: "Lucida Sans", "Lucida Sans Regular", "Lucida Grande",
          "Lucida Sans Unicode", Geneva, Verdana, sans-serif;
        font-size: 100%;
        letter-spacing: 0.25px;
        line-height: 1.75;
        margin: 0;
        padding: 0;
      }

      body {
        background: rgb(194, 226, 228);
        block-size: 100%;
        display: grid;
        min-block-size: 100vh;
        place-items: center;
      }

      a {
        color: #c8553d;
        text-decoration: underline 1px dashed;
        text-underline-offset: min(5px, 1em);
      }

      a:focus {
        outline: 1px solid currentColor;
        outline-offset: 3px;
      }

      a:hover {
        color: #131313;
      }

      h1,
      h2 {
        font-family: "Gill Sans", "Gill Sans MT", Calibri, "Trebuchet MS",
          sans-serif;
        line-height: 1.25;
      }

      .container {
        inline-size: min(750px, 50vw);
      }



Выше color-contrast() используется с псевдоэлементом ::selection; color-contrast() сравнивает не только HEX-коды (#000000). Можно изменить предыдущий пример и использовать несколько разных форматов цветов одновременно:


:root {
        --content-bg: rgb(43, 23, 244);
        --content-color: color-contrast(
          var(--content-bg) vs #fff,
          hsl(0, 100%, 12%)
        );
      }

      .content {
        background-color: var(--content-bg);
        color: var(--content-color);
      }

      .content::selection {
        background: color-contrast(
          var(--article-color) vs hsl(0, 1%, 26%),
          white
        );
      }

При помощи функции color-contrast() можно легко одновременно использовать форматы HSL, RGBA, RGB и т. д., и это не приведет к ошибкам. Упрощается работа с контрастом.


сolor-contrast() с псевдоклассами


Мы уже использовали псевдоэлемент ::selection с функцией color-contrast(). Возможность динамического определения цветов впечатляет. Но цвет текста и фон после рендеринга не изменятся, они статичны.


Посмотрим теперь на кое-что любопытнее — на изменение контрастов интерактивных элементов и их псевдоклассов.


При работе с веб-сайтом иногда нужна только клавиатура. Табуляция, например, может останавливаться на различных элементах, к примеру, кнопках, элементах ввода данных, ссылках, а также на изображениях, используемых в качестве ссылок и карточках. У каждого элемента должен быть соответствующий индикатор фокуса, но создать фокусирующие псевдоэлементы для всех элементов непросто. И здесь вам тоже может помочь color-contrast():


:root {
        --background-primary: #737272;
        --background-button: #1a73e8;
        --button-text-color: color-contrast(
          var(--background-button) vs #fff,
          #000
        );
        --button-hover: #13427e;
        --color-list: var(
          var(--background-button),
          var(--button-text-color),
          rgb(158, 113, 113),
          rgb(93, 88, 88)
        );
      }

      .rounded-btn {
        background: var(--background-button);
        color: var(--button-text-color);
      }

      .rounded-btn:hover {
        background-color: var(--button-hover);
      }

      .rounded-btn:focus {
        box-shadow: 2px 1px 23px 3px
          color-contrast(var(--background-primary) vs var(--color-list));
      }

Пользовательское свойство --background-button используется в качестве основного цвета в функции color-contrast() для выбора значения --button-text-color. При любом изменении --background-button также меняется --button-text-color, ведь они связаны. Затем мы задаем пользовательское свойство \--button-hover для псевдоэлемента :hover.


Перейдем к самому важному для доступности псевдоэлементу — :focus. В стиле :focus color-contrast() использует \--background-primary как основной цвет. Оно сравнивается с текущим стилем кнопки, что позволяет создать контекстно-зависимые стили фокуса.


Разберем этот пример:


<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Blog</title>
  </head>
  <body>
    <h1>CSS Color-Contrast() :hover & :focus pseudo-classes</h1>
    <div class="container">
      <h3>Selenium Test Automation Cloud</h3>
      <p>
        A reliable, scalable, secure, and high performing test execution cloud
        that empowers development and testing teams to accelerate their release
        cycles. Test in parallel and cut down test execution by more than 10x.
        browser.
      </p>

      <button class="btn">Test Online</button>
    </div>
  </body>
</html>

:root {
        --body-base: #131e25;
        --color-primary: rgba(255, 124, 0, 1);
        --scrollbar-bg: #222;
      }
      html,
      body {
        color: #fff;
        font-family: "Barlow", sans-serif;
        font-size: 100%;
        letter-spacing: 0.25px;
        line-height: 1.75;
        margin: 0;
        padding: 0;
      }

      .container {
        width: 500px;
        border: 1px solid lightgray;
        padding: 20px;
        border-radius: 12px;
        background-color: #2d043a;
      }

      .container > h3 {
        color: rgb(181, 210, 212);
        font-size: 1.5rem;
      }

      .btn {
        --btn-base: #76d8ff;
        --btn-color: color-contrast(var(--btn-base) vs #fff, #000);
        --btn-gradient: linear-gradient(
          180deg,
          rgb(94, 150, 223) 0%,
          rgb(27, 83, 87) 100%
        );

        background: var(--btn-base);
        background: var(--btn-gradient);
        border: 5px solid var(--body-base);
        border-radius: 12px;
        color: var(--btn-color);
        padding: 1em 2em;
        font-size: 14px;
      }

      .btn:hover {
        --btn-base: #0079b1;
        --btn-gradient: linear-gradient(
          180deg,
          rgb(38, 88, 196) 0%,
          rgb(2, 53, 112) 100%
        );

        background: var(--btn-base);
        background: var(--btn-gradient);
        cursor: pointer;
      }

      .btn:focus {
        box-shadow: 0 0 1px 3px
          color-contrast(var(--body-base) vs var(--btn-base), #bbb);
      }
      .btn:active {
        opacity: 0.95;
        transform: scale(0.98);
        transform-origin: center;
      }

      body {
        background: #96a1a8;
        block-size: 100%;
        display: grid;
        min-block-size: 100vh;
        place-items: center;
      }

      h1,
      h2 {
        font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
        line-height: 1.25;
      }

      section {
        inline-size: min(750px, 50vw);
      }



В презентации «Cовременные усовершенствования CSS для улучшения доступности» Стефани Эклз подробно и понятно рассказывает о различных усовершенствованиях CSS для повышения доступности. В ее докладе говорится о color-contrast(), cемантическом HTML и адаптивном дизайне. Эти понятия проиллюстрированы наглядными примерами.


Целевая степень контрастности


В начале этой статьи я упомянул об опциональном третьем параметре color-contrast(). Ознакомимся с ним поподробнее.



Этот параметр определяет целевую степень контрастности: AA, AA-large, AAA? AAA-large или число. Когда задается целевая контрастность, выбирается первый цвет из списка цветов, соответствующий целевой контрастности или превосходящий ее:


<body>
    <section class="container">
      <h1>Target Contrast Ratio</h1>
      <p>
        CSS color-contrast() function is having a third parameter called as
        <span style="color: red">Target contrast ratio</span> . This feature is
        only available in Safari Browser right now, so if you are using any
        other browser this won't work!
      </p>

      <div class="sample-block">
        <p>Target Ratio: <span>AA (4.5)</span></p>
      </div>

      <form>
        <label>
          Ratio Keywords
          <select id="ratios">
            <option value="AA (4.5)" selected>AA (4.5)</option>
            <option value="AA-Large (3)">AA-Large (3)</option>
            <option value="AAA (7)">AAA (7)</option>
            <option value="AAA-Large (4.5)">AAA-Large (4.5)</option>
          </select></label
        >

        <label>
          Custom Ratio
          <input
            id="slider"
            type="range"
            min="0"
            max="20"
            value="4.5"
            step="0.1"
          />
        </label>
      </form>
    </section>

    <style>

body {
        --contrast-target: AA;
      }

      .sample-block {
        --color-set: #001908, #005f73, #b5e62e, #bff5e3, #544107, #ee9b00;
        --base: color-contrast(
          var(--body-base) vs var(--color-set) to var(--contrast-target)
        );

        background: var(--base);
        display: grid;
        padding: 0.75em 1em;
        place-items: center;
      }

      .sample-block {
        background-color: whitesmoke;
        border-radius: 20px;
        margin-bottom: 30px;
      }

      .sample-block > p {
        color: black;
      }

      /* .sample-block > p {
        color: color-contrast(
          var(--base) vs var(--color-set),
          #fff to AA-Large
        );
      } */

      body::-webkit-scrollbar {
        display: none;
      }

      html,
      body {
        color: #fff;
        font-family: "Barlow", sans-serif;
        font-size: 100%;
        letter-spacing: 0.25px;
        line-height: 1.75;
        margin: 0;
        padding: 0;
      }

      body {
        block-size: 100%;
        display: grid;
        min-block-size: 100vh;
        place-items: center;
      }

      .container {
        background: rgb(24, 40, 52);
        padding: 20px;
        border-radius: 20px;
      }

      .container > h1 {
        text-align: center;
        margin-bottom: 30px;
        padding-bottom: 30px;
      }

      a {
        color: #e9d8a6;
        text-decoration: underline 1px dashed;
        text-underline-offset: min(5px, 1em);
      }

      a:hover {
        color: #ffe8d6;
      }

      a:focus {
        outline: 1px solid currentColor;
        outline-offset: 3px;
      }

      h1,
      h2 {
        line-height: 1.25;
      }

      section {
        inline-size: min(750px, 50vw);
      }

      form {
        display: grid;
        grid-gap: 2rem;
        grid-template-columns: 1fr 1fr;
        padding-block-end: 1rem;
      }

      label {
        display: grid;
        font-size: 1.2rem;
        font-weight: 600;
      }

      select,
      input {
        display: block;
      }

document
        .querySelector("#ratios")
        .addEventListener("change", (e) => {
          document.body.style.setProperty("--contrast-target", e.target.value);
          document.querySelector(".sample-block span").innerHTML =
            e.target.value;
        });

      document.querySelector("#slider").addEventListener("input", (e) => {
        document.body.style.setProperty("--contrast-target", e.target.value);
        document.querySelector(".sample-block span").innerHTML = e.target.value;
      });


При определении целевого соотношения контраста функция color-contrast() вернет самое первое значение из списка цветов, которое соответствует целевой контрастности. Однако, если ни один цвет в списке не соответствует целевой контрастности, происходит магия:


h1{
        color: color-contrast(#000 vs #111, #222 to AA);
      }

В этом коде основной цвет — black(#000), а список цветов состоит из двух оттенков темно-серого, но ни одно значение не соответствует целевому контрасту AA(4.5). Что же произойдет?


CSS заполнит пробелы, если в списке цветов нет значения, соответствующего целевому контрасту — черному или белому. В этом случае color-contrast() может позволить дизайнерам обеспечить определенный уровень доступности:


.background-primary {
        --background: #000;
        --color-list: #111, #222;
      }

      .background-primary {
        background: var(--background);
        color: color-contrast(var(--background) vs var(--color-list));
      }
      .background-primary.with-target-ratio {
        color: color-contrast(var(--background) vs var(--color-list) to AA);
      }

Попробуем понять, что такое целевая степень контрастности.


Основной класс .background-primary не использует целевую контрастность, поэтому цвет становится #222 — самым контрастным из списка цветов относительно основного, черного, цвета. Но доступен ли здесь #222? Очевидно нет!


А теперь сравним это с сочетанием классов .background-primary и .with-target-ratio, при котором целевая контрастность определена. Несмотря на использование того же основного цвета и списка цветов, результат сильно отличается. Если ни один из цветов в списке не соответствует целевой контрастности AA, функция выбирает необходимый цвет. В данном случае — белый!


Неизбежные минусы color-contrast()


Как уже говорилось, функция color-contrast() является экспериментальная, так что на момент написания материала есть ряд проблем. Давайте разберемся, как их решать!


  • Визуальные контрасты и цвета — это не одно и то же

При работе с color-contrast() происходит простое сравнение цвета текста и цвета фона. Да, именно так. Функция не учитывает другие свойства или стили, влияющие на визуальные контрасты, например размер и насыщенность шрифта, прозрачность и т. п.


Это значит, что цветовой контраст может быть правильным, но из-за других стилей и свойств контент все равно будет недоступен. К примеру, если у веб-сайта белый фон и черный текст, цветовой контраст технически правилен. Однако если шрифт очень мелкий, то пользователям с нарушениями зрения сложно прочитать текст. Аналогично, если текст чересчур прозрачен, его сложно прочитать всем пользователям. В обоих случаях, несмотря на технически правильную цветовую контрастность, текст окажется недоступен посетителям из-за проблем с типографикой.


  • Наивысшая контрастность — не гарантия доступности

Как упоминалось ранее, color-contrast() может контролировать цвета и цветовые темы, но все же есть ограничения, которые обойти не удастся. В случае когда функция сравнивает основной цвет и цвета из списка, а третий параметр — целевая степень контрастности — не задан, функция просто выберет самый контрастирующий цвет в списке.


Одно то, что два цвета — основной и цвет, выбранный из списка — контрастируют друг с другом, не значит, что доступность достигнута.


В коде выше фоновый цвет — черный. Он сравнивается с двумя оттенками темно-серого — #1e1e1e и #222; color-contrast() выберет #222: он самый контрастный, но доступный ли он? Нет. Но нет и другого выбора, ведь третий параметр не задан.


  • Градиенты не поддерживаются

На момент написания материала функция color-contrast() не поддерживает градиенты. Это логично. Представьте, что фоновый цвет — это градиент от зеленого к желтому. Какой тогда будет основной цвет? И как выбрать цвета для списка цветов?


Однако ниже находится пример на codepen, созданный Мишель Баркер. Она экспериментирует с использованием color-mix() и color-contrast() для поддержки градиентов.


Часто задаваемые вопросы (FAQ)


Что такое цветовой контраст AA и AAA?


Уровень AA требует минимальной степени контрастности 4,5:1 для обычного текста и 3:1 для текста большего размера. Кроме того, для компонентов графического интерфейса требуется коэффициент контрастности не менее 3:1. Уровень AAA требует степени контрастности по крайней мере 7:1 для обычного текста и 4,5:1 для текста большего размера.




Теги:
Хабы:
Рейтинг0
Комментарии3

Публикации

Информация

Сайт
www.skillfactory.ru
Дата регистрации
Дата основания
Численность
501–1 000 человек
Местоположение
Россия
Представитель
Skillfactory School