CSS Grid и пользовательские фигуры, часть 1. Анализ данных PlatoBlockchain. Вертикальный поиск. Ай.

CSS-сетка и пользовательские фигуры, часть 1

В предыдущей статье я рассмотрел возможности CSS Grid для создавать сложные макеты, используя его возможности автоматического размещения. Я сделал еще один шаг вперед в другой статье, которая добавлен эффект масштабирования при наведении на изображения в сетке. На этот раз я хочу погрузиться в другой тип сетки, который работает с фигурами.

Например, что, если изображения не идеально квадратные, а имеют форму шестиугольников или ромбов? Спойлер: мы можем это сделать. На самом деле, мы собираемся объединить методы CSS Grid, которые мы рассмотрели, и добавить немного CSS. clip-path и mask волшебство для создания причудливых сеток изображений практически любой формы, которую вы можете себе представить!

Начнем с разметки

Большинство макетов, которые мы собираемся рассмотреть, на первый взгляд могут показаться простыми в реализации, но трудная часть заключается в том, чтобы реализовать их с помощью та же HTML-разметка. Мы можем использовать много оберток, divs и так далее, но цель этого поста — использовать тот же и наименьший объем HTML-кода и по-прежнему получать все различные сетки, которые мы хотим. В конце концов, что такое CSS, как не способ разделить стили и разметку? Наш стиль не должен зависеть от разметки, и наоборот.

Это сказало, давайте начнем с этого:

<div class="gallery">
  <img src="..." alt="...">
  <img src="..." alt="...">
  <img src="..." alt="...">
  <img src="..." alt="...">
  <!-- as many times as we want -->
</div>

Контейнер с изображениями — это все, что нам здесь нужно. Больше ничего!

CSS-сетка шестиугольников

Ее также иногда называют «сотовой» сеткой.

Уже есть много других сообщений в блогах, которые показывают, как это сделать. Черт возьми, я написал один здесь, на CSS-Tricks! Эта статья по-прежнему хороша, и в ней очень подробно рассказывается о создании адаптивного макета. Но в этом конкретном случае мы будем полагаться на гораздо более простой подход CSS.

Во-первых, давайте использовать clip-path на изображениях, чтобы создать форму шестиугольника, и мы помещаем их все в одну и ту же область сетки, чтобы они перекрывались.

.gallery {
  --s: 150px; /* controls the size */
  display: grid;
}

.gallery > img {
  grid-area: 1/1;
  width: var(--s);
  aspect-ratio: 1.15;
  object-fit: cover;
  clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0 50%);
}
clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0 50%)

Пока ничего особенного. Все изображения шестиугольники и друг над другом. Итак, похоже, что все, что у нас есть, — это один элемент изображения в форме шестиугольника, но на самом деле их семь.

Следующим шагом будет применение перевода к изображениям, чтобы правильно расположить их на сетке.

CSS Grid и пользовательские фигуры, часть 1. Анализ данных PlatoBlockchain. Вертикальный поиск. Ай.
CSS-сетка и пользовательские фигуры, часть 1

Обратите внимание, что мы по-прежнему хотим, чтобы одно из изображений оставалось в центре. Остальные размещаются вокруг него с помощью CSS translate и старая добрая геометрия. Вот фиктивные формулы, которые я придумал для каждого изображения в сетке:

translate((height + gap)*sin(0deg), (height + gap)*cos(0))
translate((height + gap)*sin(60deg), (height + gap)*cos(60deg))
translate((height + gap)*sin(120deg), (height + gap)*cos(120deg))
translate((height + gap)*sin(180deg), (height + gap)*cos(180deg))
translate((height + gap)*sin(240deg), (height + gap)*cos(240deg))
translate((height + gap)*sin(300deg), (height + gap)*cos(300deg))

После нескольких вычислений и оптимизации (давайте пропустим эту скучную часть, верно?) мы получим следующий CSS:

