Два в одном: позиция + размеры

Автор: Александр Головко Дата публикации: 15.10.2010

Задача

Расположить блок так чтоб он имел отступы слева, справа, сверху 20px и занимал высоту 50% родителя.

иллюстрация к задаче

Если высота родителя неизвестна, то задачка стает очень нетривиальной. Ведь в CSS2, к сожалению, нельзя написать такие правила (ждем с нетерпением CSS3 и функцию calc):

.box{
	height: 50% - 20px;  /* Эх! Ну почему так писать нельзя?! */
	width: 100% - 40px;
}

Очень не многие знают, что оказывается для блоков с абсолютным (или фиксированным) позиционированием (position:absolute/fixed) уже сейчас так написать можно! Вернее, конечно, не прямо так, с точки зрения синтаксиса, но именно так, с точки зрения результата.

Решение

Секрет фокуса в том, что блок с абсолютным позиционированием для нормального отображения требует задания размеров. Так вот, размеры для него можно задать не только с помощью width и height, но и с помощью одновременного использования свойств left/right или top/bottom!

.box{
	position:absolute;
	top:20px;  
	bottom: 50%; /* 20 пискелей отступаем сверху от родителя, 50% снизу, а все остальное - высота блока! */
 	right: 20px;
	left: 20px; /* 20 пискелей отступаем слева от родителя, 20 справа, а все остальное - ширина блока! */
}

— Эй! А как же старый осел?

Ну конечно! Я уже думал, никто так и не спросит! Да-да, IE6 этот трюк выполнить отказывается. Старый уже, ноги болят, не до фокусов, знаете ли.

Костыли в студию!

* html .box{
	height: expression( parentNode.offsetHeight/2 - 20 + 'px');
	width: expression( parentNode.offsetWidth - 40 + 'px');
}

Поскольку от левого и правого края мы отступаем по 20px, то ширину блока задаем на 40px меньше, чем у родителя. Высоту рассчитываем, как половина высоты родителя минус отступ сверху.

Само собой в боевых условиях вместо хаков создаем отдельный CSS, который подключаем условным комментарием.

Конечно, это достаточно жесткий костыль, так как нет оптимизации expression. Тем не менее, учитывая все слабеющие позиции IE6, на это можно закрыть глаза.

При желании, для статичных по размерам родителей можно добавить оптимизацию (для примера устанавливаем только высоту):

* html .box{
z-index: expression( /* оптимизированный expression, который сработает только при загрузке страницы */
runtimeStyle.zIndex = 1,
runtimeStyle.height = parentNode.offsetHeight/2 - 20 + 'px');
}

Немного различных примеров. Проверено в:

Где это можно применять

Поскольку рассмотренная выше задача довольно абстрактна, возникает естественный вопрос, где же этот прием можно применить?

Существенное ограничение на позиционируемый блок — необходимость устанавливать для него position:absolute/fixed — во многом определило область применения. Очень удобно таким образом задавать какие либо декоративные элементы, например, какой-нибудь бэкграунд для резинового сайта с боковыми фиксированными декорированными границами. Или тянущуюся фоновую картинку для резинового окошка.

полупрозрачный уголок не перекрывает границ Высота боковушки — все доступное пространство, с отступом сверху и снизу на высоту уголков.

Выводы

Таким образом, с помощью позиционирования можно косвенно указать размер блока (причем такой размер, который напрямую и не укажешь!). Фокус работает только для блоков с position:absolute/fixed и тебует expression для IE6. Кроме того, родитель блока должен быть relative, что не всегда удобно. Конечно, область применения данного трюка очень ограничена, но в некоторых ситуациях его знание может сэкономить массу времени и нервов.