Як працює функція calc()

39

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

.foo {
width: calc(100px + 50px);
}

Чому calc()?

Якщо ви використовуєте препроцессоры типу SASS, приклад зверху вам має бути знайомий.

.foo {
width: 100px + 50px;
}
// Або з допомогою SASS змінних
$width-one: 100px;
$width-two: 50px;
.bar {
width: $width-one + $width-two;
}

Функція calc() краще з двох причин. По-перше, можна поєднувати різні одиниці виміру. Можна комбінувати відносні одиниці, такі як відсотки і vw, з абсолютними одиницями типу пікселів. Наприклад, можна написати вираз, в якому з процентного значення буде відніматися значення в пікселях.

.foo {
width: calc(100% — 50px);
}

У прикладі вище елемент .foo завжди буде на 50px вже 100% ширини його батька.

По-друге, в calc() обчислене значення є самим виразом, а не кінцевим значення виразу. При роботі з математичними виразами в CSS препроцессорах значення, передане в браузер, є кінцевим значенням виразу.

// Значення, задане в SCSS
.foo {
width: 100px + 50px;
}
// Скомпільований CSS і обчислене значення у браузері
.foo {
width: 150px;
}

А з функцією calc() значення, яке парс браузером, це сам вираз calc().

// Значення, задане в CSS
.foo {
width: calc(100% — 50px);
}
// Обчислене значення у браузері
.foo {
width: calc(100% — 50px);
}

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

Використання calc()

Функцію calc() можна використовувати для додавання, віднімання, множення і ділення числових значень властивостей. Її можна використовувати з типами даних length, frequency, angle, time, number та integer.

Пара прикладів:

.foo {
width: calc(50vmax + 3rem);
padding: calc(1vw + 1em);
transform: rotate( calc(1turn + 28deg) );
background: hsl(100, calc(3 * 20%), 40%);
font-size: calc(50vw / 3);
}

Вкладення calc()

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

.foo {
width: calc( 100% / calc(100px * 2) );
}

Обчислене значення цієї функції буде наступним:

.foo {
width: calc( 100% / (100px * 2) );
}

Створення фолбека

Функція calc() досить добре підтримується.

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

.foo {
width: 90%; /* Фолбек для старих браузерів */
width: calc(100% — 50px);
}

Коли можна використовувати calc()?

Функція calc() корисна в багатьох ситуаціях.

Приклад 1 – центрування елементів

Функція calc() дає нам ще один спосіб вирішення старої-старої проблеми з центруванням елементів по горизонталі і вертикалі всередині контейнера. Якщо нам відомі розміри дочірніх елементів, зазвичай можна використовувати негативні магдіп’и для зсуву елементів на половину висоти або ширини, ось так:

// Якщо розміри .foo складають 300px у висоту і завширшки 300px
.foo {
position: absolute
top: 50%;
left: 50%;
marging-top: -150px;
margin-left: -150px;
}

З допомогою calc() центрувати елемент можна лише з допомогою властивостей top і left.

.foo {
position: absolute
top: calc(50% — 150px);
left: calc(50% — 150px);
}

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

Приклад 2 – створення базового розміру сітки

З допомогою calc() можна створити сітку, подстраивающуюся під вьюпорт в rem одиницях. Це можна зробити, встановивши розмір шрифту кореневого елемента у вигляді дробу щодо ширини вьюпорта.

html {
font-size: calc(100vw / 30);
}

Тепер 1rem буде дорівнює 1/30 ширини вьюпорта. Будь-який текст на сторінці буде автоматично змінюватися разом з вьюпортом. На екрані завжди буде одне і те ж кількість тексту незалежно від розміру вьюпорта.

Як працює функція calc()

Якщо нетекстовым елементів на сторінці задати розміри в rem, вони будуть вести себе так само. Елемент шириною 1rem завжди буде займати 1/30 ширини вьюпорта.

Приклад 3 – ясність

Функцію calc() можна використовувати для спрощення обчислень, щоб вони були більш зрозумілими. Наприклад, якщо група елементів повинна займати 1/6 від ширини батьків, можна, звичайно, написати ось так:

.foo {
width: 16.666666667%;
}

Але набагато зрозуміліше буде, якщо записати код в такій формі:

.foo {
width: calc(100% / 6);
}

З calc() можна робити ще дуже багато чого, наприклад, можна створити систему сіток. Безумовно, це одна з корисних функцій в CSS.