.gallery {
  --s: 150px; /* control the size */
  --g: 10px;  /* control the gap */
  display: grid;
}
.gallery > img {
  grid-area: 1/1;
  width: var(--s);
  aspect-ratio: 1.15;
  object-fit: cover;
  clip-path: polygon(25% 0%, 75% 0%, 100% 50% ,75% 100%, 25% 100%, 0 50%);
  transform: translate(var(--_x,0), var(--_y,0));
}
.gallery > img:nth-child(1) { --_y: calc(-100% - var(--g)); }
.gallery > img:nth-child(7) { --_y: calc( 100% + var(--g)); }
.gallery > img:nth-child(3),
.gallery > img:nth-child(5) { --_x: calc(-75% - .87*var(--g)); }
.gallery > img:nth-child(4),
.gallery > img:nth-child(6) { --_x: calc( 75% + .87*var(--g)); }
.gallery > img:nth-child(3),
.gallery > img:nth-child(4) { --_y: calc(-50% - .5*var(--g)); }
.gallery > img:nth-child(5), 
.gallery > img:nth-child(6) { --_y: calc( 50% + .5*var(--g)); }

Может быть, это будет легче, когда мы получим настоящие тригонометрические функции в CSS!

Каждое изображение переведено --_x и --_y переменные, основанные на этих формулах. Только второе изображение(nth-child(2)) не определен ни в одном селекторе, потому что он находится в центре. Это может быть любое изображение, если вы решите использовать другой порядок. Вот порядок, который я использую:

CSS Grid и пользовательские фигуры, часть 1. Анализ данных PlatoBlockchain. Вертикальный поиск. Ай.
CSS-сетка и пользовательские фигуры, часть 1

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

Угадай, что? Мы можем получить еще одну шестиугольную сетку, просто изменив несколько значений.

Если вы проверите код и сравните его с предыдущим, вы заметите, что я просто поменял местами значения внутри clip-path и я переключился между --x и --y. Вот и все!

CSS сетка ромбов

Ромб — такое причудливое слово для квадрата, повернутого на 45 градусов.

Тот же HTML, помните? Сначала мы начнем с определения сетки изображений 2×2 в CSS:

.gallery {
  --s: 150px; /* controls the size */

  display: grid;
  gap: 10px;
  grid: auto-flow var(--s) / repeat(2, var(--s));
  place-items: center;
}
.gallery > img {
  width: 100%; 
  aspect-ratio: 1;
  object-fit: cover;
}

Первое, что может броситься в глаза, это grid имущество. Он довольно редко используется, но очень полезен, потому что это сокращение, которое позволяет вам определить полную сетку в одном объявлении. Это не самое интуитивно понятное — и не говоря уже о читабельном — свойство, но мы здесь, чтобы изучить и обнаружить новые вещи, так что давайте использовать его, а не записывать все отдельные свойства сетки.

grid: auto-flow var(--s) / repeat(2,var(--s));

/* is equivalent to this: */
grid-template-columns: repeat(2, var(--s));
grid-auto-rows: var(--s);

Это определяет два столбца, равных --s переменная и устанавливает высоту всех строк в --s также. Поскольку у нас есть четыре изображения, мы автоматически получим сетку 2×2.

Вот как мы могли бы написать это по-другому:

grid-template-columns: repeat(2, var(--s));
grid-template-rows: repeat(2, var(--s));

…которую можно уменьшить с помощью grid стенография:

grid: repeat(2,var(--s)) / repeat(2,var(--s));

После настройки сетки мы поворачиваем ее и изображения с помощью CSS. transformс, и мы получаем это:

Обратите внимание, как я поворачиваю их обоих на 45deg, но в обратном направлении.

.gallery {
  /* etc. */
  transform: rotate(45deg);
}
.gallery > img {
  /* etc. */
  transform: rotate(-45deg);
}

Поворот изображений в отрицательном направлении предотвращает их вращение вместе с сеткой, поэтому они остаются прямыми. Теперь мы применяем clip-path чтобы вырезать из них ромб.

CSS Grid и пользовательские фигуры, часть 1. Анализ данных PlatoBlockchain. Вертикальный поиск. Ай.
clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%)

Мы почти закончили! Нам нужно исправить размер изображения, чтобы они соответствовали друг другу. В противном случае они разнесены далеко друг от друга до такой степени, что это не похоже на сетку изображений.

CSS Grid и пользовательские фигуры, часть 1. Анализ данных PlatoBlockchain. Вертикальный поиск. Ай.
CSS-сетка и пользовательские фигуры, часть 1

Изображение находится в пределах зеленого круга, который является вписанным кругом области сетки, в которой размещено изображение. Мы хотим сделать изображение больше, чтобы оно поместилось внутри красного круга, который представляет собой описанный круг области сетки.

Не волнуйтесь, я больше не буду вводить скучную геометрию. Все, что вам нужно знать, это то, что соотношение между радиусом каждого круга равно квадратному корню из 2 (sqrt(2)). Это значение нам нужно, чтобы увеличить размер наших изображений, чтобы заполнить область. Мы будем использовать 100%*sqrt(2) = 141% и готово!

.gallery {
  --s: 150px; /* control the size */

  display: grid;
  grid: auto-flow var(--s) / repeat(2,var(--s));
  gap: 10px;
  place-items: center;
  transform: rotate(45deg);
}
.gallery > img {
  width: 141%; /* 100%*sqrt(2) = 141% */
  aspect-ratio: 1;
  object-fit: cover;
  transform: rotate(-45deg);
  clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
}

Как и в случае с шестиугольной сеткой, мы можем сделать вещи более привлекательными с помощью этого приятного эффекта масштабирования при наведении:

CSS-сетка треугольных фигур

Вы, наверное, уже знаете, что большая хитрость заключается в том, чтобы выяснить, clip-path чтобы получить формы, которые мы хотим. Для этой сетки каждый элемент имеет свой собственный clip-path значение, тогда как последние две сетки работали с постоянной формой. Итак, на этот раз мы как будто работаем с несколькими различными треугольными формами, которые вместе образуют прямоугольную сетку изображений.

CSS Grid и пользовательские фигуры, часть 1. Анализ данных PlatoBlockchain. Вертикальный поиск. Ай.
Три изображения вверху
CSS Grid и пользовательские фигуры, часть 1. Анализ данных PlatoBlockchain. Вертикальный поиск. Ай.
Три изображения внизу

Мы помещаем их в сетку 3×2 с помощью следующего CSS:

.gallery {
  display: grid;
  gap: 10px; 
  grid-template-columns: auto auto auto; /* 3 columns */
  place-items: center;
}
.gallery > img {
  width: 200px; /* controls the size */
  aspect-ratio: 1;
  object-fit: cover;
}
/* the clip-path values */
.gallery > img:nth-child(1) { clip-path: polygon(0 0, 50% 0, 100% 100% ,0 100%); }
.gallery > img:nth-child(2) { clip-path: polygon(0 0, 100% 0, 50% 100%); }
.gallery > img:nth-child(3) { clip-path: polygon(50% 0, 100% 0, 100% 100%, 0 100%); }
.gallery > img:nth-child(4) { clip-path: polygon(0 0, 100% 0, 50% 100%, 0 100%); }
.gallery > img:nth-child(5) { clip-path: polygon(50% 0, 100% 100%, 0% 100%); }
.gallery > img:nth-child(6) { clip-path: polygon(0 0, 100% 0 ,100% 100%, 50% 100%); } }

Вот что мы получаем:

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

grid-template-columns: auto 0 auto;

Мне пришлось возиться с clip-path значения, чтобы убедиться, что все они хорошо сочетаются друг с другом, как головоломка. Исходные изображения перекрываются, когда средний столбец имеет нулевую ширину, но после нарезки изображений иллюзия идеальна:

CSS Grid и пользовательские фигуры, часть 1. Анализ данных PlatoBlockchain. Вертикальный поиск. Ай.
CSS-сетка и пользовательские фигуры, часть 1

Сетка пирога для пиццы CSS

Угадай, что? Мы можем получить еще одну классную сетку, просто добавив border-radius и overflow к нашей сетке или треугольным формам. 🎉

