Масштабування зображень у макеті сітки PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Масштабування зображень у макеті сітки

Завдяки CSS Grid створити сітку зображень легко. Але змушувати сітку робити дивовижні речі після розміщені зображення може бути важко зняти.

Скажімо, ви хочете додати ефект наведення до зображень, де вони ростуть і масштабуються за межі рядків і стовпців, де вони розташовані? Ми можемо це зробити!

Круто, правда? Якщо ви перевірите код, ви не знайдете ні JavaScript, ні складних селекторів, ні навіть магічні числа. І це лише один приклад із багатьох, які ми розглянемо!

Побудова сітки

HTML-код для створення сітки такий же простий, як список зображень у контейнері. Більше нам не потрібно.

<div class="gallery">
  <img>
  <img>
  <img>
  <!-- etc. -->
</div>

Для CSS ми спочатку налаштуємо сітку за допомогою наступного:

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

  display: grid;
  gap: var(--g);
  width: calc(3*var(--s) + 2*var(--g)); /* 3 times the size plus 2 times the gap */
  aspect-ratio: 1;
  grid-template-columns: repeat(3, auto);
}

Коротше кажучи, у нас є дві змінні: одна керує розміром зображень, а інша встановлює розмір проміжку між зображеннями. aspect-ratio допомагає зберігати пропорції.

Вам може бути цікаво, чому ми визначаємо лише три стовпці, а не рядки. Ні, я не забув рядки — нам просто не потрібно їх явно встановлювати. CSS Grid здатний автоматично розміщувати елементи на неявні рядки та стовпці, що означає, що ми отримуємо стільки рядків, скільки потрібно для будь-якої кількості зображень, які ми кидаємо на нього. Натомість ми можемо явно визначити рядки, але нам потрібно додати grid-auto-flow: column щоб переконатися, що браузер створить для нас необхідні стовпці.

Ось приклад для ілюстрації обох випадків. Різниця в тому, що один тече в a row напрямок і інший в a column напрямок.

Перевіряти цю статтю я написав щоб дізнатися більше про неявні сітки та алгоритм автоматичного розміщення.

Тепер, коли у нас є сітка, настав час стилізувати зображення:

.gallery > img {
  width: 0;
  height: 0;
  min-height: 100%;
  min-width: 100%;
  object-fit: cover;
}

Ефект наведення, який ми створюємо, покладається на цей CSS. Можливо, вам здається дивним, що ми створюємо зображення, які не мають ні ширини, ні висоти, але мають мінімальну ширину та висоту 100%. Але ви побачите, що це досить влучний трюк для того, чого ми намагаємося досягти.

Що я тут роблю, це повідомляю браузеру, що зображення повинні мати 0 ширину та висоту, але мінімальна висота також повинна дорівнювати 100%... але 100% якого? При використанні відсотків значення дорівнює відносно чогось іншого. У цьому випадку наше зображення розміщується всередині a комірка сітки і нам потрібно знати цей розмір, щоб знати, що таке 100% відносно.

Браузер спочатку проігнорує min-height: 100% щоб обчислити розмір комірок сітки, але він буде використовувати height: 0 в його розрахунку. Це означає, що наші зображення не впливатимуть на розмір комірок сітки... оскільки технічно вони не мають фізичного розміру. Це призведе до трьох рівних стовпців і рядків, які базуються на розмірі сітки (який ми визначили на .galleryширина і aspect-ratio). Висота кожної комірки сітки є не що інше, як змінна --s ми визначили (те саме для ширини).

Масштабування зображень у макеті сітки

Тепер, коли ми маємо розміри клітинок нашої сітки, браузер використовуватиме їх min-height: 100%min-width: 100%), що змусить зображення повністю заповнити простір кожної комірки сітки. Все це може виглядати дещо заплутаним, але головна ідея полягає в тому, щоб переконатися, що сітка визначає розмір зображень, а не навпаки. Я не хочу, щоб зображення визначало розмір сітки, і ви зрозумієте чому після додавання ефекту наведення.

Створення ефекту наведення

Що нам потрібно зробити, це збільшити масштаб зображень, коли вони наводяться. Ми можемо зробити це, відкоригувавши зображення width та height on :hover:

.gallery {
  --f: 1.5; /* controls the scale factor */
}

.gallery img:hover{
  width:  calc(var(--s) * var(--f));
  height: calc(var(--s) * var(--f));
}

