Математика разметки с помощью CSS: разбираемся с calc

http://demosthenes.info/blog/953/Layout-Math-with-CSS-Understanding-calc
  • Перевод
За последние годы верстка в интернете развилась из фиксированных дизайнов к адаптивным. Причем, в стилях могут использоваться сразу несколько видов единиц измерений (проценты, em или px). Дизайнерам и разработчикам следует понимать, как это работает. Но было бы удобно оперировать (складыва/вычитать) единицами разной размерности в одном и том же выражении.

Для этого отлично подходит calc. При ее всей мощности, то, как ее можно применять, лучше продемонстрировать на примерах.

image

Vertical Flush Margins


Например, возьмем шикарную фотографию водопада от Stian Klo. Это изображение сдвинуто с отступом в 2rem вправо. Теперь его сделаем адаптивным, установив ширину в 50% от ширины родительского элемента:

<img src="" alt style="width:50%; margin-right: 2rem; float: left;"> <p>Det er et velkjent faktum...

Нам нужно, чтобы вертикальный зазор увеличивался, визуально подчеркивая изображение негативным пространством под ним. Проблема в том, что адаптивность абзацев означает, что они будут “ползать” под картинкой по мере сужения (link):

image

Есть много способов решить эту проблему, и одним из самых простых будет так, чтобы:

у абзацев рядом с картинкой был левый отступ 50% плюс 2rem.

Используя calc, это будет (link):

img ~ p { margin-left: calc(50% + 2rem); }


image

calc же позволяет комбинировать разные системы измерения, делая отсуп фиксированным, а картинку — адаптивной.

Full-Width Elements In Padded Containers


Рассмотрим следующий пример — полноширинный элемент (например, картинка) над контентом с внутренним отступом (padding):

<article>
<header>
<img src="" alt>
</header>
<p>Det er et velkjent faktum at lesere distraheres av lesbart innhold på en side når man ser på dens layout...
</article>

CSS:

* { box-sizing: border-box; }
body { background: #000; font-family: Edelsans, sans-serif; line-height: 1.5; }
article { width: 80%; margin: 0 auto; background: #fff; padding: 0 2rem; color: #000; }
article header img { width: 100%; height: auto; }

Проблема заключается в том, что padding элемента также смещает контент внутрь (link):

image

Это можно исправить путем вычисления ширины с помощью calc:

article header { width: calc(100% + 4rem); margin-left: -2rem; }

4rem, добавленные к ширине , создают -2rem-padding с левой и правой стороны для (link):

image

Операции


calc поддерживает основные арифметические операции (сложение (+), вычитание (-), умножение ( * ) и деление (/)). Важно помнить о том, что необходимо обрамлять операнды сложения и вычитания пробелами с двух сторон, а между calc и открывающей скобкой ничего не должно быть. Так что в такой форме это будет работать:

width: calc(20% - 1rem);

А это нет:

width: calc(20%-1rem);

И это также:

width: calc (20% - 1rem);

Тому есть простое объяснение: какое-либо число со знаком минус перед ним будет трактоваться, как отрицательное значение.

Возможности и ограничения


Все современные браузеры поддерживают calc для длины в CSS. Теоретически, calc может быть применим в любом месте, где встречаются операции с числами, что дает несколько интересных применений:

.box { background: rgba(255, 0, 0, calc(.3 * 2)); }


image

Или так:

.box { transform: rotate(calc(45deg - 2.31rad)); }


image

Но у всех браузеров есть подводные камни:
  • Chrome и Opera поддерживают все виды использования calc, но до Chrome 38 / Opera 25 вычисления углов не работают
  • На данный момент (ноябрь-декабрь 2014) Firefox поддерживает только вычисления длины и относительные величины (в процентах)
  • Safari / Mobile Safari: calc работает с 3D-трансформациями и вычислениями цветов, но что странно, это не прокатывает с двухмерными трансформациями
  • Android 4.4 поддерживает исключительно операции сложения и вычитания, в более ранних версиях calc не работает вообще. Chrome 38 на Android предлагает полноценную поддержку, как обычный десктопный браузер
  • Internet Explorer 9+ (десктоп/мобильный) достаточно хорошо поддерживает вычисления длины. К сожалению, IE9 падает, если calc используется в CSS-свойстве background-position

К счастью, бОльшая часть браузеров не требуют использовать vendor-префиксы.
Выражаю огромную благодарность Ana Tudor за проведение этих исследований; больше информации о поддержке calc браузерами вы можете найти на caniuse.com

calc так же может быть применяться для вычисления color stops в градиентах.

Заключение


Математически операции всегда были одним из преимуществ препроцессоров, как SASS. Сегодня они еще на шаг впереди, но функции, как calc, сокращают разрыв.
  • +21
  • 42,7k
  • 8
Поделиться публикацией

Похожие публикации

Комментарии 8

    0
    Интересная статья, очень неплохая с углами — для отрисовки красивых индикаторов, контроля каких-либо техпроцессов и математических вычислений — вариантов применений, помимо оформительских — мнгого. Единственное, о чем задумываюсь — не станут ли браузеры без плагинов тормозить больше, чем раньше «тормозили» браузеры с плагинами…
      0
      Что вы подразумеваете под плагинами? Flash, например?
        0
        Ну это же популярная фишка — винить Flash во всех грехах :) Рисую по 20 баннеров в месяц среднем, сам к таким заявлениям отношусь, как к мифологии, уж самые ярые противники могут отключить наглухо, а вот разухабистый не оптимизированный код на javascript уже сейчас может значительно тормозить браузер, а отключить это нельзя. Перенос разных рутинных вещей в движок может одновременно и замедлить и ускорить его работу, и пока что неизвестно, в какую сторону это сыграет — сейчас говорить рано, т.к. calc в разных интерпретациях пытаются внедрить, ЕМНИП, 10 лет, а до сих пор спецификация только перешла в RC только недавно — до полной поддержки тоже пока далековато
          0
          > Ну это же популярная фишка — винить Flash во всех грехах :)
          Когда я писал свой камент, то я думал про pollyfills.

          > а вот разухабистый не оптимизированный код на javascript уже сейчас может значительно тормозить
          Казалось бы, что такого в следовании нескольким правилам:

          1) нет анимации и большим вычислениям в обработчиках
          2) не нужен обработчик — сними его
          3) не забывай удалять ссылки на DOM-элементы

          > Перенос разных рутинных вещей в движок может одновременно и замедлить и ускорить его работу
          О, тут просто непаханое поле. Без реальных исследований сложно утверждать. А самое противное — это будет зависить от билда браузера.
      +3
      Что же веб технологии-то такие неуклюжие? Там пробел можно, там нельзя. Почему все языки решают эти проблемы, а в CSS не могут? Складывать можно, умножать нельзя. Для длин можно, для углов нельзя. Чёрт-те что, извините меня за прямоту. Ну сделайте, чтобы внутри calc было полноценное javascript выражение в нужном контектсе и всего делов. Всё равно все браузеры поддерживают JS, для JS давно есть все интерфейсы для работы с CSS.
      • НЛО прилетело и опубликовало эту надпись здесь
          0
          > Почему все языки решают эти проблемы, а в CSS не могут?
          Мне кажется, что люди для JS-движка и CSS-парсинга все такие разные.

          UPDATE:
          Отвечал на уровень выше.
            0
            В Netscape тоже было. Во-первых, там были JSSS, во-вторых, вычисляемые значения в атрибутах тегов, не помню точно, как-то долбанутый синтаксис был, типа «#{JS here}» или как-то так.

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое