Играем со шрифтами на главной странице

Играем со шрифтами на главной странице

Делаем красивый эффект на случайном фоне

Сегодня будет простой проект в сфере фронтенда. Сделаем три вещи, которые раньше не делали:

  1. Наложим два слова друг на друга так, чтобы они хорошо читались.
  2. Через стили добавим в документ новый текст. 
  3. Подключим специальный сервис, который будет давать нам красивые фоны для страницы. 

В итоге получится что-то вроде красивой шапки сайта:

Играем со шрифтами на главной странице

Создаём страницу

Для проекта нам понадобится самая простая HTML-страница, даже без JavaScript. Единственное, что на ней будет, — подключённый файл со стилями и пара блоков для текста. При этом если присмотреться к коду, то можно увидеть, что самого текста на странице нет. Все слова — это атрибут тега, а не его содержимое. С помощью хитрой команды мы в стилях возьмём текст оттуда и выведем его в нужное место на странице.

Если мы откроем эту страницу в браузере, то ничего не увидим, потому что между тегами нет никакого текста — а раз нет текста, то и браузер ничего не выведет и покажет белое окно.

<!DOCTYPE html>
<html lang="ru" >
<head>
  <meta charset="UTF-8">
  <title>Играем со шрифтами и фоном</title>

  <!-- добавляем файл со стилями -->
  <link rel="stylesheet" href="style.css">

</head>
<body>
  <!-- пример текста с заливкой и прозрачными границами -->
	<div class="wrapper">
		<span data-text="Журнал"></span>
		<span data-text="Код"></span>
	</div>
  
	<!-- и наоборот — текст без заливки, но с цветным контуром -->
	<div class="wrapper invert">
		<span data-text="Журнал"></span>
		<span data-text="Код"></span>
	</div>
</body>
</html>

Подключаем случайный фон

Особенность проекта в том, что при каждом обновлении страницы у неё случайным образом меняется фон. За это отвечает сервис Picsum.photos — когда он получает специальный запрос, то в ответ отдаёт случайную бесплатную картинку из фотостока Unsplash.

Самый простой способ получить картинку — указать в адресе её ширину и высоту, например так:

https://picsum.photos/1280/800

Когда сервер увидит такой адрес в запросе, он поймёт, что нам нужно отдать картинку 1280 пикселей по ширине и 800 по высоте. Сервер возьмёт из Unsplash случайное фото, сделает его нужного размера и отправит нам. И так будет каждый раз, когда мы будем обновлять страницу. 

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

/* Общие настройки для всей страниц */
body {
  /* делаем высоту страницы на весь экран */
  height: 100vh;
  /* то, что не влезло в границы — скрываем */
  overflow: hidden;
  /* подключаем случайный фон и добавляем затемнение по кругу */
  background: radial-gradient(farthest-corner, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.8)), url(https://picsum.photos/1280/800) center/cover;
  /* выравниваем всё по центру */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* убираем отступы */
  margin: 0;
}

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

Играем со шрифтами на главной странице

Выводим слова на экран

Сейчас наш текст хранится только в атрибутах тега span, и нам нужно его как-то оттуда извлечь и вывести на экран. Для этого в современном CSS используют команду content: attr(data-text), которая работает так:

  1. Она берёт название свойства тега из скобок и ищет его среди HTML-кода. Как только находит — возвращает значение этого свойства. В нашем случае она будет искать свойство data-text.
  2. Как только значение найдено, оно в виде текста возвращается в CSS, и к нему сразу применяются все стили, написанные в этом блоке. 
  3. Этот текст выводится на экран в том месте, где по логике HTML-страницы применяется этот стиль.

Ещё мы будем использовать псевдоэлементы ::before и ::after. Они называются псевдоэлементами потому, что ведут себя, с одной стороны, как настоящие элементы на странице, а с другой — они существуют только вместе со своим родительским элементом. 

Псевдоэлемент ::before создаётся и выполняется до того, как обработается родительский элемент, а ::after— сразу после родительского. Это нам пригодится для вывода и оформления текста — так мы сможем создавать обводку слов как бы в отдельном виртуальном слое и при этом управлять им как настоящим слоем.