CSS сетка кусочков головоломки

На этот раз мы поиграем с CSS. mask свойство, чтобы изображения выглядели как кусочки головоломки.

Если вы не использовали mask CSS-градиенты, Я очень рекомендую эта другая статья Я написал в теме, потому что это поможет с тем, что будет дальше. Почему градиенты? Потому что это то, что мы используем, чтобы получить круглые выемки в формах кусочков головоломки.

Настроить сетку уже несложно, так что давайте вместо этого сосредоточимся на mask часть.

Как показано в приведенной выше демонстрации, нам нужны два градиента для создания окончательной формы. Один градиент создает круг (зеленая часть), а другой создает правильную кривую, заполняя верхнюю часть.

--g: 6px; /* controls the gap */
--r: 42px;  /* control the circular shapes */

background: 
  radial-gradient(var(--r) at left 50% bottom var(--r), green 95%, #0000),
  radial-gradient(calc(var(--r) + var(--g)) at calc(100% + var(--g)) 50%, #0000 95%, red)
  top/100% calc(100% - var(--r)) no-repeat;

Две переменные управляют формой. --g переменная не что иное, как разрыв сетки. Нам нужно учитывать зазор, чтобы правильно разместить наши круги, чтобы они идеально перекрывались, когда вся головоломка собрана. --r переменная управляет размером круглых частей формы головоломки.

CSS Grid и пользовательские фигуры, часть 1. Анализ данных PlatoBlockchain. Вертикальный поиск. Ай.
CSS-сетка и пользовательские фигуры, часть 1

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

У нас есть формы, но нет перекрывающихся ребер, которые нам нужны, чтобы совместить их друг с другом. Каждое изображение ограничено ячейкой сетки, в которой оно находится, поэтому понятно, почему в данный момент формы перемешаны:

CSS Grid и пользовательские фигуры, часть 1. Анализ данных PlatoBlockchain. Вертикальный поиск. Ай.
CSS-сетка и пользовательские фигуры, часть 1

Нам нужно создать переполнение, увеличив высоту/ширину изображений. Из приведенного выше рисунка мы должны увеличить высоту первого и четвертого изображений, а также увеличить ширину второго и третьего. Вы, наверное, уже догадались, что нам нужно увеличить их с помощью --r Переменная.

.gallery > img:is(:nth-child(1),:nth-child(4)) {
  width: 100%;
  height: calc(100% + var(--r));
}
.gallery > img:is(:nth-child(2),:nth-child(3)) {
  height: 100%;
  width: calc(100% + var(--r));
}

Мы приближаемся!

Мы создали перекрытие, но по умолчанию наши изображения перекрываются либо справа (если мы увеличиваем ширину), либо снизу (если мы увеличиваем высоту). Но это не то, что мы хотим для второго и четвертого изображений. Исправление заключается в использовании place-self: end на этих двух изображениях, и наш полный код становится таким:

Вот еще один пример, где я использую конический градиент вместо радиального. Это дает нам треугольные кусочки головоломки, сохраняя при этом тот же базовый HTML и CSS.

Последний! На этот раз я использую clip-path и так как это свойство, которое мы можем анимировать, мы получаем крутой ховер, просто обновляя пользовательское свойство, которое управляет формой.

Подведение итогов

Это все для этой первой части! Объединив то, что мы уже узнали о CSS Grid, с некоторыми дополнительными clip-path и mask волшебство, мы смогли сделать сетку с различными формами. И каждый раз мы использовали одну и ту же HTML-разметку! А сама разметка — не что иное, как контейнер с горсткой элементов изображения!

Во второй части мы собираемся исследовать более сложные на вид сетки с более причудливыми формами и эффектами наведения.

Я планирую воспользоваться демонстрацией расширения панелей изображений, которые мы сделали вместе в эта другая статья:

…и превратите его в зигзагообразные панели изображений! И это только один пример из многих, которые мы обнаружим в следующей статье.

Отметка времени:

Больше от CSS хитрости