en.javascript.info/8-css-for-js/14-height-percent/article.md
2015-03-12 10:26:02 +03:00

5.5 KiB
Raw Blame History

Особенности свойства "height" в %

Обычно свойство height, указанное в процентах, означает высоту относительно внешнего блока.

Однако, всё не так просто. Интересно, что для произвольного блочного элемента height в процентах работать не будет!

[cut]

Чтобы лучше понимать ситуацию, рассмотрим пример.

Пример

Наша цель -- получить вёрстку такого вида:

[iframe src="height-percent" height=160 link edit]

При этом блок с левой стрелкой должен быть отдельным элементом внутри контейнера.

Это удобно для интеграции с JavaScript, чтобы отлавливать на нём клики мыши.

То есть, HTML-код требуется такой:

<div class="container">
  <div class="toggler">
    <!-- стрелка влево при помощи CSS, ширина фиксирована -->
  </div>
  <div class="content">
    ...Текст...
  </div>
</div>

Как это реализовать? Подумайте перед тем, как читать дальше...

Придумали?... Если да -- продолжаем.

Есть разные варианты, но, возможно, вы решили сдвинуть .toggler влево, при помощи float:left (тем более что он фиксированной ширины) и увеличить до height: 100%, чтобы он занял всё пространство по вертикали.

Вы ещё не видите подвох? Смотрим внимательно, что будет происходить с height: 100%...

Демо height:100% + float:left

CSS:

.container { 
  border: 1px solid black;
}

.content {
  *!*/* margin-left нужен, так как слева от содержимого будет стрелка */*/!*
  margin-left: 35px;
}

.toggler {
  *!*/* Зададим размеры блока со стрелкой */*/!* 
  height: 100%;
  width: 30px;
  float: left;

  background: #EEE url("arrow_left.png") center center no-repeat;
  border-right: #AAA 1px solid;
  cursor: pointer;
}

А теперь -- посмотрим этот вариант в действии:

[iframe src="height-percent-float" height=160 link edit]

Как видно, блок со стрелкой вообще исчез! Куда же он подевался?

Ответ нам даст спецификация CSS 2.1 пункт 10.5.

"Если высота внешнего блока вычисляется по содержимому, то высота в % не работает, и заменяется на height:auto. Кроме случая, когда у элемента стоит position:absolute."

В нашем случае высота .container как раз определяется по содержимому, поэтому для .toggler проценты не действуют, а размер вычисляется как при height:auto.

Какая же она -- эта автоматическая высота? Вспоминаем, что обычно размеры float определяются по содержимому (10.3.5). А содержимого-то в .toggler нет, так что высота нулевая. Поэтому этот блок и не виден.

Если бы мы точно знали высоту внешнего блока и добавили её в CSS -- это решило бы проблему.

Например:

/*+ no-beautify */
.container {
  height: 200px; /* теперь height в % внутри будет работать */
}

Результат:

[iframe src="height-percent-float-exact" height="230" link edit]

...Но в данном случае этот путь неприемлем! Ведь мы не знаем, сколько будет текста и какой будет итоговая высота.

Поэтому решим задачу по-другому.

Правильно: height:100% + position:absolute

Проценты будут работать, если поставить .toggler свойство position: absolute и спозиционировать его в левом-верхнем углу .container (у которого сделать position:relative):

.container {
  *!*position: relative;*/!*
  border: 1px solid black;
}

.content {
  margin-left: 35px;
}

.toggler {
*!*
  position: absolute;
  left: 0;
  top: 0;
*/!*

  height: 100%;
  width: 30px;
  cursor: pointer;

  border-right: #AAA 1px solid; 
  background: #EEE url("arrow_left.png") center center no-repeat;
}

Результат:

[iframe src="height-percent" height=160 link edit]

Итого

  • Свойство `height`, указанное в %, работает только если для внешнего блока указана высота.
  • Стандарт CSS 2.1 предоставляет обход этой проблемы, отдельно указывая, что проценты работают при `position:absolute`. На практике это часто выручает.