/* общий класс для текста */
.wrapper {
  /* задаём размеры текста, высоту и ширину */
  font-size: 17vmin;
  height: 2em;
  width: 100%;
  /* размещаем текст по центру блока */
  display: flex;
  align-items: center;
  justify-content: center;
  /* добавляем прозрачность для всех элементов на странице */
  mix-blend-mode: screen;
}

/* стиль для тега span, который будет лежать внутри стиля wrapper */
.wrapper span {
  /* цвет первого слова текста */
  --color: #ffba11;
  /* устанавливаем вид шрифта, его начертание и жирность */
  font-family: Impact, "Anton", Haettenschweiler, "Arial Narrow Bold", sans-serif;
  font-weight: 700;
  font-style: italic;
  /* создаём новый блок, в котором будет текст */
  display: block;
  /* включаем абслютное позиционирование элементов */
  position: absolute;
  /* используем цвет из переменной */
  color: var(--color);
}

/* общие настройки псевдоклассов для тега span */
.wrapper span::before, .wrapper span::after {
  /* создаём в стиле новый текст */
  content: attr(data-text);
  /* делаем для него новый блок */
  display: block;
  /* включаем для него относительное позиционирование */
  position: relative;
}

/* этот псевдокласс создаёт прозрачную обводку для каждого слова */
.wrapper span::before {
  position: absolute;
  /* добавляем прозрачный контур к этому слову */
  -webkit-text-stroke: 0.1em black;
}
Играем со шрифтами на главной странице

Отделяем слова друг от друга

Видно, что на странице появился текст с прозрачной обводкой, но все слова одного цвета и закрывают друг друга. Нам нужно их разнести в стороны, чтобы было удобно читать, а также поменять цвет второго слова. Используем для этого CSS-свойства :first-child и :last-child — они отвечают за работу с первым и последним элементом, которые относятся к одному тегу.

Так как слова у нас хранятся в свойстве тега span, то и применять эти свойства будем к нему:

/* обрабатываем первое слово */
.wrapper span:first-child {
  /* сдвигаем его чуть выше и левее, чтобы он оказался не по центру */
  transform: translate(-0.255em, -0.25em);
}

/* обрабатываем второе слово */
.wrapper span:last-child {
  /* цвет второго слова */
  --color: #b6acff;
  /* сдвигаем второе слово вправо и вниз */
  transform: translate(0.255em, 0.25em);
}
Играем со шрифтами на главной странице

Добавляем второй способ оформления

У нас получилось два одинаковых оформления, потому что мы до сих пор не прописали стиль для класса .wrapper.invert, который мы использовали на нашей странице. 

Так как у нас в описании стиля для каждого блока стоит mix-blend-mode: screen, то это значит, что прозрачность работает так:

Чем темнее цвет, тем он прозрачнее. Белый полностью непрозрачный, а чёрный — прозрачный.

Это значит, что нам достаточно сделать второй блок слов чёрного цвета, чтобы они стали полностью прозрачными. А чтобы можно было их прочитать — добавим к ним цветную обводку:

/* делаем прозрачными слова */
.wrapper.invert span {
  /* используем для этого чёрный цвет */
  color: black;
}

/* с помощью псевдокласса делаем цветную обводку для каждого слова */
.wrapper.invert span::before {
  -webkit-text-stroke: 0.1em var(--color);
}
Играем со шрифтами на главной странице

Посмотреть результат на странице проекта.

<!DOCTYPE html>
<html lang="ru" >
<head>
  <meta charset="UTF-8">
  <title>Играем со шрифтами и фоном</title>

  <!-- добавляем файл со стилями -->
  <link rel="stylesheet" href="style.css">

</head>
<body>
  <!-- пример текста с заливкой и прозрачными границами -->
	<div class="wrapper">
		<span data-text="Журнал"></span>
		<span data-text="Код"></span>
	</div>
  
	<!-- и наоборот — текст без заливки, но с цветным контуром -->
	<div class="wrapper invert">
		<span data-text="Журнал"></span>
		<span data-text="Код"></span>
	</div>
</body>
</html>

