Немного о calc()
Рассмотрим пример:
<div></div>
<style>
div {
height: calc(-14px);
}
</style>
Подробно поведение браузера можно посмотреть в этом
пэне. Здесь же ограничимся информацией о том, что эта декларации валидная и Used value высота для блока
будет
0px
.
Почему отрицательное значение может быть валидно для высоты?
Потому что calc()
наследуется в вычисленном не до конца виде.
Computed value - это значение,
которое вложенные блоки наследуют как inherit
. На этом этапе значения в относительных единицах
(em, ex, vh, vw, но не проценты) приводятся к пикселям. Это утверждение относится и к
значениям, содержащим calc()
или другие функции.
Например:
height: calc(50% - 25px); /* => CV=calc(50% - 25px) */
height: calc(100px - 5em); /* => CV=calc(50px) */
Рассмотрим пример с вложенными блоками, объясняющий зачем это нужно:
<div class="a"> // 100px
<div class="b"> // 60px
<div class="c"> // 20px
<div class="d"></div> //0px
</div>
</div>
</div>
<style>
.a { height: 100px; }
.b { height: calc(100% - 40px); } /* => CV=calc(100% - 40px) */
.c { height: inherit; } /* => CV=calc(100% - 40px) */
.d { height: inherit; } /* => CV=calc(100% - 40px) */
</style>
Для каждого блока выражение вычисляется заново и для блока .d
вычисление наследованного
выражение дает отрицательное значение. НО! Во время вычисления used value
для функий проводится
Range Checking
.
Проверка диапазона во время синтаксического анализа не выполняется для математических функциях, и поэтому значения вне диапазона не приводят к тому, что декларация становится невалидной. Однако значение свойства все же должно быть ограничено диапазоном, разрешенным в целевом контексте.
Range Checking
выполняется на этапе computed value
, если это возможно (то есть если
выражение не содержит процентов и возможно вычисление для пикселей), и на этапе used value
во
всех остальных случаях.
Проще говоря, если вычисленное значение не может быть применено в целевом контексте, то оно приводится к ближайшей границе допустимого диапазона.