Конспект JS-course

Раскладка в CSS: поток

Источник: http://softwaremaniacs.org/blog/2005/08/27/css-layout-flow/

Статья написана 27.08.2005, однако как сказал Антон Шевчук, автор блога http://anton.shevchuk.name/ , пусть вас не смущают даты написания статей – они повествуют об основах и актуальность они не потеряют ещё очень долго.

Прямой поток - тот порядок, в котором располагаются боксы, если им не давать какого-то специального позиционирования.

Типы боксов

Боксы, участвующие в потоке, бывают двух принципиально разных типов: строчные и блочные ("inline" и "block" в терминлогии CSS).

Строчные боксы, как следует из названия, это все то, что раскладывается друг за другом в строки и переносится на следующие строки, когда не хватает ширины. К ним относится обычный текст, теги, отвечающие за оформление текста, такие как <b>, <i>, <code>, а также картинки. Строчные боксы могу также содержать в себе другие строчные боксы. Вот пример набора строчных боксов:

Это пример длинного текста, в котором встречаются <em>всяческие
<dfn>теги</dfn></em>, которые, тем не менее, <strong>нисколько 
не нарушают</strong> его плавного течения с переносами на 
следующие строки...

Кстати, те части, которые не обрамлены никаким тегами объединяются в так называемые безымянные строчные боксы ("anonymous inline box").

Важным свойством строчных боксов является то, что у них есть свой собственный размер. Он складывается из размера шрифта (для букв), собственных размеров картинок, расстояния между строками. Это означает, что браузер при раскладке строчных боксов определяет их размер сам, без указания всяких width и height.

Еще одна особенность - это то, что для строчных боксов не работают верхние и нижние границы и отступы. Это не так уж и странно, если учесть, что из-за переноса строк четких понятий "верх" и "низ" уже нет.

Блочные боксы (или просто "блоки") - это прямоугольники, которые занимают по ширине все доступное им место и никуда не переносятся. А вот собственной высоты они не имеют. Их размер по высоте определяется теми боксами, которые они содержат в себе. И это - содержание в себе других боксов - их основная задача. Содержать в себе они могут и строчные боксы, и блочные.

<body>
  Какой-нибудь текст в начале.
  <h1>Заголовок</h1>
  <p>Абзац текста</p>
</body>

Здесь блочные боксы &lt;h1&gt; и &lt;p&gt; содержат в себе строчные боксы с текстом, а сами входят в другой блочный бокс, заданный тегом &lt;body&gt;.

Вообще, технически, если внутри блока сидят и строчные, и блочные боксы вперемешку, то все строчные объединяются в безымянные блочные боксы ("anonymous block box"). В предыдущем примере текст до заголовка как раз заключается в такой безымянный блочный бокс.

Расположение боксов

Поток задает довольно жесткое поведение боксов, поэтому как-то вольготно их располагать, в общем-то, и нельзя. Что с ними можно делать - так это выравнивать по горизонтали.

Проще всего с этим обстоят дела у строчных боксов. Для них существует специальное свойство - text-align, котрое бывает left, right и center. Единственное, что надо помнить, оно задается не для самих строчных боксов, а для того блока, в котором они лежат.

С блочными боксами все слегка сложнее. Первое, с чем надо разобраться - это ширина. Особенностью (полезной особенностью!) блочных боксов в прямом потоке состоит в том, что если ширина не задана явно, то она расчитывается автоматически так, чтобы бокс в точности уместился в ширину своего родителя вместе с отступами, рамками и границами. Это не то же самое, что задание ширины в 100% - тогда при наличии отступов, рамок или границ он за пределы родителя вылезет.

Из этого же следует, что выравнивание блочного бокса по горизонтали без указания ширины не имеет смысла: он и так занимает все пространство. А вот если ширину четко указать, и она будет меньше, чем ширина родителя, то тогда блочный бокс уже может выравниваться. Делается это, как ни странно, с помощью задания левой и правой границ (margin'ов):

То есть, принцип такой: установка боковой границы в auto отлепляет бокс от соответствующего края и прилепляет к противоположному, если в auto стоят обе границы - бокс выравнивается по центру. Если же ни одна из боковых границ не стоит в auto, то бокс выравнивается к тому краю, с которого идет текст в текущем языке (то есть, у нас - слева, а в арабском - справа).

Вертикальное выравнивание

Раз уж зашла речь о выравнивании, скажу и о вертикальном. Это одна из тех немногих вещей, с которой в CSS совсем плохо. Говоря по-простому, какого-то одного вменяемого механизма, да еще и работающего в большинстве браузеров, просто не существует. Существуют способы обходить этот недостаток, причем нет ни одного универсального - все с каким-то условиями. Я, видимо, остановлюсь на этом больном вопросе в отдельной статье, а нетерпеливым пока вот - по-английски.

Управление типами боксов

Тип боксов, создаваемых элементами HTML, опредеяется ими самими. Например, &lt;p&gt;, &lt;h1&gt;, &lt;pre&gt;, &lt;ul&gt;, &lt;div&gt; - это блочные элементы, а &lt;b&gt;, &lt;i&gt;, &lt;span&gt; - строчные. По сути же все это подчиняется обычной логике: стилевое оформление фраз - строчные элементы, а основные блоки текста - они блоки и есть. Блоки содержат строки, но не наоборот.

Однако, CSS'ом это поведение можно свободно менять. Для этого служит свойство display.

У него есть значения, которые придают любым элементами поведение таблиц. Есть значения, имитирующие отображения элементов списков, которые создают два бокса: отдельно для текста и отдельно для значочка. И есть еще экзотика типа run-in и compact, которые работают то как блочные, то как строчные, в зависимости от окружающего контекста. Но все это либо не поддерживается многими браузерами, либо не очень ценно практически.

Остаются три очевидных и наиболее часто используемых значения: inline и block, котрые могут из любого элемента сделать строчный и блочный соответственно, а также none, который полностью устраняет элемент из отображения вместе со всеми вложенными в него другими элементами.

Таким образом, если у нас есть такой HTML:

<p>Текст с <strong>выделенным</strong> текстом внутри.</p>

... и такой CSS:

strong {
  display:block;
}

То выделенный текст вылезет из строки и начнет занимать отдельное место по вертикали:

Аналогично, можно сделать и наоборот. HTML:

<h1>Заголовок</h1>
<p>Абзац текста.</p>

CSS:

h1,p {
  display:inline;
}

И заголовок с абзацем выложены в одну строчку:

Это, в частности, широко используется для таких вещей, как раскладывание главного меню сайта, заданного с помощью списка (&lt;ul&gt;) в виде горизонтальной строки.

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