/* Общие настройки для всей страниц */
body {
  /* делаем высоту страницы на весь экран */
  height: 100vh;
  /* то, что не влезло в границы — скрываем */
  overflow: hidden;
  /* подключаем случайный фон и добавляем затемнение по кругу */
  background: radial-gradient(farthest-corner, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.8)), url(https://picsum.photos/1280/800) center/cover;
  /* выравниваем всё по центру */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* убираем отступы */
  margin: 0;
}


/* общий класс для текста */
.wrapper {
  /* задаём размеры текста, высоту и ширину */
  font-size: 17vmin;
  height: 2em;
  width: 100%;
  /* размещаем текст по центру блока */
  display: flex;
  align-items: center;
  justify-content: center;
  /* добавляем прозрачность для всех элементов на странице */
  mix-blend-mode: screen;
}

/* стиль для тега span, который будет лежать внутри стиля wrapper */
.wrapper span {
  /* цвет первого слова текста */
  --color: #ffba11;
  /* устанавливаем вид шрифта, его начертание и жирность */
  font-family: Impact, "Anton", Haettenschweiler, "Arial Narrow Bold", sans-serif;
  font-weight: 700;
  font-style: italic;
  /* создаём новый блок, в котором будет текст */
  display: block;
  /* включаем абсолютное позиционирование элементов */
  position: absolute;
  /* используем цвет из переменной */
  color: var(--color);
}

/* общие настройки псевдоклассов для тега span */
.wrapper span::before, .wrapper span::after {
  /* создаём в стиле новый текст */
  content: attr(data-text);
  /* делаем для него новый блок */
  display: block;
  /* включаем для него относительное позиционирование */
  position: relative;
}

/* этот псевдокласс создаёт прозрачную обводку для каждого слова */
.wrapper span::before {
  position: absolute;
  /* добавляем прозрачный контур к этому слову */
  -webkit-text-stroke: 0.1em black;
}

/* обрабатываем первое слово */
.wrapper span:first-child {
  /* сдвигаем его чуть выше и левее, чтобы он оказался не по центру */
  transform: translate(-0.255em, -0.25em);
}

/* обрабатываем второе слово */
.wrapper span:last-child {
  /* цвет второго слова */
  --color: #b6acff;
  /* сдвигаем второе слово вправо и вниз */
  transform: translate(0.255em, 0.25em);
}

/* делаем прозрачными слова */
.wrapper.invert span {
  /* используем для этого чёрный цвет */
  color: black;
}

/* с помощью псевдокласса делаем цветную обводку для каждого слова */
.wrapper.invert span::before {
  -webkit-text-stroke: 0.1em var(--color);
}

Текст:

Михаил Полянин

Редактор:

Максим Ильяхов

Художник:

Даня Берковский

Корректор:

Ирина Михеева

Вёрстка:

Кирилл Климентьев

Соцсети:

Алина Грызлова

Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
Начать карьеру в ИТ
Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию
Еще по теме
Конец ретроградному Меркурию! Пишем собственный гороскоп на Python

Наш гороскоп точен и прост! Сбросим иго астрологов!

medium
Как накопить на Айфон ещё быстрее
Как накопить на Айфон ещё быстрее

Excel нам в помощь.

easy
Улучшаем автоматизацию новостей
Улучшаем автоматизацию новостей

И получаем готовый рабочий продукт.

easy
Делаем свой текстовый редактор с автосохранением

Это не так сложно, как звучит.

medium
Прогаем в Экселе: автомобиль в кредит или по подписке?
Прогаем в Экселе: автомобиль в кредит или по подписке?

Программерский подход, подручные средства.

easy
Как утащить что угодно с любого сайта
Как утащить что угодно с любого сайта

Например, заголовки или содержимое статьи.

medium
Uncaught SyntaxError: Unexpected identifier — что это означает?
Uncaught SyntaxError: Unexpected identifier — что это означает?

Вредная ошибка, которую легко исправить.

medium
Три ИТ-проекта из России от читателей «Кода»
Три ИТ-проекта из России от читателей «Кода»

Время отечественного пиара.

medium
Что означает ошибка TypeError: can only concatenate str (not "int") to str
Что означает ошибка TypeError: can only concatenate str (not "int") to str

Это значит, что вы пытаетесь сложить строки с числами

easy
Решаем кодом: программа угадает число за 7 попыток
Решаем кодом: программа угадает число за 7 попыток

Попробуйте её победить

easy
easy