calc()
довольно новая и еще совсем редко используемая функциональность в CSS3. Она позволяет задавать несложные арифметические операции непосредственно в описании стилей с участием всевозможных единиц измерения. Это очень удобно для вычисления размеров, позиций, трансформаций.. и даже цветов элементов. Давайте разберемся, где все это может пригодиться и стоит ли это того.
Синтаксис css calc
сalc()
позволяет осуществлять простые математические операции:
- сложение
+
- вычитание
-
- умножение
*
- деление
/
и использовать результат вычисления в качестве значений для задания
- размеров
cm
,mm
,in
,pt
,pc
,px
- частот
Hz
,kHz
- углов
deg
,grad
,rad
,turn
- времени
s
,ms
- или любых простых численных значений, используемых в CSS
Все вычисления осуществляются с соблюдением стандартных правил приоритета операторов.
Для понимания синтаксиса приведем несколько примеров:
CSS
width: calc(70%/3);
width: calc(50% - 2em);
width: calc((50% + 2em) / 2 + 14px);
width: calc(100% / 3 - 2 * 1em - 2 * 1px);
margin: calc(1rem - 2px) calc(1rem - 1px);
background-position: calc(50% + 20px) calc(50% + 20px), 50% 50%;
background-image: linear-gradient(to right, silver, white 50px, white calc(100% - 50px), silver);
Поддержка браузерами и префиксы
На текущий момент (07.2013) calc
поддерживается всеми десктопными браузерами, включая IE9! Из мобильных браузеров, есть проблемы в опере и андройд браузере.
Мобильный и десктопный сафари, а также блекбери нуждаются в префиксах. Можно еще поставить префикс для opera mini на случай, если в ней это когда-нибудь заработает.
CSS
width: -webkit-calc(70% - 20px);
width: -o-calc(70% - 20px);
width: calc(70% - 20px);
подробную и актуальную информацию о текущей поддержке браузерами всегда можно найти тут
Как css calc может облегчить жизнь при верстке?
Создание любой верстки для веб приложений всегда начинается с назначения размеров и расположения всех основных элементов. При этом, в зависимости от задач проекта и особенностей дизайна, могут использоваться различные сочетания всех единиц измерения (%, px, em, rem). calc
позволяет элегантно решать проблемы комбинирования фиксированных и «резиновых» блоков, взаимного расположения абсолютно спозиционированных и/или плавающих элементов, задания размеров без длинных бесконечных дробей (а-ля «42.857142857%») и многое другое.
Самая типовая задача при верстке на сегодняшний день имеет следующие требования:
- часть элементов должны быть «резиновыми», т.е. заданы в процентах от ширины или высоты (обычно это основной контент)
- часть элементов должны быть фиксированной ширины (в зависимости от требований, это могут быть блоки рекламы, меню, банеры, боковые колонки и т.п.).
- расстояние между блоками может быть как фиксированным (px, em, rem), так и относительным (%)
Давайте рассмотрим несколько примеров:
- Пример 1. Верстка в 2 колонки, обе колонки резиновые по ширине. Левая 70%, правая 30%. Между колонками должно быть некоторое расстояние.
- Пример 2. Верстка в 2 колонки, обе колонки резиновые по ширине. Левая 70%, правая 30%. Между колонками должно быть фиксированное расстояние в 20px
- Пример 3. Верстка в 2 колонки, правая колонка имеет фиксированную ширину 200px, левая занимает все оставшееся пространство. Между колонками должно быть фиксированное расстояние в 20px
- Пример 4. Верстка в 3 колонки, правая и левая колонки имеют фиксированную ширину 150px, центральная занимает все оставшееся пространство. Между колонками должно быть фиксированное расстояние в 20px
Без calc
все примеры, кроме первого, потребуют от Вас создания некоторых вложенных контейнеров, дополнительных margin и padding, float-ов и т.п.
А вот как просто все становится с использованием CSS calc()
HTML (упрощено для понимания)
<section class="example1">
<p>...</p>
<div class="content">...</div
><div class="sidebar">...</div>
</section>
<section class="example2">
<p>...</p>
<div class="content">...</div
><div class="sidebar">...</div>
</section>
<section class="example3">
<p>...</p>
<div class="content">...</div
><div class="sidebar">...</div>
</section>
<section class="example4">
<p>...</p>
<div class="nav">...</div
><div class="content">...</div
><div class="sidebar">...</div>
</section>
CSS
/* EXAMPLE 1 */
.example1 .content {
width: 68%;
margin-right: 1%;
}
.example1 .sidebar {
width: 30%;
margin-left: 1%;
}
/* EXAMPLE 2 */
.example2 .content {
width: -webkit-calc(70% - 20px);
width: -o-calc(70% - 20px);
width: calc(70% - 20px);
}
.example2 .sidebar {
width: 30%;
margin-left: 20px;
}
/* EXAMPLE 3 */
.example3 .content {
width: -webkit-calc(100% - 200px - 20px);
width: -o-calc(100% - 200px - 20px);
width: calc(100% - 200px - 20px);
}
.example3 .sidebar {
width: 200px;
margin-left: 20px;
}
/* EXAMPLE 4 */
.example4 .content {
width: -webkit-calc(100% - 300px - 20px - 20px);
width: -o-calc(100% - 300px - 20px - 20px);
width: calc(100% - 300px - 20px - 20px);
}
.example4 .nav {
width: 150px;
margin-right: 20px;
}
.example4 .sidebar {
width: 150px;
margin-left: 20px;
}
Красивая запись бесконечных дробей с CSS calc
Рассмотрим типовой пример, когда в CSS не обойтись без некрасивых псевдо-бесконечных дробных чисел.
Допустим, у нас есть 7 inline-block кнопок, которые нужно расположить в один ряд так, чтобы в итоге они занимали всю предоставленную ширину.
Как вы уже поняли, ширина каждой кнопки составит в процентах 100/7 = 14.2857142857
и в CSS это будет выглядеть так:
CSS
.button{
// попробуй разберись почему
width:14.2857142857%;
};
Используя css calc
, то же самое можно записать красиво и понятно:
CSS
.button{
// все понятно
width: calc(100% / 7);
};
Пробелы в выражениях CSS calc
Пожалуйста, обратите внимание на то, что пробелы calc(100% - 300px - 20px - 20px);
по обе стороны от математических операторов обязательны.
Возможные проблемы
В Safari 6 (десктоп) и мобильном Safari (iOS6) при совместном использовании CSS calc и CSS transitions в некоторых случаях случается полный крэш браузера. И это можно обойти только с помощью магии, да и то не всегда.
Что дальше?
Пробуйте. Пишите в комментариях все, что Вы об этом думаете. Для любознательных вот тут можно найти спецификацию.
Круто, не знал, спасибо. На http://css3please.com/ такого не нашел.
О вас узнал только по ссылке с хабра
Круто! Не знал что уже всеми браузерами поддерживается..
весьма спорно надо ли оно?
обойтись можно..а создавать мамематику в css, зачём?
в стилях все должно быть просто и статично, математикой пусть занимается js
А аппаратным ускорением тоже джаваскрипт будет заниматься? Цсс transitions этим и лучше, в частности. Сейас уже нету четкой границы, где кончается понятие «стиль» и начинается понятие «скриптовая логика».
:hover — это тоже поведение, причем этому псевдоклассу уже много-много лет. И как-то никому в голову не приходит вместо него использовать скрипты.
Не путай дикларативные и императивные языки Вася. CSS декларативный и вычислениям тут не место, для подобных версток придумали flex. Чувак прав calс() не православный.
прав/не прав, а это удобно. порядок нужен для удобства выполнения задачи, а не наоборот. элементарная математика нужна в CSS.
Поддержка браузерами и префиксы: поддерживается всеми десктопными браузерами, включая IE9!
Что-то caniuse считает иначе
Да и с развитием препроцессоров это свойство становится ненужным
1) Что по вашему сaniuse считает не так?
2) Препроцессоры тут воообще не причем, вы не совсем поняли для чего сужен calc() :)
Например, он считает, что IE 9-10 не держит данное свойство, в отличае от автора статьи, который утверждает обратное.
А с препроцессорами — да, пример неудачный
Не мог понять почему в IDE
width: calc(100% - 6px);
дает в браузереwidth: calc(94%)
пока не стал править css руками, а не посредством less. Вопрос: как это написать средствами less? Ибо от less из-за calc() отказываться не хочется.Не долгий поиск в интернете привел на оверфлоу. Запись для less:
width: calc(~"100% - 6px");
cacl() неплохо поддерживается сейчас, это да. Но столкнулась с проблемами иного рода.
LESS пытается высчитать значения в скобках так, как он это умеет. В результате выходят абсолютно не те числа. С этим ладно, разобрались. Заэкраноровали и все.
А тут еще проблема — при компрессинге убираются некоторые пробелы (calc(100% + 10px) —> calc(100%+10px) ), а форма эта уже невалидна и браузер не понимает.