У попередній статті я розглянув здатність CSS Grid створювати складні макети, використовуючи можливості автоматичного розміщення. Я зробив ще один крок далі в іншій статті додано ефект масштабування при наведенні до зображень у макеті сітки. Цього разу я хочу зануритися в інший тип сітки, який працює з фігурами.
Наприклад, що, якщо зображення не ідеально квадратні, а натомість мають форму шестикутників або ромбів? Спойлер: ми можемо це зробити. Насправді ми об’єднаємо методи CSS Grid, які ми розглянули, і додамо трохи CSS clip-path
та mask
магія створювати химерні сітки зображень майже будь-якої форми, яку тільки можете собі уявити!
Почнемо з розмітки
Більшість макетів, які ми збираємося розглянути, на перший погляд можуть здатися легкими для виконання, але найскладніша частина полягає в тому, щоб досягти їх за допомогою та сама розмітка HTML. Ми можемо використовувати багато обгорток, div
s, і багато іншого, але мета цієї публікації полягає в тому, щоб використовувати той самий і найменший обсяг 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%);
}
Ще нічого особливого. Усі зображення є шестикутниками та розташовані один над одним. Отже, здається, що все, що ми маємо, — це єдиний елемент зображення у формі шестикутника, але насправді їх сім.
Наступним кроком буде застосування перекладу до зображень, щоб правильно розмістити їх у сітці.
Зверніть увагу, що ми все ще хочемо, щоб одне із зображень залишалося в центрі. Решта розміщуються навколо нього за допомогою 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)
) не визначено в жодному селекторі, оскільки він знаходиться в центрі. Це може бути будь-яке зображення, якщо ви вирішите використовувати інший порядок. Ось який порядок я використовую:
Використовуючи лише кілька рядків коду, ми отримуємо класну сітку зображень. До цього я додав невеликий ефект наведення до зображень, щоб зробити речі вишуканішими.
Вгадай що? Ми можемо отримати ще одну шестикутну сітку, просто оновивши кілька значень.
Якщо ви перевірите код і порівняєте його з попереднім, ви помітите, що я просто поміняв значення всередині 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
s і ми отримуємо це:
Зверніть увагу, як я обертаю їх обох 45deg
, але в зворотному напрямку.
.gallery {
/* etc. */
transform: rotate(45deg);
}
.gallery > img {
/* etc. */
transform: rotate(-45deg);
}
Обертання зображень у негативному напрямку запобігає їх обертанню разом із сіткою, тому вони залишаються прямими. Тепер ми застосовуємо a clip-path
щоб вирізати з них форму ромба.
Ми майже готові! Нам потрібно виправити розмір зображення, щоб вони підходили один до одного. В іншому випадку вони рознесені так, що це не буде схоже на сітку зображень.
Зображення знаходиться в межах зеленого кола, яке є вписаним колом області сітки, де розміщено зображення. Те, що ми хочемо, це зробити зображення більшим, щоб воно містилося всередині червоного кола, яке є окресленим колом області сітки.
Не хвилюйтеся, я більше не буду вводити нудну геометрію. Все, що вам потрібно знати, це те, що співвідношення між радіусом кожного кола є квадратним коренем з 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
значення, тоді як останні дві сітки працювали з узгодженою формою. Отже, цього разу ми ніби працюємо з кількома різними трикутними фігурами, які об’єднуються, щоб утворити прямокутну сітку зображень.
Ми розміщуємо їх усередині сітки 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 Pizza Pie Grid
Вгадай що? Ми можемо отримати ще одну класну сітку, просто додавши 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;
Дві змінні контролюють форму. The --g
змінна є нічим іншим, як розривом сітки. Нам потрібно врахувати проміжок, щоб правильно розташувати кола, щоб вони ідеально перекривалися, коли весь пазл буде зібрано. The --r
змінна керує розміром круглих частин форми пазла.
Тепер ми беремо той самий CSS і оновлюємо в ньому кілька значень, щоб створити три інші форми:
У нас є фігури, але немає країв, що перекриваються, щоб вони з’єднувалися. Кожне зображення обмежене клітинкою сітки, у якій воно міститься, тож має сенс, чому фігури наразі переплутані:
Нам потрібно створити переповнення, збільшивши висоту/ширину зображень. З наведеного вище малюнка ми повинні збільшити висоту першого та четвертого зображень, тоді як ми збільшимо ширину другого та третього. Ви, напевно, вже здогадалися, що нам потрібно збільшити їх за допомогою --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
magic, ми змогли створити макети сітки з різними формами. І ми кожного разу використовували ту саму розмітку HTML! А сама розмітка — це не що інше, як контейнер із кількома елементами зображення!
У другій частині ми збираємося дослідити більш складні на вигляд сітки з більш химерними формами та ефектами наведення.
Я планую взяти демонстрацію розширених панелей зображень, які ми створили разом ця інша стаття:
…і перетворити його на зигзагоподібні панелі зображень! І це лише один приклад із багатьох, які ми розглянемо в наступній статті.