Frontender Magazine

Сила цветовой CSS-функции rgba()

Одна из наиболее интересных мне вещей в CSS — новая функция color-mod. Она позволит нам манипулировать цветами прямо в браузере. Например, при наведении на кнопку мы сможем изменить её цвет примерно так — color: color(black darkness(50%));, не используя препроцессоры вроде Sass.

Но пока поддержка таких CSS-функций не реализована, мы можем временно использовать PostCSS для их компиляции в обычные цвета. Или мы можем поэкспериментировать и исследовать силу функции rgba(), чтобы менять цвета на лету! Давайте посмотрим, как её можно использовать.

Как это работает

Как это работает. Часть 1.

Когда в графическом редакторе мы помещаем чёрный и белый блоки над большим синим блоком (как в примере), то в результате получаем, соответственно, более светлый или более тёмный синий цвет.

Это происходит потому, что при увеличении прозрачности цвета будут смешиваться на основе того, белый это или чёрный. Знаете, что произойдет, если изменить синий фон на зелёный? Верно!

Как это работает. Часть 2.

Как видите, при изменении цвета фона маленькие блоки стали выглядеть иначе: мы получили светлый и тёмный зелёный. Также мы можем изменить значение прозрачности, чтобы выбрать более светлый или тёмный оттенок. Давайте отработаем этот базовый навык, чтобы перейти к реальным примерам.

Применение концепции

Чтобы сохранить лаконичность предыдущего примера, поиграем с прозрачностью. В реальном дизайне нам может понадобиться альфа-значение rgba().

.header {
    background: rgba(0, 0, 0, 0.5); /* Чёрный с непрозрачностью 50% */
}

Здесь мы взяли background вместо opacity, потому что при использовании opacity будут затронуты все потомки, а нам это не нужно. Если мы используем альфа-канал для свойства background, мы обеспечиваем изменение только нужного элемента.

Примечание: в демо для скорости мы будем использовать rgba()-функции Sass. Например:

.elem {
    background: rgba(white, 0.5);
}

скомпилируется в:

.elem {
    background: rgba(255, 255, 255, 0.5);
}

Оформление шапки сайта

Первый вариант использования rgba() — это стилизация шапок веб-приложений. В Trello используются цвета фона с rgba() для дочерних элементов шапки (логотип, поле поиска, кнопки):

.search {
    background: rgba(255, 255, 255, 0.5); /* Белый с 50% альфа-каналом */
}

Devtools в Trello

Так мы получим возможность стилизовать шапку, меняя только её фон, и вместе с фоном будут изменены дочерние элементы.

В нашем примере мы можем сделать что-то похожее на шапку Trello и поиграть с фоном через панель разработки.

Шапка Trello

Обратите внимание, как отличается цвет фона потомков в двух шапках. Если мы хотим исследовать элемент и изменить фон родителя, мы можем очень просто настроить шапку.

Стилизация шапки

Посмотреть пример шапки можно на CodePen.

Шапка статьи

В этом примере использование rgba() будет полезно для:

Заголовок статьи с комментариями

.parent {
    background: #5aaf4c; /* фон родителя */
    box-shadow:
        inset 0 8px 0 0 rgba(255, 255, 255, 0.5),
        inset 0 -8px 0 0 rgba(255, 255, 255, 0.5); /* верхняя и нижняя рамки */
}

.contain {
    background: rgba(0, 0, 0, 0.1);
}

.category {
    background: rgba(255, 255, 255, 0.5);
}

Посмотреть пример шапки статьи можно на CodePen.

Кнопки

В темах для кнопок мы можем использовать rgba() для создания эффектов по наведению или фокусу через рамки и тени.

.button {
    background: #026aa7;
    box-shadow: inset 0 -4px 0 0 rgba(0, 0, 0, 0.2);
}

.button:hover {
    box-shadow: inset 0 -4px 0 0 rgba(0, 0, 0, 0.6), 0 0 8px 0 rgba(0, 0, 0, 0.5);
}

.button:focus {
    box-shadow: inset 0 3px 5px 0 rgba(0, 0, 0, 0.2);
}

Посмотреть пример кнопок можно на CodePen.

Градиенты

Другой полезный приём — это заливка фона сплошным цветом и добавление псевдоэлемента с rgba()-цветами для точек перехода цветов градиента.

Градиенты

.elem {
    background: green;
}

