Вы можете встретить компонент пользовательского интерфейса, у которого есть текст над изображением. В некоторых случаях в зависимости от используемого изображения текст будет трудно прочитать. У этой проблемы есть несколько различных решений, таких как добавление градиента или затемнение изображения, наложение тени на текст и другие. Этот прием будет полезен не только frontend и веб-разработчикам, но и ui/ux-дизайнерам. Написать эту статью меня вдохновил твит от Эдди Османи, работающего над Google Chrome.
Здесь я рассмотрю различные подходы и решения этой проблемы, а также то, как передать пользовательский интерфейс фронтенд разработчику таким образом, чтобы гарантировать, что UI реализован в соответствии с макетом дизайна, поскольку некоторые детали в CSS можно легко упустить.
Вступление
Давайте посмотрим на нашу задачу. При разработке компонента с текстом над изображением мы должны позаботиться о том, чтобы текст было легко прочитать.
Обратите внимание, что версия без наложения градиента читается плохо. Для пользователя это нехорошо. Чтобы решить эту проблему, нам нужно добавить слой под текстом так, чтобы текст читался легко. Добавление этого слоя может быть сложной задачей, и я видел многих, кто внедряет это решение, не принимая во внимание доступность.
Обзор возможных решений
Давайте посмотрим на возможные решения.
Есть решения, требующие большего внимания, — это градиентные решения. Почему? Потому что добавить слой градиента — это очень просто, но текст не будет удобным.
Решения
Наложение градиента
Вообще говоря, наложение градиента — это наиболее распространённое решение, позволяющее сделать текст на изображении более чётким. Учитывая это, я остановлюсь на нём немного подробнее.
При реализации наложения градиента у нас есть два варианта:
Использовать отдельный элемент для градиента (псевдоэлемент или пустой
<div>
)Применить градиент как фоновое изображение.
У каждого из вышеперечисленных есть свои плюсы и минусы, давайте рассмотрим их.
Элемент содержимого позиционируется абсолютно, его фоновым изображением служит градиент. Это означает, что размер градиента равен высоте элемента.
.card__content {
position: absolute;
/* other styles (left, top, right, and padding) */
background: linear-gradient(to top, rgba(0, 0, 0, 0.85), transparent);
}
На первый взгляд может показаться, что градиент хорошо работает. Это не так. Я протестировал тот же градиент с большим количеством изображений, и вот результат.
Обратите внимание, что контраст между белым текстом и изображениями не всегда чёткий. Некоторые люди прочитают текст, но использовать такой градиент — огромная ошибка.
Причина в том, что градиент должен покрывать больше пространства по вертикали, поэтому должен быть выше. Если градиент равен размеру контента, он будет работать не во всех случаях. Чтобы решить эту проблему, мы можем использовать min-height, как показано ниже:
min-height к элементу .card__content.
Flexbox для перемещения содержимого вниз.
.card__content {
position: absolute;
/* other styles (left, top, right, and padding) */
display: flex;
flex-direction: column;
justify-content: flex-end;
background: linear-gradient(to top, rgba(0, 0, 0, 0.85), transparent);
}
Другое решение — большой padding-top, с ним не нужны min-height и flexbox.
.card__content {
position: absolute;
padding-top: 60px;
background: linear-gradient(to top, rgba(0, 0, 0, 0.85), transparent);
}
Обратите внимание на разницу между левой и правой карточками. Градиент больше по высоте.
Выглядит хорошо. Можем ли мы сделать лучше? Определённо да!
Смягчение градиента
Присмотревшись, вы заметите, где заканчивается градиент, то есть у него резкая граница.
Чтобы сделать лучше, мы можем применить смягчение градиента. Таким образом градиент будет выглядеть естественнее, и вы не заметите резких краёв в его конце.
Чтобы достичь плавности, в CSS нам нужно несколько границ перехода градиента, но на момент написания этой статьи в CSS нет нативного способа сделать несколько границ. Хорошая новость заключается в том, что рабочая группа CSS обсуждает возможность реализации нативного смягчения градиентов на CSS, но остаётся неясным, когда эту возможность внедрят.
К счастью, г-н Андреас Ларсен создал удобные плагины PostCSS и Sketch, которые помогают преобразовывать резкий градиент в более мягкий.
Вот градиент CSS для примера выше:
.card__content {
background-image: linear-gradient(
0deg,
hsla(0, 0%, 35.29%, 0) 0%,
hsla(0, 0%, 34.53%, 0.034375) 16.36%,
hsla(0, 0%, 32.42%, 0.125) 33.34%,
hsla(0, 0%, 29.18%, 0.253125) 50.1%,
hsla(0, 0%, 24.96%, 0.4) 65.75%,
hsla(0, 0%, 19.85%, 0.546875) 79.43%,
hsla(0, 0%, 13.95%, 0.675) 90.28%,
hsla(0, 0%, 7.32%, 0.765625) 97.43%,
hsla(0, 0%, 0%, 0.8) 100%
);
}
Сравните карточки со смягчением градиента и без него.
Горизонтальные градиенты
Работа с текстом поверх изображения не может касаться только вертикального градиента, можно работать и с горизонтальным.
Вот CSS градиента для раздела выше. Чтобы добиться смягчения градиента, я использовал упомянутый ранее инструмент.
background: linear-gradient(
to right,
hsl(0, 0%, 0%) 0%,
hsla(0, 0%, 0%, 0.964) 7.4%,
hsla(0, 0%, 0%, 0.918) 15.3%,
hsla(0, 0%, 0%, 0.862) 23.4%,
hsla(0, 0%, 0%, 0.799) 31.6%,
hsla(0, 0%, 0%, 0.73) 39.9%,
hsla(0, 0%, 0%, 0.655) 48.2%,
hsla(0, 0%, 0%, 0.577) 56.2%,
hsla(0, 0%, 0%, 0.497) 64%,
hsla(0, 0%, 0%, 0.417) 71.3%,
hsla(0, 0%, 0%, 0.337) 78.1%,
hsla(0, 0%, 0%, 0.259) 84.2%,
hsla(0, 0%, 0%, 0.186) 89.6%,
hsla(0, 0%, 0%, 0.117) 94.1%,
hsla(0, 0%, 0%, 0.054) 97.6%,
hsla(0, 0%, 0%, 0) 100%
);
Смешивание сплошного цвета и градиента
Я узнал об этом приёме на сайте Netflix. На домашней странице для незарегистрированного пользователя есть заголовок с большим фоновым изображением.
Мне это нравится, но он скрывает многие детали изображения. Используйте этот приём только в том случае, если изображение должно быть декоративным (не приносит реальных преимуществ конечному пользователю).
<div class="hero">
<img src="cover.jpg" alt="" />
<div class="hero__content">
<h2>Unlimited movies, TV shows, and more.</h2>
<p>Watch anywhere. Cancel anytime.</p>
</div>
</div>
.hero:after {
content: "";
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
background-image: linear-gradient(
to top,
rgba(0, 0, 0, 0.8),
rgba(0, 0, 0, 0) 60%,
rgba(0, 0, 0, 0.8) 100%
);
}
Вот наглядное объяснение того, как работает этот паттерн.
Наложение градиента и тень текста
Есть небольшая полезная деталь, которая может сделать текст поверх изображений ещё лучше. Всё дело в добавлении к тексту лёгкой тени. Даже когда заметить её нелегко, она может быть очень полезной, если изображение не загружается. Посмотрим на такой пример.
.whatever-text {
text-shadow: 0 2px 3px rgba(0, 0, 0, 0.3);
}
Наложение градиента, тень текста и непрозрачность
Это закономерность, которую я заметил в проигрывателе видео на Facebook. Мне понравилось, что они использовали несколько техник, чтобы сделать текст и другие элементы пользовательского интерфейса чёткими. При работе с проигрывателем очень важно гарантировать, что элементы поверх него заметны.
.player__icon {
opacity: 0.9;
}
.player__time {
color: #fff;
text-shadow: 0 0 5px #fff;
}
Что в этом нового? Значки и проигрыватель имеют непрозрачность в 90 %. Это помогает им смешаться с фоном под ними. Создаётся ощущение, что элементы управления вмешаны в изображение.
Кроме того, белая тень у белого текста — эффективный способ сделать текст чётче. Вы хотите доказательства того, что всё вышесказанное будет работать, даже если фон полностью белый? Ну, вот.
Youtube делает то же самое со своими видео.
Вот что мне понравилось в подходе Youtube:
Тёмная рамка для каждого значка, чтобы он лучше выделялся.
Чёрная тень вместо белой для времени видео.
Радиальный градиент
Интересное решение, о котором я узнал от Netflix, — радиальный градиент. Вот как он работает:
Установите основной цвет заднего фона.
Поместите изображение в верхний правый угол с шириной 75 %.
Наложение соответствует размеру и положению изображения.
.hero {
background-color: #000;
min-height: 300px;
}
.hero__image {
position: absolute;
right: 0;
top: 0;
width: 75%;
height: 100%;
object-fit: cover;
}
.hero:after {
content: "";
position: absolute;
right: 0;
top: 0;
width: 75%;
height: 100%;
background: radial-gradient(
ellipse 100% 100% at right center,
transparent 80%,
#000
);
}
Тем не менее команда Netflix в качестве оверлея использовала изображение .png. Конкретной причины этого я не знаю. Может быть, дело в проблеме с кросс-браузерностью или что-то в этом роде: я не тестировал решение с радиальным градиентом.
Выбор удобного пользователю цвета наложения
Я покажу отличный инструмент, который помогает выбрать правильную непрозрачность наложения в зависимости от изображения. Посмотрите его на Codepen. Интересная задача — сделать градиент удобным.
В общем, если вы гарантируете, что наложение градиента правильно заполняет текст и имеет подходящий цветовой контраст, всё готово.
Тестирование
Решение нельзя считать хорошим, пока оно не протестировано, верно? Один из способов, который я использую для проверки наложения градиента, — добавление белого фона ниже градиента. Если текст после этого читаемый, то градиент будет работать с любым изображением, а если нет, вам нужно настроить и улучшить его.
В приведённом выше примере я выбрал сплошной цвет под заголовком, а коэффициент контрастности составляет 4,74, такой коэффициент считается хорошим.
Работа с Firefox DevTools
Спасибо Гийсу Вейфейкену: он рассказал мне, что Firefox может тестировать цветовой контраст на градиентах. Это отличная функция.
Если хотите прокачать себя в веб-разработке, освоить специальность frontend-разработчика или стать настоящим Fullstack-универсалом — приходите учиться, а наши опытные менторы и внимательные кураторы помогут вам дойти до финала.
Узнайте, как прокачаться в других специальностях или освоить их с нуля:
Другие профессии и курсы
ПРОФЕССИИ
КУРСЫ
jt3k
Эдди Османи пишется не так https://github.com/web-standards-ru/dictionary/blob/master/names.md#osmani-addy
Исправьте пожалуйста