Использование Calc() в CSS

22 января 2016
Дмитрий Кабаков, Senior Frontend Developer

Calc() — довольно старая, но, к сожалению, редко встречающаяся в реализации CSS3 функциональность.

Если коротко, эта функция позволяет выполнить простые математические вычисления прямо в стилях. Все, что нужно, — просто указать calc(выражение) как значение  свойства.

Поддерживаются операции: '+','-', '*', '/'

Кроме этого, функция понимает практически все единицы измерений, используемые в CSS, в том числе, и релятивные значения (vh, %, em).

За последние примерно пять лет поддержка этой функции появилась во всех последних браузерах. Поэтому проще перечислить, в каких браузерах она не работает: IE8 (частично IE9), Opera Mini, Android Browser (кроме последнего Chromium 44).

Примеры использования

Ниже хочу привести варианты использования calc() для решения наиболее распространенных проблем.

Выравнивание элемента по центру (вертикально)

Наиболее распространенная проблема. Есть множество решений, но никто не включил решение с помощью calc().

Пример: элемент высотой в 50 px нужно разместить по центру.

margin-top: calc( 50% - 25px );

See the Pen Calc() - Vertical align by Dmitriy (@Dmitriy-ateo) on CodePen.

Также с помощью функции calc() мы можем обойтись без отрицательных отступов для абсолютно позиционированных элементов. Т. е. если раньше мы писали

top: 50%;    margin-top: - 2em;    height: 4em;

...то с помощью функции calc() мы можем переписать следующим образом:

top: calc(50% - 2em);      height: 4em;

See the Pen Calc() - Centered elements by Dmitriy (@Dmitriy-ateo) on CodePen.

Резиновый контент и статические элементы

Есть задачи, когда нужно разместить статические элементы по краям, а остальное место оставить под контент. Конечно, это можно решить с помощью float и overflow, но, думаю, с помощью calc() будет гораздо проще.

Пример: элемент шириной 200 px разместить справа c отступом в 15 px, остальное — под контент.

width: calc(100% - 200px - 15px);

See the Pen Calc() - Fixed Sidebar by Dmitriy (@Dmitriy-ateo) on CodePen.

Недостаток — нужно учесть все размеры: ширина, отступы и т. п. Конечно, недостаток можно перекрыть с помощью SCSS.

Note: Для LESS функцию calc() нужно немного переписать:

width: calc(~"100% - 200px - 15px");

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

Чтобы разместить изображение у правого края, нужно знать размеры изображения и, конечно, отступ.

SCSS:

$img_height: 225px;    $img_width: 200px;    $img_padding: 15px;

background-position:         calc(100vw - #{$img_width} - #{$img_padding})        calc(100vh - #{$img_height} - #{$img_padding});

See the Pen Calc() - Background position by Dmitriy (@Dmitriy-ateo) on CodePen.

Примечание: Работает везде, кроме старых IE. Вы удивлены? Я — нет :).

Разметка страницы

С помощью функции calc() можно быстро создать простенькую разметку страницы, рассчитав размеры колонок в зависимости от их количества и отступов между ними.

Пример: Создать вспомогательные классы для создания колонок (максимум пять) с отступами в 15 px.

SCSS:

// Параметры:  $gutter:  15px !default;    $padding: 15px !default;  $columns: 5 !default;  $class-slug: col !default;  $number_of_gutters: $columns - 1;  $total_gutter_space: $gutter * $number_of_gutters;

// Создаем классы колонок    @for $i from 1 through $columns {      .#{$class-slug}-#{$i} {          float: left;          display: inline-block;                margin-left: $gutter;          padding: 0 $padding;          width: calc((100% - #{$total_gutter_space})/#{$columns} * #{$i} + (#{$i} - 1) * #{$gutter});      }    }

// Убираем отступ у первого элемента    [class*="col-"]:first-child {         margin-left: 0;    }

See the Pen Calc() - Dirty grid by Dmitriy (@Dmitriy-ateo) on CodePen.

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

Даже за время написания этой стать, функция calc() сохранила мне много времени и строк кода. Кроме того, код стал намного читабельнее.

Отрицательным моментом остается отсутствие поддержки IE. Но, если вы не собираетесь писать для IE8, можете использовать функцию без ограничений.

Все примеры можно посмотреть в коллекции на codepen.io: http://codepen.io/collection/noEKEm/.