.elem:before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    background: linear-gradient(to right, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.7));
}

Это также даёт нам возможность анимировать градиенты изменением одного только цвета фона.

.elem {
    /* остальные стили */
    animation: bg 2s ease-out alternate infinite;
}

@keyframes bg
    to {
        background: green;
    }
}

Посмотреть пример градиентов можно на CodePen.

Вложенный элемент

Если у нас есть навигация списком в шапке, мы можем добавить для неё цвет фона с rgba(). Это сделает фон немного прозрачным, поэтому он будет смешиваться с фоном родителя.

Посмотреть пример вложенных элементов можно на CodePen.

То же может использоваться для создания динамических эффектов при наведении:

Посмотреть пример эффектов при наведении можно на CodePen.

Тёмные/светлые вариации цветовой схемы

Мы можем использовать эту идею для генерации различных оттенков определённой цветовой палитры через размещение псевдоэлемента над каждым цветным блоком с определённым значением rgba().

Посмотреть пример [цветовой палитры][21] можно на [CodePen][12].

Эффекты изображения

Чтобы сделать изображение темнее или светлее, мы можем использовать псевдоэлемент с rgba()-фоном.

Примеры эффектов

При использовании цветного фона мы можем создавать оттенки цвета. Кроме этого, мы можем использовать свойство mix-blend-mode, чтобы смешать фон с изображением для получения разных эффектов.

Важно проверить поддержку mix-blend-mode браузерами перед использованием:

.elem:before {
    background: rgba(0, 0, 0, 1);
    mix-blend-mode: color;
}

Если mix-blend-mode не поддерживается, изображение будет чёрным, и пользователь не сможет его увидеть. Лучше использовать этот эффект как прогрессивное улучшение, но не полагаться на него. В этом может помочь @support или Modernizr.

@supports (mix-blend-mode: color) {
    /* здесь будут ваши расширенные стили */
}

See the Pen Посмотреть пример изображений можно на CodePen.

Создание тем с CSS-переменными

Когда вы используете CSS-переменные (кастомные свойства) для родительских элементов, при изменении переменной меняются ещё и все дочерние элементы. Например:

:root {
    --brand-color: #026aa7;
}

/* Проверка поддержки CSS-переменных */
@supports (--color: red) {
    .elem {
        background: var(--brand-color);
    }
}

var colors = ["#026aa7", "#5aaf4c", "#00bcd4", "#af4c4c"];
var colorOptions = document.querySelectorAll(".option");
var colorLabels = document.querySelectorAll(".option + label");

for (var i = 0; i < colorOptions.length; i++) {

    /* Добавим слушателя события на каждую радио-кнопку */
    colorOptions[i].addEventListener('click', changeColor);

    /* Добавим значение каждой радио-кнопке из массива colors[] */
    colorOptions[i].value = colors[i];

    colorLabels[i].style.background = colors[i];
}

function changeColor(e) {
    /* Вызовем корневой элемент и установим значение определённого свойства. В нашем случае: --brand-color */
    document.documentElement.style.setProperty('--brand-color', e.target.value);
}

Сочетая CSS-переменные и rgba(), мы можем делать раскладки и цвета более динамичными без переопределения нового цвета для каждого элемента.

Посмотреть пример шапки с CSS-переменными можно на CodePen.

Что нужно принимать во внимание

Запасной цвет

Хотя глобальная поддержка CSS-цветов составляет примерно 97.39%, важно обеспечить запасной вариант для браузеров, в которых они не поддерживаются.

.elem {
    background: #fff;
    background: rgba(255, 255, 255, 0.5); /* браузеры без поддержки проигнорируют эту декларацию */
}

Проверка контрастности цвета

Мы должны обеспечивать между элементами контраст, соответствующий гайдлайнам доступности. Иногда при использовании rgba() может получиться цвет, который будет резать глаза, но вы можете использовать инструменты вроде проверки контраста от Lea Verou и определить, соответствуют ли цвета стандартам доступности.

Если вы заметили ошибку, вы всегда можете отредактировать статью, создать issue или просто написать об этом Антону Немцеву в skype ravencry.

Ahmad Shadeed
Автор:
Ahmad Shadeed
GitHub:
shadeed
Twitter:
@shadeed9
Сaйт:
https://ishadeed.com/
Альбина Токарчук
Переводчик:
Альбина Токарчук
GitHub:
endophasie
Twitter:
@endophasie