Изменение прозрачности фона кажется простой задачей. В CSS есть свойство opacity, которое управляет прозрачностью. Но этот подход работает не всегда. Если нужно разместить, например, текст поверх картинки, то использовать opacity — не лучшее решение.
Давайте разбираться, в чем проблема с вроде бы подходящим свойством CSS и как изменить прозрачность фона картинки, чтобы не испортить внешний вид других частей интерфейса.
К вам приходит проджект-менеджер и показывает новый дизайн страницы облачные серверы. В нем есть такие облака. Задача — сделать их полупрозрачными, а сверху добавить текст.
Источник: Shareicon
Первая мысль — сделать прозрачный фон CSS с помощью opacity. Выглядит так, будто это оптимальное решение для поставленной задачи. Набросаем простую разметку и посмотрим, что из этого получится.
HTML:
<div class="cloud">
<h1 class="title">Timeweb Cloud</h1>
</div>
CSS:
.cloud {
background-image: url(../images/cloud.png');
opacity: 1;
}
Свойство opacity принимает значение от 0 до 1, где 0 — полная прозрачность, а 1 — полная непрозрачность. Можно регулировать отображение с очень высокой точностью. Правда, на глаз разница заметна только при значительном изменении.
Сейчас результат выглядит так:
Выставили непрозрачность, выглядит нормально. Но в дизайне явно указано, что картинка должна быть полупрозрачной. Попробуем изменить значение opacity — например, 0.5 вместо 1. Облака должны стать немного светлее, насыщенность цветов ведь тоже изменится.
Вылезла проблема — вместе с фоновой картинкой начал исчезать текст с названием сервиса timeweb.cloud. В дизайне страницы такого нет. Более того, если сделать opacity: 0, то текст вообще исчезнет, как и облака под ним. Значит, это решение не подходит. Осталось разобраться, в чём причина такого поведения.
Объяснение простое. Проблема в том, что непрозрачность автоматически наследуется дочерними элементами. Нет свойства CSS, которое можно использовать для изменения непрозрачности только фонового изображения родителя. Возможно, оно появится когда-нибудь в будущем. Пока же нужны небольшие «костыли».
Мы поняли, что такое применение opacity для решения задачи не подходит. Для изменения прозрачности фонового изображения потребуется другой подход.
Cloud
Чтобы решить задачу, нужно поместить фоновое изображение в дочерний элемент родителя. Это гарантирует, что облака и текст будут каждый на своем слое. А непрозрачность каждого слоя можно контролировать по отдельности. В теории это выглядит как то, что нам нужно для достижения эффекта, который отрисовал дизайнер.
Разметка останется такой же, а стили перепишем:
.cloud {
position: relative;
height: 100vh;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.cloud::before {
content: "";
background-image: url('../images/cloud.png');
background-size: cover;
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
opacity: 0.3;
}
.title {
position: relative;
top: 80px;
right: 50px;
}
Элемент .cloud получил свойство position: relative. Это нужно для того, чтобы относительно родителя позиционировать потомков — .cloud::before и .title. Потомки выстраиваются внутри родители с помощью флекса.
Чтобы сделать псевдоэлемент того же размера, что и родитель, необходимо задать ему абсолютное позиционирование. Верхнее, правое, нижнее и левое значения должны быть равны нулю, чтобы :before не схлопывался. У него также должно быть установлено свойство content, иначе он не будет отображаться на странице.
Тексту нужно установить position: relative, чтобы он был поверх наложения и картинки. Если вы не установите position явно, надпись будет скрыта под абсолютно позиционированным псевдоэлементом. Это позволяет добиваться разных интересных эффектов в интерфейсе. Но мы сейчас решаем другую задачу.
Посмотрим на результат. Теперь облака полупрозрачные, а текст — непрозрачный, как того и требует дизайн страницы.
Вместо .cloud::before можно добавить обычный HTML-элемент для фонового изображения CSS — например, ещё один div. Принципиально это ничего не изменит. Но использование псевдоэлементов помогает упростить структуру HTML и не плодить в разметке лишние сущности.
А в чём же гибкость этого подхода?
Мало того, что вы можете сделать из непрозрачного фона прозрачный без влияния на другие части дизайна, так ещё и получаете возможность дополнительно управлять цветом наложения. Для этого достаточно немного изменить стили.
Свойства background-image и background-size перенесём в стили .cloud. В стили .cloud::before добавим background-color: rgba(0,0,0,0.25). Должно получиться так:
.cloud {
position: relative;
height: 100vh;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
background-image: url('../images/cloud.png');
background-size: cover;
}
.cloud::before {
content: "";
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
background-color: rgba(256,256,256,0.75)
}
RGBA — это три основных цвета (Red, Green, Blue) плюс альфа-канал, который помогает управлять прозрачностью. Значение rgba(256,256,256,0.75) говорит о том, что мы наложили белую плашку с непрозрачностью 25%. Вместо белого можно применить любой другой цвет и получить интересный эффект наложения:
Какой способ выбрать — решайте сами. Если с цветами играть не придётся, то можно обойтись первым вариантом. Хотя кто знает, что в следующий раз придёт от дизайнера.
Подготовили для вас выгодные тарифы на облако
Как мы увидели, свойство opacity всё-таки пригодилось. Правда, использовать его «в лоб» для изменения прозрачности не получится. Выход простой — добавить псевдоэлемент, который решит проблему с наследованием.