В предыдущей статье я уже пару раз помянул прямой поток - тот порядок, в котором располагаются боксы, если им не давать какого-то специального позиционирования. И порядок этот, надо сказать, не такой уж и простой.

Типы боксов

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

margin-right:auto - выравнивание влево, margin-left:auto - вправо, margin-left:auto и margin-right:auto - по центру

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

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

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

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

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

Однако, 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;
}

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

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

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


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

Комментарии: 43

  1. Зверёк Харьковский

    Иван, маленькое замечание со стороны: тексты этого цикла у Вас отличаются какой-то совершенно зверской, нечеловеческой полезностью :) Вообще-то, это надо бы студентам рассказывать :)

  2. Boris

    C большим удовольствием читаю этот блог и данный учебник. Систематизированный материал, это весьма полезно, даже если в основном все это уже знаешь на собственных набитых шишках.
    Спасибо.

  3. Иван Сагалаев

    Спасибо за комментарии.

    Систематизированность и "чтобы студентам можно было читать" - это очень важные вещи, которые я держу в голове, когда пишу это. Раз это заметно и остальным, значит задуманное выходит правильно :-).

  4. Mic

    Не хватало информации когда использовать span, a когда div. Теперь все встало на свои места. Большое спасибо!

  5. Студент

    Очень полезные статьи. Пишите пожалуйста еще. Однозначно в закладки.

  6. Alex

    Чертовски интересно, увлекательно и понятно написано, но...

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

    И вот читаю я сейчас ваши материалы, любуюсь чистым кодом, ломаю голову над css-файлом и делаю попытку взглянуть на данную станицу "глазами" разных броузеров. И что же вижу??? Похоже, только IE показывает ваши страницы так, как задумано. Opera - тоже терпимо, но уже теряются оформительские элементы. А набирающий популярность (судя по логам моего сайта) FireFox извратил все до неузнаваемости - страница представлена... как это по-вашему... "прямой поток" - забавно. Кроме ... ничего не осталось, а меню в самом неожиданном, наверное, для вас (да и для посетителей) месте. Хотя плюс в том, что вся информация все же осталась... в том виде, в каком его показывали текстовые броузеры на заре интернет-становления.

    Все так здорово начиналось в теории ваших статей и все так плачевно закончилось на практике.

    Мы не сможем заставить программистов написать такой броузер, чтобы он в совершенстве поддерживал CSS, да и не сможем заставить всех пользователей перейти на них, если такое чудо вдруг случится. Получается, что только для собстенного удовлетворения и стоит верстать с помощью css.Очень печально все это.

  7. Alex

    Дико извиняюсь! Первый пост писал, когда смотрел в офф-лайне - была диская жуть, а сейчас и с Firefox'om все хорошо. И даже, как оказалось, видно больше, нежели в IE.

  8. Иван Сагалаев

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

    Теперь по сути. Я бы сказал, что сейчас ситуация с поддержкой CSS'а браузерами куда как определенней, чем во времена IE4 и NN4. Проблемы обычно возникают у дизайнеров, которые пользуются навыками старой школы верстки. Я, как и обещал уже раньше, обязательно напишу про практическую сторону. И про поддержку в браузерах и про понятие "выглядит одинаково" и т.д. Но я намеренно хочу это сделать после теории про раскладку, чтобы было, на что ссылаться. Так что, потерпите еще чуток :-). К сожалению, у меня не все время уходит только на эти статьи...

  9. Иван Сагалаев

    Сегодня получил одно письмо от читателя, по которому понял, что не совсем ясно выразился про выравнивание строчных боксов и то, куда применяется text-align. Разъясняю подробней.

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

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

    Поэтому для выравнивания строк нужны два элемента: блочный бокс и строчные боксы, которые в нем лежат. И свойство text-align назначается именно родительскому блочному боксу.

    То есть, когда мы пишем:

    p {     text-align:center;   }

    Это означает "внутри блочного бокса <p> выравнивать строчные боксы по центру".

    Вот. Надеюсь, не запутал еще больше :-)

  10. Александр Шугард

    Нет. Всё нормальненько теперь ... =)
    Хотя я впринципе так и понимал всегда выравнивание это =)
    Спасибо.

  11. Александр Шугард

    Очень хочеться увидеть внятную статью про вертикальное выравнивание =) ...
    Сижу вот эксперементирую ... так и хочеться забить и сделать одну ... главную таблицу с вертикальным выравниванием ... всего-то ...

    и сколько проблем сразу решиться ... =)))

  12. Ozz

    Это все отлично.. но у меня такой вопрос:
    можно ли составить такой универсальный HTML файл, чтобы к нему можно было "присобачить" любой дизайн подключив CSS ..
    Т.е. ведь нельзя оставить голый HTML без доп. оформительных тэгов.. Ну что-то вроде:
    <html> <head>.. </head> <body> <div id="wrap"> <div id="heading"> --- ШАПКА ----- </div> <div id="navigation"> --- СПИСОК МЕНЮ --- </div> <div id="content"> ---- СОДЕРЖАНИЕ ---- <div> <div id="footer"> ----- ФУТЕР ---- </div> </div> </body> <html>``А внутри там уже голый HTML без всяких "id" и "class"... Или все-таки пока рано об этом говорить? Какие еще есть идеи?

  13. Иван Сагалаев

    Ну, в общем-то так все почти и делается. Если посмотреть в код этой страницы и поискать там id="menu", то можно увидеть, что оно расположено далеко внизу, после комментариев и представляет собой обычный список <ul>. Между тем, визуально оно расположено в правом верхнем углу, вписанное в заголовок. Это, вот, та самая свобода.

    Но все же CSS'ом можно сделать не все, что угодно. У него есть ограничения, которые я периодически уже упоминал:
    - нельзя привязать позицию элемента к другому произвольному элементу (например, я не смогу впихнуть меню между постом и комментариями)
    - нет нормального вертикального выравнивания
    - и т.д.

    То есть, ответ скорее "да". Но не совсем :-)

  14. [...] Интересной находкой недели для меня оказалась заметка “Linux на 40% дешевле Windows?“. Честно говоря, я верю результатам этих исследований больше, чем аналогичным, но проведенным по заказу Microsoft (на мой взгляд все такие исследования должны проводить независимые эксперты). Очень много полезного я узнал в заметке Ивана Сагалаева “Раскладка в CSS: поток“. [...]

  15. gruz0

    А я вот предпочитаю использовать css в связке с php.
    очень удобно, например менять цвета таблиц:
    <?
    $table1 = " style=\"background-color:#F5F5F5;\"";
    $table2 = " style=\"background-color:#E4E4E4;\"";
    echo "SOME TEXT HERE";
    echo "SOME TEXT HERE2";
    ?>
    и всегда можно поменять, либо вообщезакомментировать.

  16. Никита

    Точно по середине страницы на мой взгляд тоже очень хороший способ выравнивания как по вертикали, так и по горизонтали. При этом родительский элемент (в котором находится выравниваемый объект) может иметь размер с процентным соотношением.

  17. Ширшов Илья

    abba abba

    В ie6 не работает, спасите кто может! Опера и файфокс показывают внутренний бокс справа, а ie6 слева. Что делать?

  18. Ширшов Илья

    Спасение утопающих...

    В ie6 заработало так:

  19. Irisha

    А нельзя ли сделать на сайте Вашем ссылку на архивчик со статьями. А то в сети постоянно сидеть тоже накладно, а инфа очень даже полезная. Спасибо заранее

  20. Иван Сагалаев

    Непосредственно архива не существует, но я могу предложить просто скачать архив категории "Учебник" какой-нибудь качалкой сайтов.

  21. Александр

    Спасибо за интересные статьи! Но исправьте пожалуйста недочет с названием ссылок в тексте.

    Например:

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

    Однако, CSS’ом это поведение можно свободно менять. Для этого служит свойство display. Значений у <a>него</a> - туча. А не <a>туча</a>.

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

  22. Люмин

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

    Почему-то в случае, если блок содержит только одну картинку, размер блока по высоте больше высоты картинки на 2 пикселя. Для IE помогает после картинки. А как быть с оперой и мозиллой? Задавать размер блока вручную? Может есть какие-то "более другие" варианты?

  23. Люмин
    • Для IE помогает тэг br после картинки.
  24. Иван Сагалаев

    <img> по умолчанию отображается в CSS как строчный элемент. А значит для него, как и для всех букв, предусматривается подстрочное место. Чтобы от этого избавиться, можно поставить ему блочное отображение:

    img {
      display: block;
    }
    
  25. kontiky

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

      ) в виде горизонтальной строки.

    Можно реально работающий пример для этого трюка?

  26. Муркт

    Можно реально работающий пример для этого трюка?

    http://softwaremaniacs.org/ ;-) Меню сверху именно так и сделано.

  27. Иван Сагалаев

    Нет, там float'ами, а не inline'ами...

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

    <ul>
      <li><a href="">One</a>
      <li><a href="">Two</a>
      <li><a href="">Three</a>
    </ul>
    

    ...

    ul {
      margin: 0; padding: 0;
    }
    
    li {
      display: inline;
      padding: 0 1em; margin: 0;
    }
    

    Чем не меню...

  28. Слон

    Спасибо, очень живые и информативные статьи!!! Мало где еще на ограниченном пространстве можно встретить такую кучу полезностей.

  29. dreamer

    Насчёт меню.. Обычно все используют конструкцию

    ..<li><a>пункт меню</a></li>..
    

    Попробовал как-то другой подход:

    ..<a>пункт меню</a>..
    

    задав блочный стиль для A - тоже всё неплохо позиционируется..
    Зачем тогда "лишний" ul-li?

  30. Иван Сагалаев

    Это неверная постановка вопроса. HTML'ные конструкции нужны не для навешивания стилей. Они задают смысл и структуру документа. Меню — это список пунктов, так его и рекомендуется оформлять. А пригодились элементы для стайлинга или нет — это уже второстепенный вопрос. И к слову сказать, обычно их не хватает, приходится лишние бессмысленные контейнеры добавлять (span, div).

  31. dreamer

    лично автору - с этим согласен, а лишние div-span элементы меня бесят самого,
    если использовать БОЛЬШЕ из всего разнообразия css
    (к примеру img vspace=0 hspace=0) думается от 80% лишних элементов можно было бы отказаться, лишние спаны вводятся тогда, когда "нехватка" стилевых id-class, или в попытке "Хоть как-то прибить к центру этот чёртов текст!".. :)

  32. Dmitry

    ээ.. я начинающий в CSS.
    Есть для меня проблема, которую я не могу понять. А именно

    .content {
        width   : 800px;
        margin  : 0 auto;
        border  : 1px solid silver;
    }
    .content .post {
        padding : 6px;
    }
    .content .post .title {
        font-size   : 1.0em;
    }
    .content .post .body {
        font-size   : 0.5em;
    }
    

    Собственно, вроде все правильно и красиво, с текстом.
    Но тут я убираю тест и оставляю в .post один img который перекрывает низ .post тоесть внутри его начало и внизу поверх бордюра моего .post
    выпадет из него. А как сделать, чтобы этот <div class="post"> увеличивался в высоту и обхватывал рисунок ?

  33. Александр

    Просто незаменимый пример выравнивания блоков, если использован float - http://w3pro.ru/article/vyravnivanie-blokov-po-tsentru. Очень полезно если надо выравнять по центру горизонтальное меню сайта.

  34. SelenIT

    Иван, возник вопрос по поводу безымянных инлайнов: части небезымянного инлайна, разбитого другими тегами (как слово "всяческими " в первом примере из статьи, внутри em, но делящее его с соседом dfn) — это что? Безымянные инлайны или нет?

  35. AlexZ

    2012 год на дворе, а только на вашем блоге есть приличное описание потоков.

  36. Pawel.rsk

    А как же inline-block ?!

  37. Ivan Sagalaev

    Семь лет назад поддержка inline-block в браузерах была в зачаточном состоянии, и пользоваться им было нельзя.

  38. Рустам

    Круто, 2013 год на дворе, а учебник все актуален )

  39. Лена

    Гг :) 2015 - это все еще лучший учебник! :) Уважаемый автор, похоже, что ваше творение бессмертно:)

  40. Надежда

    2016 пошёл. Все ещё... =)

  41. Николай

    2017 год, и это первый ресурс, где я как  backend разработчик, смог разобраться наконец то более менее с  премудростями CSS

  42. Andrei

    2019 год. Действительно крутое объяснение. Везде все объясняется какими-то урывками.

  43. Александр

    2020 год. по прежнему это лучший материал, Иван! Огромное спасибо!!!!

Добавить комментарий