Я додав нову користувацьку змінну, --f, до суміші як масштабного коефіцієнта для керування розміром при наведенні. Зверніть увагу, як я множу змінну розміру, --s, щоб обчислити новий розмір зображення.

Але ви сказали, що розмір зображення має бути 0. Що відбувається? Я загубився…

Те, що я сказав, усе ще вірно, але я роблю виняток для зображення, яке наведено. Я повідомляю веб-переглядачу, що лише одне зображення матиме розмір, який не дорівнює нулю, тож це сприятиме розміру сітки, а всі інші залишатимуться рівними 0.

Масштабування зображень у макеті сітки PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.
Масштабування зображень у макеті сітки

Ліва сторона показує сітку в її природному стані без будь-яких наведених зображень, як і права сторона. Усі клітинки сітки ліворуч мають однаковий розмір, оскільки всі зображення не мають фізичних розмірів.

Праворуч на друге зображення в першому рядку наведено курсор, що надає йому розміри, які впливають на розмір комірки сітки. Під час наведення курсора браузер збільшить конкретну клітинку сітки, що вплине на загальний розмір. А оскільки встановлено розмір усієї сітки (оскільки ми встановили фіксований width на .gallery), інші комірки сітки будуть логічно реагувати, стаючи меншими, щоб зберегти .galleryзагальний розмір такт.

Ось наш ефект масштабування в дії! Збільшуючи розмір лише одного зображення, ми впливаємо на всю конфігурацію сітки, і ми вже говорили, що сітка визначає розмір зображень таким чином, що кожне зображення розтягується всередині своєї клітинки сітки, щоб заповнити весь простір.

До цього ми додаємо нотку transition І використовувати object-fit щоб уникнути спотворення зображення, і ілюзія ідеальна!

Я знаю, що логіку цього трюку зрозуміти нелегко. Не хвилюйтеся, якщо ви не до кінця це розумієте. Найважливішим є розуміння структури використовуваного коду та того, як його змінити, щоб отримати більше варіантів. Ось що ми будемо робити далі!

Додавання інших зображень

Ми створили сітку 3×3, щоб пояснити головний трюк, але ви, мабуть, здогадалися, що нам не потрібно зупинятися на цьому. Ми можемо зробити змінними кількість стовпців і рядків і додати скільки завгодно зображень.

.gallery {
  --n: 3; /* number of rows*/
  --m: 4; /* number of columns */
  --s: 150px; /* control the size */
  --g: 10px;  /* control the gap */
  --f: 1.5;   /* control the scale factor */

  display: grid;
  gap: var(--g);
  width:  calc(var(--m)*var(--s) + (var(--m) - 1)*var(--g));
  height: calc(var(--n)*var(--s) + (var(--n) - 1)*var(--g));
  grid-template-columns: repeat(var(--m),auto);
}

У нас є дві нові змінні для кількості рядків і стовпців. Потім ми просто визначаємо ширину та висоту нашої сітки, використовуючи їх. Те саме для grid-template-columns який використовує --m змінна. Як і раніше, нам не потрібно явно визначати рядки, оскільки функція автоматичного розміщення CSS Grid виконає цю роботу за нас, незалежно від того, скільки елементів зображення ми використовуємо.

Чому не різні значення для ширини та висоти? Ми можемо це зробити:

.gallery {
  --n: 3; /* number of rows*/
  --m: 4; /* number of columns */
  --h: 120px; /* control the height */
  --w: 150px; /* control the width */
  --g: 10px;  /* control the gap */
  --f: 1.5;   /* control the scale factor */

  display: grid;
  gap: var(--g);
  width:  calc(var(--m)*var(--w) + (var(--m) - 1)*var(--g));
  height: calc(var(--n)*var(--h) + (var(--n) - 1)*var(--g));
  grid-template-columns: repeat(var(--m),auto);
}

.gallery img:hover{
  width:  calc(var(--w)*var(--f));
  height: calc(var(--h)*var(--f));
}

Замінюємо --s з двома змінними, одна для ширини, --w, і ще один для висоти, --h. Потім відповідно регулюємо все інше.

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

А як щодо повноекранної версії? Так, це теж можливо. Все, що нам потрібно, це знати, які значення ми повинні призначити нашим змінним. Якщо ми хочемо N рядків зображень, і ми хочемо, щоб наша сітка була на весь екран, нам спочатку потрібно визначити висоту 100vh:

var(--n) * var(--h) + (var(--n) - 1) * var(--g) = 100vh

Така сама логіка для ширини, але з використанням vw замість vh:

