Математичні функції CSS

11 хв. читання

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

calc()

Призначення calc(): базові математичні операції з можливістю інтерполяції між типами одиниць (наприклад, з rem у vw).

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

Наприклад, вам потрібно, щоб якийсь елемент займав більшу частину висоти вікна перегляду, якщо не враховувати висоти навігації. Для цього можна змішувати одиниці виміру, щоб передати відносну одиницю vh (висоту вікна перегляду) в абсолютну одиницю виміру піксель:

.content {
  height: calc(100vh - 60px);
}

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

Перевага calc() у тому, що ви можете уникнути захардкодженого діапазону магічних чисел, як і додавання JavaScript для обчислення значення, необхідного для його застосування як вбудованого стилю.

Застосовуємо calc() для генерування колірної палітри

Ми можемо розширити можливості calc(), передавши кастомні властивості CSS.

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

.colors {
  --base-hue: 140;
  --saturation: 95%;
  --lightness: 80%;
  --rotation: 60;

  color: #222;
  text-align: center;
}

.color {
  padding: 0.25rem;
  background-color: hsl(var(--hue), var(--saturation), var(--lightness));
}

.color1 {
  --hue: calc(var(--base-hue));
}

.color2 {
  --hue: calc(var(--base-hue) + var(--rotation));
}

.color3 {
  --hue: calc(var(--base-hue) + var(--rotation) * 2);
}
Математичні функції CSS

clamp()

Призначення clamp(): встановлення меж у діапазоні допустимих значень.

Функція clamp() приймає три значення, і їхній порядок важливий. Перше — це найменше значення у вашому діапазоні, середнє — ідеальне значення, а третє — найвище.

Ви могли натрапляти на clamp() у адаптивній верстці. Там важлива опція плавного регулювання кегля, де розмір шрифту залежить від розміру вікна перегляду. Так заголовки не збільшуються надмірно і не перекривають вміст.

Дуже базове визначення адаптивного стилю h1:

h1 {
  font-size: clamp(1.75rem, 4vw + 1rem, 3rem);
}

Докладніше про генерування адаптивних типів у Modern CSS episode 12 (англійською).

Створюємо відносний адаптивний відступ за допомогою clamp()

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

У прикладі зі SmolCSS відступ буде збільшуватись і зменшуватися відносно ширини елемента. Він ніколи не буде меншим за 1rem і не перевищуватиме 3rem:

.element {
  padding: 1.5rem clamp(1rem, 5%, 3rem);
}

Завдяки цьому знову зникає потреба у сценаріях, для яких ви, можливо, раніше застосовували медіазапити. Замість мікрокерування цим інтервалом або турбот про суворе дотримання піксельної градації (наприклад, 8, 12, 24, 36), ви можете встановити розумні вказівки для адаптивного перетворення.

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

min()

Призначення min(): встановлення меж максимально допустимого значення, щоб воно реагувало на адаптивний контекст елемента.

Саме так, хоч це і функція min(), отримані значення властивості будуть максимально дозволеними.

Приміром, маємо width: min(80ch, 100vw). У результаті в більшому вікні перегляду буде вибрано 80ch, оскільки це менше значення з двох варіантів, але воно буде максимумом в цьому просторі. Тільки-но вікно перегляду зменшиться, буде застосовано 100vw, оскільки воно обчислюється меншим, ніж 80ch, але насправді воно забезпечує максимальну межу для ширини елемента.

Клас .container у сучасному CSS

Наведений приклад — простий спосіб визначити .container, але з однією крихітною поправкою. Функція min() дає змогу вкладати основні математичні операції. А це означає, що ми можемо перейти до віднімання певного простору як заміни для визначення відступу ліворуч та праворуч, ось так:

.container {
  width: min(80ch, 100vw - 2rem);
}

Якщо вікно перегляду більше, елемент може збільшитися максимум до 80ch. Щойно вікно перегляду стане вужчим, йому буде дозволено вирости до 100vw - 2rem. Це визначення ефективно створює 1rem відступу обабіч елемента.

У цьому прикладі ви також можете підставити 100% замість vw, щоб ширина елемента відповідала ширині батьківського контейнера, як це зроблено для цієї демонстрації:

.container {
  width: min(40ch, 100% - 2rem);
  margin-right: auto;
  margin-left: auto;
}
Математичні функції CSS

Примітка: одиниця виміру ch дорівнює ширині символу 0, з урахуванням всіх поточних властивостей font на момент його застосування. Це робить його чудовим вибором для приблизного визначення довжини рядка (наприклад, заради зручнішого читання).

Які ж переваги? Адаптивний розмір без застосування медіазапитів! Схоже, це спільна тема для наших функцій 😉.

Тепер розгляньмо ще деякі дивовижні оновлення практичних сценаріїв.

Створюємо адаптивний розмір елемента за допомогою min()

Якщо ви хочете, щоб елемент змінював розмір адаптивно, зверніть увагу на функціїю min (). Її можна використати, наприклад, для налаштування розмірів аватара у стрічці коментарів.

У прикладі з аватаром ми застосували три значення з різними одиницями виміру: min(64px, 15%, 10vw). Тобто розмір аватара не перевищуватиме жодне з цих значень у будь-який час, а браузер обиратиме мінімальне обчислене значення.

Це визначення працює так, щоб ніколи не з'являвся аватар розміром понад 64px. 10vw допомагає розміру бути відносним, особливо для масштабування. А 15% допомагають зберегти розмір відносно елемента, що створює приємніший візуальний результат до застосування 10vw.

min() в інших властивостях

