Сегодня займёмся искусством сразу в двух направлениях: нарисуем 9 разных картин и посмотрим, как это легко сделать с помощью современного CSS. Работы на 10–15 минут, а в конце получится такая красота:
Логика проекта
Всё, что нам сегодня будет нужно, — это HTML и CSS. Скрипты не понадобятся, потому что современные стили уже умеют работать с переменными и создавать новые картинки на основе других элементов на странице.
Работу построим так:
- Создадим HTML-страницу, где разместим блоки, в которых и появятся наши картинки.
- Зададим стили для всей страницы и общие для блоков.
- Нарисуем первую картинку.
- На основе первой создадим остальные 8 — и каждая будет выглядеть иначе.
Подводных камней тут нет, поэтому сразу приступим.
Создаём HTML-страницу
Открываем редактор кода, создаём новый файл и сохраняем его сразу как index.html
. Всё, что нам нужно от страницы, — добавить блоки, в которых и будут создаваться картинки. Также добавим общий блок, внутри которого будут появляться наши картинки — так мы сможем настроить сразу их размер, отступы и расположение (но это уже сделаем в стилях, которые подключим сразу):
<!DOCTYPE html>
<html lang="ru" >
<head>
<meta charset="UTF-8">
<title>Создаём абстрактный фон</title>
<!-- Подключаем стили -->
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- Общий блок с картинками -->
<div class="wrapper">
<!-- Отдельные блоки для каждой картинки -->
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</body>
</html>
Сохраняем — и переходим к стилям. Можно сразу открыть эту страницу в браузере, но пока мы там увидим только пустой белый фон. Всё потому, что мы ничего не задали внутри блоков — над этим и будем работать в стилях.
Настраиваем стили
Теперь создаём новый файл style.css
и начинаем наполнять уже его.
Первое, что делаем — ограничиваем визуальное отображение каждого блока по границам. Это нам нужно для того, чтобы если что-то не помещается в блок, это обрезалось как раз по границам блока:
/* Ограничиваем размер содержимого блока их границами */
* {
box-sizing: border-box;
}
Следующий шаг — общие настройки для всей страницы. Тут мы используем переменные для размера рамок и цвета фона, чтобы было проще работать. Все элементы на странице располагаем по сетке, а контент — по центру. Ну и фон сразу сделаем тёмно-зелёным, чтобы было контрастнее:
/* Общие настройки для всей страницы */
body {
/* Переменные для размера рамок и цвета фона в картинках */
--s: max(1rem, 2vw);
--bg: deeppink;
/* Настраиваем отступы */
margin: 0;
padding: var(--s);
/* Размещаем элементы по сетке */
display: grid;
/* Пусть контент занимает всю высоту экрана */
min-height: 100vh;
/* Располагаем элементы по центру */
place-items: center;
/* Цвет фона для страницы */
background: teal;
}
Визуально у нас поменялся только фон, но эти стили нам помогут правильно разместить элементы на странице, когда они появятся. Обновляем браузер и видим новый фон:
Настраиваем модуль с блоками
У нас есть общий блок с классом .wrapper
, где располагаются 9 блоков с будущими картинками. Пропишем стили, которые будут влиять сразу на все блоки внутри — их размер, расстояние между ними и их расстановку:
/* Настройки общего блока с картинками */
.wrapper {
/* Настраиваем ширину блока */
width: 100%;
max-width: 70rem;
/* Размещаем элементы по сетке */
display: grid;
/* Устанавливаем расстояние между картинками */
gap: var(--s);
/* Заполняем общий блок мелкими картинками с автоподбором расстояния */
grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
}
Теперь настроим стили уже для этих отдельных маленьких блоков — сделаем их квадратными, добавим рамку и фон:
/* Настройки отдельной картинки внутри общего блока */
.wrapper div {
/* Делаем их квадратными */
aspect-ratio: 1;
/* Настраиваем рамки вокруг картинок */
border: calc(var(--s) * 0.2) solid;
/* Задаём фон для мелких картинок */
background-color: var(--bg);
}
Если обновить страницу в браузере, то увидим, что у нас появилось что-то новое — те самые 9 основ для картинок, которые нам предстоит создать (и сделать разными):
Рисуем первую картинку
👉 Сейчас внимательно: мы продолжаем работать внутри стиля для отдельных картинок — просто продолжаем писать код внутри этого раздела.
Чтобы нарисовать картинку, используем три элемента: чёрные линии, зелёную полосу и белый круг. Ещё нам понадобится стартовое смещение для зелёной полосы, чтобы она начиналась не от края картинки, а где-то в другом месте. И ещё: внутри мы используем переменные со значениями по умолчанию, чтобы можно было потом это использовать для создания других картинок на основе первой.
Рисуем первую картинку:
/* Смещение зелёной полосы */
--c1-pos: 30%;
/* Все элементы на картинке используются как части изображения */
background-image:
/* Создаём чёрные линии */
linear-gradient(
/* Направление линий */
var(--black-dir, to bottom),
/* Формируем 4 линии, каждая со своими параметрами прозрачности */
transparent 10%, black 0, black 15%, transparent 0,
transparent 18%, black 0, black 22%, transparent 0,
transparent 25.25%, black 0, black 29%, transparent 0,
transparent 33%, black 0, black 35.5%, transparent 0),
/* Создаём зелёную полосу */
linear-gradient(
/* Направление полосы */
var(--c1-angle, 105deg),
/* Параметры зелёной полосы */
transparent var(--c1-pos), lime 0, lime calc(var(--c1-pos) + var(--c1-w, 10%)), transparent 0),
/* Создаём белый круг */
radial-gradient(
/* Положение круга */
circle at var(--circle-pos, 75% 75%),
/* Размер круга */
white var(--circle-size, 30%),
/* Прозрачность */
transparent 0);
Вот что у нас получилось:
Смотрите, что здесь произошло и почему именно так.
- Мы нарисовали первую картинку: расположили чёрные линии, зелёную полосу и круг так, как нам нужно (ну, или как захотели, без разницы).
- Всё это мы прописали в стиле для конкретного блока.
- Так как все 9 блоков внутри общего — одинаковые, то мы и получили 9 одинаковых картинок.
Теперь сделаем так, чтобы все картинки были разными.
Делаем так, чтобы картинки отличались
Так как наша задача в том, чтобы картинки отличались друг от друга, мы используем псевдокласс :nth-child()
, где в скобках указывается какое-то число. Этот псевдокласс смотрит на число в скобках и находит такой же по счёту элемент среди всех элементов того же класса.
Первая картинка у нас готова, значит будем работать со вторым элементом — :nth-child(2)
. Так как мы при создании первой картинки использовали переменные, нам достаточно в этом псевдоклассе поменять значения этих переменных, чтобы получить новый результат:
/* Указываем параметры картинки во втором блоке */
&:nth-child(2) {
/* Поворачиваем чёрные линии */
--black-dir: 35deg;
/* Поворачиваем зелёную линию */
--c1-angle: 175deg;
/* Настраиваем ширину зелёной линии */
--c1-w: 55%;
/* Указываем центр круга */
--circle-pos: 60% 12%;
/* Настраиваем размер круга */
--circle-size: 9%;
}
Обратите внимание на вторую картинку: она отличается визуально от первой, хотя состоит из тех же компонентов. Мы просто изменили несколько переменных, а браузер сам пересчитал их значения для второй картинки.
Теперь зная, как это работает, поменяем переменные во всех остальных картинках:
&:nth-child(3) {
--black-dir: 250deg;
--c1-angle: 360deg;
--c1-w: 15%;
--circle-pos: 5% 50%;
--circle-size: 40%;
}
&:nth-child(4) {
--black-dir: 280deg;
--c1-angle: 20deg;
--c1-w: 5%;
--circle-pos: 25% 25%;
--circle-size: 18%;
}
&:nth-child(5) {
--black-dir: 0;
--c1-angle: 135deg;
--c1-w: 60%;
--circle-pos: 35% 35%;
--circle-size: 30%;
}
&:nth-child(6) {
--black-dir: 50deg;
--c1-angle: 265deg;
--c1-w: 10%;
--circle-pos: 40% 45%;
--circle-size: 10%;
}
&:nth-child(7) {
--black-dir: 140deg;
--c1-angle: 90deg;
--c1-w: 20%;
--circle-pos: 50% 65%;
--circle-size: 24%;
}
&:nth-child(8) {
--black-dir: 190deg;
--c1-angle: 10deg;
--c1-w: 8%;
--circle-pos: 50% 120%;
--circle-size: 50%;
}
&:nth-child(9) {
--black-dir: 100deg;
--c1-angle: -40deg;
--c1-w: 25%;
--circle-pos: 40% 20%;
--circle-size: 12%;
}
Обновляем страницу и видим финальный результат. Вы можете поменять значения переменных на любые другие — и получить совершенно другие картинки. А ещё можно сделать так, чтобы они формировались случайным образом при обновлении страницы — и это уже тема для отдельного проекта.
<!DOCTYPE html>
<html lang="ru" >
<head>
<meta charset="UTF-8">
<title>Создаём абстрактный фон</title>
<!-- Подключаем стили -->
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- Общий блок с картинками -->
<div class="wrapper">
<!-- Отдельные блоки для каждой картинки -->
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</body>
</html>
/* Ограничиваем размер содержимого блока их границами */
* {
box-sizing: border-box;
}
/* Общие настройки для всей страницы */
body {
/* Переменные для размера рамок и цвета фона в картинках */
--s: max(1rem, 2vw);
--bg: deeppink;
/* Настраиваем отступы */
margin: 0;
padding: var(--s);
/* Размещаем элементы по сетке */
display: grid;
/* Пусть контент занимает всю высоту экрана */
min-height: 100vh;
/* Располагаем элементы по центру */
place-items: center;
/* Цвет фона для страницы */
background: teal;
}
/* Настройки общего блока с картинками */
.wrapper {
/* Настраиваем ширину блока */
width: 100%;
max-width: 70rem;
/* Размещаем элементы по сетке */
display: grid;
/* Устанавливаем расстояние между картинками */
gap: var(--s);
/* Заполняем общий блок мелкими картинками с автоподбором расстояния */
grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
}
/* Настройки отдельной картинки внутри общего блока */
.wrapper div {
/* Делаем их квадратными */
aspect-ratio: 1;
/* Настраиваем рамки вокруг картинок */
border: calc(var(--s) * 0.2) solid;
/* Задаём фон для мелких картинок */
background-color: var(--bg);
/* Создаём и настраиваем первую картинку */
--c1-pos: 30%;
/* Все элементы на картинке используются как части изображения */
background-image:
/* Создаём чёрные линии */
linear-gradient(
/* Направление линий */
var(--black-dir, to bottom),
/* Формируем 4 линии, каждая со своими параметрами прозрачности */
transparent 10%, black 0, black 15%, transparent 0,
transparent 18%, black 0, black 22%, transparent 0,
transparent 25.25%, black 0, black 29%, transparent 0,
transparent 33%, black 0, black 35.5%, transparent 0),
/* Создаём зелёную полосу */
linear-gradient(
/* Направление полосы */
var(--c1-angle, 105deg),
/* Параметры зелёной полосы */
transparent var(--c1-pos), lime 0, lime calc(var(--c1-pos) + var(--c1-w, 10%)), transparent 0),
/* Создаём белый круг */
radial-gradient(
/* Положение круга */
circle at var(--circle-pos, 75% 75%),
/* Размер круга */
white var(--circle-size, 30%),
/* Прозрачность */
transparent 0);
/* Указываем параметры картинки во втором блоке */
&:nth-child(2) {
/* Поворачиваем чёрные линии */
--black-dir: 35deg;
/* Поворачиваем зелёную линию */
--c1-angle: 175deg;
/* Настраиваем ширину зелёной линии */
--c1-w: 55%;
/* Указываем центр круга */
--circle-pos: 60% 12%;
/* Настраиваем размер круга */
--circle-size: 9%;
}
&:nth-child(3) {
--black-dir: 250deg;
--c1-angle: 360deg;
--c1-w: 15%;
--circle-pos: 5% 50%;
--circle-size: 40%;
}
&:nth-child(4) {
--black-dir: 280deg;
--c1-angle: 20deg;
--c1-w: 5%;
--circle-pos: 25% 25%;
--circle-size: 18%;
}
&:nth-child(5) {
--black-dir: 0;
--c1-angle: 135deg;
--c1-w: 60%;
--circle-pos: 35% 35%;
--circle-size: 30%;
}
&:nth-child(6) {
--black-dir: 50deg;
--c1-angle: 265deg;
--c1-w: 10%;
--circle-pos: 40% 45%;
--circle-size: 10%;
}
&:nth-child(7) {
--black-dir: 140deg;
--c1-angle: 90deg;
--c1-w: 20%;
--circle-pos: 50% 65%;
--circle-size: 24%;
}
&:nth-child(8) {
--black-dir: 190deg;
--c1-angle: 10deg;
--c1-w: 8%;
--circle-pos: 50% 120%;
--circle-size: 50%;
}
&:nth-child(9) {
--black-dir: 100deg;
--c1-angle: -40deg;
--c1-w: 25%;
--circle-pos: 40% 20%;
--circle-size: 12%;
}
}