var(--m) * var(--w) + (var(--m) - 1) * var(--g) = 100vw

Ми обчислюємо, щоб отримати:

--w: (100vw - (var(--m) - 1) * var(--g)) / var(--m)
--h: (100vh - (var(--n) - 1) * var(--g)) / var(--n)

Готово!

Це той самий HTML, але з деякими оновленими змінними, які змінюють розмір і поведінку сітки.

Зауважте, що я пропустив формулу, яку ми попередньо встановили на .galleryс width та height і замінив їх на 100vw та 100vh, відповідно. Формула дасть той самий результат, але оскільки ми знаємо, яке значення ми хочемо, ми можемо відмовитися від цієї додаткової складності.

Ми також можемо спростити --h та --w шляхом усунення прогалини в рівнянні на користь цього:

--h: calc(100vh / var(--n)); /* Viewport height divided by number of rows */
--w: calc(100vw / var(--m)); /* Viewport width divided by number of columns */

Це призведе до того, що наведене зображення збільшиться трохи більше, ніж у попередньому прикладі, але це нічого страшного, оскільки ми можемо контролювати масштаб за допомогою --f змінна, яку ми використовуємо як множник.

І оскільки змінні використовуються в одному місці, ми все одно можемо спростити код, видаливши їх взагалі:

Важливо зазначити, що ця оптимізація стосується лише повноекранного прикладу, а не прикладів, які ми розглянули. Цей приклад є окремим випадком, коли ми можемо полегшити код, усунувши частину складної обчислювальної роботи, яка потрібна в інших прикладах.

Насправді у нас є все необхідне для створення популярного шаблону розширювальних панелей:

Копнімо ще глибше

Ви помітили, що наш коефіцієнт масштабування може бути меншим за 1? Ми можемо визначити розмір наведеного зображення меншим за --h or --w але зображення стає більшим при наведенні.

Початковий розмір комірки сітки дорівнює --w та --h, чому менші значення утворюють клітинку сітки більший? Чи не повинна клітина дістати менше, чи принаймні зберегти початковий розмір? І який кінцевий розмір комірки сітки?

Нам потрібно глибше розібратися в тому, як алгоритм CSS Grid обчислює розмір комірок сітки. І це включає розуміння CSS Grid за замовчуванням розтягнути вирівнювання.

Ось приклад для розуміння логіки.

У лівій частині демонстрації я визначив два стовпці з auto ширина. Отримуємо інтуїтивно зрозумілий результат: два рівних стовпця (і дві однакові комірки сітки). Але сітка, яку я встановив у правій частині демонстрації, де я оновлюю вирівнювання за допомогою place-content: start, здається, нічого не має.

DevTools допомагає нам показати, що насправді відбувається в обох випадках:

Масштабування зображень у макеті сітки PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.
Масштабування зображень у макеті сітки

У другій сітці ми маємо два стовпці, але їх ширина дорівнює нулю, тому ми отримуємо дві клітинки сітки, які згорнуті у верхньому лівому куті контейнера сітки. Це є НЕ помилка, але логічний результат вирівнювання сітки. Коли ми змінюємо розмір стовпця (або рядка) за допомогою auto, це означає, що його вміст визначає його розмір — але ми маємо порожній div без змісту, щоб звільнити місце.

Але так stretch є вирівнюванням за замовчуванням, і у нас достатньо місця всередині нашої сітки, браузер розтягне обидві комірки сітки однаково, щоб покрити всю цю область. Ось так сітка зліва складається з двох рівних стовпців.

Від специфікація:

Зверніть увагу, що певні значення justify-content та align-content може призвести до розносу доріжок (space-around, space-between, space-evenly) або змінити розмір (stretch).

Зверніть увагу на «розмір потрібно змінити», який тут є ключовим. В останньому прикладі я використав place-content що є скороченням для justify-content та align-content

І це десь закопано алгоритм Grid Sizing специфікації:

Цей крок розширює треки, які мають автоматичний функція визначення розміру максимальної доріжки шляхом ділення будь-якого позитивного, що залишився, визначений вільний простір порівну між ними. Якщо вільне місце є невизначений, але сітковий контейнер має певну мінімальна ширина/висота, замість цього використовуйте цей розмір, щоб обчислити вільний простір для цього кроку.

«Однаково» пояснює, чому ми отримуємо рівні клітинки сітки, але це стосується «вільного простору», що дуже важливо.