Математичні функції CSS можна використовувати у більшості властивостей, які допускають числові значення. Одне унікальне місце для їх застосування — це background-size.

Чому? Уявімо, що ви створюєте ефект багатошаровості кольору тла та зображення. І замість вжити значення розміру cover, яке заповнить увесь простір зображенням, ви хотіли б обмежити збільшення зображення. Це ідеальне місце, щоб додати min().

Розглянемо приклад, де min() не дає зображенню перевищити розмір 600px. Разом з тим йому дозволено відповідати розміру елемента, оскільки другим обмежувальним значенням встановлено 100%. Іншими словами, воно збільшиться до 600px, а потім змінить свій розмір відповідно до ширини елемента, якщо він буде меншим за 600px.

.background-image {
  background: #1F1B1C url(https://source.unsplash.com/RapCPd_mJTU/800x800) no-repeat center;
  background-size: min(600px, 100%);
}
Математичні функції CSS

max()

Призначення max(): встановлення меж мінімально допустимого значення, щоб воно реагувало на адаптивний контекст елемента.

Так, max() є протилежністю min()! Тож зараз ми встановлюємо визначення мінімально допустимих значень. Перейдімо безпосередньо до прикладів.

Створюємо контекстні поля за допомогою max()

У критеріях доступності вебвмісту (WCAG) 1.4.10 зазначено, що користувач повинен мати можливість масштабувати сайт до 400%. Примітно, що пікселі та rem не впораються з цим завданням без деяких хитрощів.

Візьмемо розмір стільниці 1280px за масштабу 400%. Ваш вміст матиме вигляд, як на пристрої з роздільністю 320 пікселів. Однак, на відміну від мобільного телефону, орієнтація альбомна. Вікно перегляду такого розміру означає значно зменшену область для читання та виконання дій. Крім того, розміри, які здавалися доречними для телефону, стають завеликими у збільшеному вікні.

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

.element + .element {
  margin-top: max(8vh, 2rem);
}

У вищих вікнах перегляду буде застосовано 8vh, а в менших або збільшених вікнах перегляду — 2rem. Радимо вам спробувати це і витратити деякий час на тестування з різними вікнами перегляду, пристроями, а також з масштабуванням макета та без нього. Ця техніка є невеликим оновленням, яке може значно вплинути на комфорт кінцевого користувача.

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

Запобігаємо масштабуванню форм у браузері на iOS за допомогою max()

Ви коли-небудь стикалися з примусовим масштабуванням браузера після того, як фокус перейшов на поле введення на iOS? Цей станеться з будь-яким полем введення, шрифт у якому менший за 16px.

Ось приклад простого виправлення цієї проблеми, описаний у статті Дена Бурзо:

input {
  font-size: max(16px, 1rem);
}

1rem можна замінити змінною Sass або кастомною властивістю CSS. Застосування max() гарантує, що font-size буде щонайменше 16px — незалежно від іншого наданого значення. Отже, ми уникнемо примусового масштабування в браузері.

Створюємо відносні контури фокусування за допомогою max()

Ще одне доповнення до скидання деяких стилів — використання min() заради відносного розміру контурів фокусування.

Це скорочений фрагмент, але з max() ми гарантуємо мінімальний розмір контуру буде 2px. Тож він зростатиме відносно елемента, використовуючи пов'язане зі шрифтом значення em.

a {
  --outline-size: max(2px, 0.08em);
  --outline-style: solid;
  --outline-color: currentColor;
}

a:focus {
  outline: var(--outline-size) var(--outline-style) var(--outline-color);
  outline-offset: var(--outline-size);
}

Доступні цільові розміри за допомогою max()

Термін «цільовий розмір» походить із WCAG Success Criterion (SC) 2.5.5, де «ціль» означає ділянку, на якій відбувається подія вказівника (наприклад, клацання мишею або торкання). У прийдешній WCAG 2.2 буде «розширена» версія — і SC 2.5.5 матиме мінімальний розмір 44px.

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

У цих випадках ми можемо застосовувати max() так само, як і для уникнення масштабування полів. Ми встановимо 44px одним зі значень у max(), щоб це був мінімальний розмір елемента.

.icon-button {
  width: max(44px, 2em);
  height: max(44px, 2em);
}

Зауважте, що ця умова також враховує простір навколо елемента, який у поєднанні з фактичним розміром елемента становить щонайменше 44px. Як і з усіма цими методами, не забудьте все протестувати заздалегідь: на справжньому продукті й на справжніх користувачах. Результат їм сподобається!

Застосовуємо max() як резервний варіант для aspect-ratio

Інший спосіб використати max() — це встановити висоту зображення, коли ми застосовуємо aspect-ratio, щоб досягти прийнятної роботи у браузерах, які ще не підтримують цю властивість.

Ви можете переглянути роботу наведеного прикладу у презентації про SmolCSS для компонента складуваної картки.

img {
  /* Запасний варіант `aspect-ratio` для визначення висоти */
  height: max(18vh, 12rem);
  object-fit: cover;
  width: 100%;
}

/* Якщо підтримується, використовувати `aspect-ratio` */
@supports (aspect-ratio: 1) {
  img {
    aspect-ratio: var(--img-ratio);
    height: auto;
  }
}

Поєднаймо все до купи

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

Більше статей про CSS можна знайти за відповідним гештегом 🙂.

Помітили помилку? Повідомте автору, для цього достатньо виділити текст з помилкою та натиснути Ctrl+Enter
Codeguida 5.8K
Приєднався: 8 місяців тому
Коментарі (0)

    Ще немає коментарів

Щоб залишити коментар необхідно авторизуватися.

Вхід / Реєстрація