Давайте візьмемо попередній приклад і додамо вміст до одного з divs:

Ми додали квадрат 50px зображення. Ось ілюстрація того, як кожна сітка в нашому прикладі реагує на це зображення:

Масштабування зображень у макеті сітки PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.
Масштабування зображень у макеті сітки

У першому випадку ми бачимо, що перша клітинка (червона) більша за другу (синя). У другому випадку розмір першої клітинки змінюється відповідно до фізичного розміру зображення, тоді як друга клітинка залишається без розмірів. Вільний простір поділено порівну, але перша комірка містить більше вмісту, що робить її більшою.

Це математика, щоб визначити наш вільний простір:

(grid width) - (gap) - (image width) = (free space)
200px - 5px - 50px = 145px 

Поділивши на два — кількість колонок — ми отримаємо ширину 72.5px для кожного стовпця. Але ми додаємо розмір зображення, 50px, до першого стовпця, який залишає нам один стовпець на 122.5px а другий дорівнює 72.5px.

Така ж логіка застосовна до нашої сітки зображень. Усі зображення мають розмір, рівний 0 (немає вмісту), тоді як наведене зображення сприяє розміру — навіть якщо це просто 1px — зробити свою комірку сітки більшою за інші. З цієї причини коефіцієнт масштабування може бути будь-яким значенням, більшим за 0 навіть десяткові коми між 0 та 1.

Щоб отримати остаточну ширину клітинок сітки, ми виконуємо той самий обчислення, щоб отримати наступне:

(container width) - (sum of all gaps) - (hovered image width) = (free space)

Ширина контейнера визначається:

var(--m)*var(--w) + (var(--m) - 1)*var(--g)

…і всі пропуски дорівнюють:

(var(--m) - 1)*var(--g)

…і для наведеного зображення ми маємо:

var(--w)*var(--f)

Ми можемо обчислити все це за допомогою наших змінних:

var(--m)*var(--w) - var(--w)*var(--f) = var(--w)*(var(--m) - var(--f))

Кількість стовпців визначається --m , тому ми ділимо цей вільний простір порівну, щоб отримати:

var(--w)*(var(--m) - var(--f))/var(--m)

…що дає нам розмір зображень без наведення. Для наведених зображень ми маємо це:

var(--w)*(var(--m) - var(--f))/var(--m) + var(--w)*var(--f)
var(--w)*((var(--m) - var(--f))/var(--m) + var(--f))

Якщо ми хочемо контролювати кінцевий розмір зображення, яке наведено, ми враховуємо наведену вище формулу, щоб отримати точний розмір, який ми хочемо. Якщо, наприклад, ми хочемо, щоб зображення було вдвічі більше:

(var(--m) - var(--f))/var(--m) + var(--f) = 2

Отже, значення нашого множника масштабу, --f, має дорівнювати:

var(--m)/(var(--m) - 1)

За три стовпчики матимемо 3/2 = 1.5 і це коефіцієнт масштабування, який я використовував у першій демонстрації цієї статті, тому що я хотів зробити зображення вдвічі більшим при наведенні!

Така ж логіка застосовується до обчислення висоти, і якщо ми хочемо керувати ними обома незалежно, нам потрібно буде врахувати два коефіцієнти масштабу, щоб переконатися, що ми маємо певну ширину та висоту при наведенні.

.gallery {
  /* same as before */
   --fw: 1.5; /* controls the scale factor for the width */
   --fh: 1.2; /* controls the scale factor for the height */

  /* same as before */
}

.gallery img:hover{
  width:  calc(var(--w)*var(--fw));
  height: calc(var(--h)*var(--fh));
}

Тепер ви знаєте всі секрети створення будь-якої сітки зображень із крутим ефектом наведення, а також контролюєте потрібний розмір за допомогою математики, яку ми щойно розглянули.

Підводячи підсумок

У моєму Остання стаття, ми створили складну на вигляд сітку з кількома рядками CSS, які використовують неявну сітку CSS Grid і функції автоматичного розміщення. У цій статті ми покладалися на певний трюк із розміром сітки CSS, щоб створити химерну сітку зображень, які збільшуються при наведенні курсора та викликають відповідне налаштування сітки. Усе це завдяки спрощеному коду, який легко налаштувати за допомогою змінних CSS!

У наступній статті ми пограємо з формами! Ми об’єднаємо CSS-сітку з маскою та кліпом, щоб отримати привабливу сітку зображень.

Часова мітка:

Більше від CSS-хитрощі