Введение в стандарты Web

Плавающие элементы и очистка

Разбить на страницы
Показывать лекцию целиком

Введение

В этой статье мы познакомимся с плавающими элементами (float) и очисткой (clearing) -- двумя обязательными инструментами современного Web-дизайнера. Они являются многогранными инструментами, которые можно использовать для реализации обтекания текстом изображений и даже создания много-столбцовых компоновок.

Статья имеет следующую структуру:

Для чего нужны плавающие элементы и очистка?
Немного теории
Как работают плавающие элементы? 
	Детали 
	Дополнительные плавающие элементы 
	Поля плавающих элементов
Очистка 
Контейнерные плавающие элементы 
Заключение в оболочку 
Центрирование плавающих элементов 
Ошибки!
Заключение 
Контрольные вопросы

Для чего нужны плавающие элементы и очистка?

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

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

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

Немного теории

Чтобы объяснить, как работает float, необходимо посмотреть, как браузеры Web воспроизводят документ HTML/CSS. Не беспокойтесь, это будет коротко.

Каждый видимый элемент HTML генерирует бокс, который затем воспроизводится. Если вы просматриваете документ на экране компьютера или мобильного телефона, боксы воспроизводятся на экране. При печати документа боксы воспроизводятся на бумаге. Если используется считыватель экрана, содержимое бокса воспроизводится вслух, как речь.

Также как в HTML имеются элементы блочного и строкового уровней, в CSS имеются боксы блочного и строкового уровней. По умолчанию элементы блочного уровня генерируют боксы блочного уровня, а строковые элементы генерируют строковые боксы. Кроме боксов, генерируемых элементами, будут также генерироваться дополнительные боксы, например, для текстового контента документа. Блочные боксы обычно располагаются в том порядке, в котором элементы появляются в разметке, сверху вниз. Блочные боксы не могут появляться рядом бок о бок, если не используется некоторый код CSS. Строковые боксы располагаются горизонтально. Свойство direction определяет, будут ли они располагаться слева направо или справа налево (по умолчанию используется слева направо, если оно не определено).

Это называется потоком документа: строковые боксы текут горизонтально в боксах своих блоков предков, а боксы блоков текут вертикально. Боксы появляются в том же порядке, что и элементы в разметке HTML.

Рассмотрим следующий простой документ HTML (я включил только часть в элементе body ):

<p>This is a very simple document. </p>
<p>It consists of <em>two</em> paragraphs. </p>

рис 35.1 показывает снимок с экрана этого документа с дополнительной графикой, которая показывает два блочных бокса, сгенерированных элементами p, и строковым боксом, сгенерированным элементом em.(рис 35.1) Демонстрация блочных боксов, сгенерированных элементами p, и строкового блока, сгенерированного элементом em

Все строковые боксы, которые составляют одну "строку" на устройстве вывода, заключаются в воображаемые прямоугольники, называемые линейными боксами. Линейные боксы всегда размещаются сверху вниз без интервала между ними, как показано на рис 35.2.(рис 35.2) Каждая воспроизведенная строка заключается в отдельный линейный бокс

Как работают плавающие элементы?

Теперь, познакомившись с основами теории, давайте перейдем к рассмотрению синтаксиса плавающих элементов и очистки, и рассмотрим несколько примеров.

Свойство float имеет четыре допустимых значения: left, right, none и inherit. Первые два используются значительно чаще и будут заставлять бокс смещаться влево или вправо. Объявление float:none, которое используется по умолчанию, обычно объявляется только для "отмены" объявления в некотором другом правиле. float:inherit используется очень редко и существует скорее просто для единообразия. Оно заставляет элемент наследовать значение float от элемента предка.

Плавающий бокс исключается из потока документа и смещается как можно дальше влево или вправо, в зависимости от указанного направления смещения. "Как можно дальше" обычно означает, пока внешний край плавающего элемента не коснется края содержащего его блока (внутреннего края его заполнения, если имеется). Таким образом, для float:left бокс смещается влево, пока левое поле плавающего элемента не коснется левого края предка.

Внимательный читатель мог заметить, что выше было сказано "обычно". Если уже имеется бокс, смещенный влево, когда мы смещаем другой бокс в том же направлении, то второй бокс остановится, когда коснется первого бокса. Другими словами, плавающие элементы не накладываются друг на друга.

Пришло время посмотреть на плавающие элементы в действии, поэтому приготовьте текстовый редактор.

1. Создайте новый файл, скопируйте в него приведенный ниже код, и сохраните документ как float.html.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd" >
<html>
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" >
      <title>Floating</title>
    </head>
    <body>
      <p id="p1" > <span id="span-a" >Lorem ipsum</span>
      <span id="span-b" >dolor sit amet</span>
      <span id="span-c" >consectetuer</span> adipiscing elit.
      Curabitur feugiat feugiat purus.
      Aenean eu metus. Nulla facilisi.
      Pellentesque quis justo vel massa suscipit sagittis.
      Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos.
      Quisque mollis, justo vel rhoncus aliquam, urna tortor varius lacus, ut tincidunt metus arcu vel lorem.
      Praesent metus orci, adipiscing eget, fermentum ut, pellentesque non, dui.
      Sed sagittis, metus a semper dictum, sem libero sagittis nunc, vitae adipiscing leo neque vitae tellus.
      Duis quis orci quis nisl nonummy dapibus.
      Etiam ante. Phasellus imperdiet arcu at odio.
      In hac habitasse platea dictumst. Aenean metus.
      Quisque a nibh. Morbi mattis ullamcorper ipsum.
      Nullam odio urna, feugiat sed, bibendum sed, vulputate in, magna.
      Nulla tortor justo, convallis iaculis, porta condimentum, interdum nec, arcu.
      Proin lectus purus, vehicula et, cursus ut, nonummy et, diam. </p>

      <p id="p2" >Nunc ac elit. Vestibulum placerat dictum nibh. Proin massa.
      Curabitur at lectus egestas quam interdum mollis.
      Cras id velit a lacus sollicitudin faucibus.
      Proin at ante id nisi porttitor scelerisque.
      In metus. Aenean nonummy semper enim.
      Aenean tristique neque quis arcu tincidunt auctor.
      Fusce consequat auctor ligula.
      Fusce nulla lorem, sagittis a, lacinia et, nonummy in, eros.
      In nisi augue, aliquam eget, convallis vel, malesuada quis, libero. </p>

      <p id="p3" >Hello, World! </p>
    </body>
  </html>

Файл содержит много контента, но он нам понадобится, чтобы показать, как все работает.

2. Откройте документ в Web-браузере, чтобы увидеть, как он выглядит. Скучновато, не правда ли?

3. Создайте другой документ в текстовом редакторе, введите в него представленный ниже код, и сохраните как style.css в том же каталоге, что и файл HTML шага 1.

#span-a {
  float: left;
  background-color: #cfc;
  color: #030;
}

4. Соедините таблицу стилей с документом HTML, вставляя следующую строку сразу перед тегом </head>:

<link rel="stylesheet" type="text/css" href="style.css" >

5. Сохраните и обновите страницу в браузере. Вы увидите теперь элемент span, содержащий слова "Lorem ipsum", смещенный влево. Я задал для него также светло-зеленый фон, чтобы слегка его выделить.

6. По прежнему не так просто увидеть, что здесь происходит, поэтому давайте сделаем плавающий элемент немного больше. Добавьте следующее объявление в таблицу стилей:

#span-a {
  float: left;
  background-color: #cfc;
  color: #030;
  padding: 1em;
}

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

Детали

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

1. Добавьте еще одно правило CSS в таблицу стилей следующим образом:

p {
  border: 1px solid #f00;
}

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

3. Давайте модифицируем последнее правило, чтобы проверить, что плавающие элементы останавливаются на внутреннем крае области заполнения предка:

p {
  border: 1px solid #f00;
  padding: 1em;
  background-color: #ff9;
}

4. Сохраните и обновите, и вы увидите доказательство того, что было сказано ранее: плавающий бокс смещается до края содержащего его блока, в то время как заполнение предка находится вне его. Вы увидите также, что желтый фон параграфа распространяется под плавающим боксом. Плавающий бокс потомок очевидно не влияет на бокс параграфа, только на линейные боксы внутри.

5. Давайте поэкспериментируем еще - что произойдет, если плавающий элемент будет выше чем его предок? Модифицируем правило для плавающего элемента следующим образом:

#span-a {
  float: left;
  background-color: #cfc;
  color: #030;
  padding: 1em 1em 10em;
}

Примечание: Если вы используете более узкое окно браузера, то может понадобиться использовать для нижнего заполнения значение больше 10em, чтобы зеленая область распространилась за пределы нижней границы параграфа.

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

Дополнительные плавающие элементы

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

1. Добавьте новое правило в таблицу стилей, сохраните и обновите страницу как и раньше:

#span-b {
  float: left;
  background-color: #ccf;
  color: #003;
  padding: 1em;
}

Теперь элемент span, содержащий слова "dolor sit amet", также смещается влево. Вы увидите, что он смещается влево, пока не коснется первого плавающего элемента; другими словами, "насколько возможно".

2. Зачем останавливаться на двух плавающих элементах? Давайте сделаем третий - добавим следующее правило в таблицу стилей:

#span-c {
  float: left;
  background-color: #fcc;
  color: #300;
  padding:2em 1em;
}

3. Я хочу также, чтобы вы добавили временное правило, чтобы увидеть на примере, что происходит, когда в строке недостаточно места для плавающего элемента. Добавьте следующее правило в конце таблицы стилей:

span {
  width: 34%;
}

4. Как и раньше, сохраните таблицу стилей и обновите документ в браузере - вы увидите что-то похожее на вывод, показанный на рис 35.3.(рис 35.3) Не совсем то, что ожидали?

Ну! Что же произошло? Третий плавающий элемент теперь оказался ниже второго! (А браузер Internet Explorer 6 делает другую странную вещь, которую мы пока проигнорируем.) Так как ширина каждого элемента span составляет 34% от ширины параграфа (как определено правилом, добавленным на шаге 3), плюс некоторое заполнение, то пространства для всех трех в строке не хватает (3 x 34% = 102%). Два первые плавающие элемента находятся на одной линии, но для третьего места не хватает, и он сдвигается вниз. Важно то, что он сдвигается вниз только настолько, чтобы поместиться в строке. Он не сдвигается вниз ниже высокого первого плавающего элемента, так как справа от него имеется пространство.

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

Поля плавающих элементов

Теперь посмотрим, что можно делать с полями плавающих элементов.

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

span {
  width: 34%;
}

Теперь плавающие элементы тесно соединены вместе, и смежный текст начинается сразу после последнего плавающего элемента (если только вы не используете Microsoft Internet Explorer 6 или более старый, в этому случае появляется 3-пиксельный зазор справа в связи с трех-пиксельной ошибкой соединения). Как можно создать некоторое пространство вокруг плавающего бокса? Ответом будут поля!

2. Давайте сделаем это на среднем плавающем элементе - измените правило CSS для среднего плавающего элемента следующим образом, затем сохраните и обновите:

#span-b {
  float: left;
  background-color: #ccf;
  color: #003;
  padding: 1em;
  margin-left: 1em;
  margin-right: 1em;
}

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

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

#span-c {
  float: left;
  background-color: #fcc;
  color: #300;
  padding:2em 1em;
  margin-top: 2em;
  margin-bottom: 2em;
}

Это заставляет третий плавающий элемент переместиться вниз, и также имеется некоторое дополнительное пространство ниже его.

4. Так как мы занимаемся экспериментами, давайте посмотрим, что произойдет, если мы зададим отрицательные поля! Сделайте следующие изменения в правиле для третьего плавающего элемента, затем сохраните и обновите:

#span-c {
  float: left;
  background-color: #fcc;
  color: #300;
  padding:2em 1em;
  margin-top: 2em;
  margin-bottom: 2em;
  margin-left: -4em;
}

Вы увидите теперь вывод, показанный на рис 35.4.(рис 35.4) Теперь плавающие элементы перекрывают друг друга!

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

Очистка

Теперь, после рассмотрения основ плавающих элементов, мы переходим к тесно связанной теме очистки.

Как вы видели в примерах в этой статье, текст будет обтекать вокруг плавающего элемента, а блочные боксы не затрагиваются плавающими элементами. Иногда желательно гарантировать, что элемент не заканчивается рядом с плавающим элементом. Например, заголовок, который вводит новый раздел статьи, не должен появляться рядом с изображением из предыдущего раздела. Значительно лучше если заголовок появится ниже изображения, даже если изображение высовывается ниже последнего параграфа. Единственным способом сделать это является использование свойства clear на заголовке.

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

Свойство clear имеет три используемых значения: left, right и both. Также допустимыми значениями являются значения none (по умолчанию) и inherit.

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

Очистка достигается смещением элемента вниз (над его верхним полем добавляется пустое место), если потребуется, пока его верхний край не будет ниже всех плавающих боксов в указанном направлении. Давайте рассмотрим пример с целью дополнительной иллюстрации.

1. Прежде чем делать это, давайте изменим таблицу стилей. Удалите правила для #span-b и #span-c, так чтобы слева остался только зеленый плавающий элемент. Проверьте, что его нижнее заполнение достаточно большое, чтобы распространиться на второй параграф.

2. Добавьте следующее правило для второго параграфа, затем сохраните и обновите:

#p2 {
  clear: left;
}

Видите! Второй параграф смещается вниз, пока не освободится полностью от плавающего элемента, как видно на рис 35.5.(рис 35.5) Второй параграф теперь смещен ниже первого

Чтобы еще больше все запутать, можно использовать float и clear в одном элементе.

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

#span-b {
  float: left;
  clear: left;
  padding: 1em;
  background-color: #ccf;
  color: #003;
}

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

Контейнерные плавающие элементы

Как вы видели выше, бокс предок обычно не расширяется, чтобы охватить плавающего потомка. Это часто может создавать путаницу, например, когда все потомки элемента являются плавающими, когда создается горизонтальное меню из неупорядоченного списка, делая плавающими все элементы li. Так как плавающие боксы извлекаются из потока и не влияют на бокс предок, то все плавающие потомки делают по сути предка пустым и он схлопнется до нулевой высоты. Иногда это нежелательно, например, если вы хотите задать для предка фон. Если предок имеет нулевую высоту, то никакой фон не будет виден.

Очевидно, что нужен некоторый механизм, позволяющий расширить бокс предок, чтобы он охватил своих плавающих потомков. Традиционный метод состоит в добавлении в разметку дополнительного элемента, сразу перед закрывающим тегом предка, и задание на нем clear:both. Это работает, но это недостаточно хорошо, так как включает использование дополнительной ненужной, несемантической разметки. К счастью имеются другие способы, которые будут сейчас рассмотрены.

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

1. Чтобы проверить это в нашем примере документа, снова удалите правило для #span-b, и сделайте следующим образом первый параграф плавающим, прежде чем сохранить и обновить:

#p1 {
  float: left;
}

Параграф теперь расширяется, пока не охватит зеленый плавающий элемент. Все это прекрасно работает, но иногда предок не может быть плавающим элементом. Другим способом, который не требует плавающего предка, является задание для свойства overflow элемента предка значения отличного от visible. Если задать его как hidden и не определить высоту, то предок будет охватывать плавающих потомков.

2. Замените последнее правило следующим, затем сохраните и обновите страницу:

#p1 {
  overflow: hidden;
}

Отметим, что последний метод не работает в браузере Internet Explorer 6 или более старой версии.

Заключение в оболочку

Я упоминал ранее, что превращение строкового бокса в плавающий делает его блочным боксом, позволяя тем самым определить для него размеры и вертикальные поля. Плавающий блочный бокс также имеет удивительные свойства: если ширина не определена, то бокс будет сжиматься "создавая оболочку" вокруг своего контента. Это не было видно в примере документа, когда плавающим был сделан первый параграф, так как он имел достаточное количество контента, чтобы заполнить все окно (если только у вас не слишком широкий монитор).

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

Добавьте следующее правило в таблицу стилей, затем сохраните и обновите страницу:

#p3 {
  float: right;
}

Параграф, который содержит "Hello, World!", будет теперь смещаться вправо, и будет иметь ширину имеющегося текста плюс некоторое заполнение, которое было определено в предыдущем правиле для всех параграфов.

Центрирование плавающего элемента

Иногда вы захотите сделать элемент плавающим - возможно, чтобы заставить его охватить плавающих потомков -- сохраняя его при этом горизонтально центрированным в его предке. Здесь имеется проблема: вы не можете использовать обычный прием задания левого и правого полей как auto для плавающих элементов, и не существует такого значения как float:center. Существует ли здесь какой-то способ обойти эту проблему?

Такое решение имеется. Специалист по CSS Поль О'Брайен объясняет, как это можно сделать, в своей статье "Когда float не является float"? (http://www.search-this.com/2007/09/19/when-is-a-float-not-a-float/). Это включает дополнительный элемент оболочки, но с этим можно смириться. Метод использует относительное позиционирование, которое мы рассмотрим в следующей статье о статическом и относительном позиционирование CSS. Смещая элемент оболочки вправо, а затем смещая плавающий элемент снова влево, вы можете в действительности центрировать завернутый в оболочку плавающий элемент неизвестной ширины!

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

1. Вставьте следующую разметку сразу после тега <body> в документе HTML:

<div class="wrap">
<ul id="menu">
    <li><a href="#">Home</a></li>
    <li><a href="#">News</a></li>
    <li><a href="#">Products</a></li>
    <li><a href="#">Services</a></li>
  </ul>
</div>

<!--Internet Explorer needs this-->
<div class="clear" > </div>

2. Добавьте следующие правила CSS в таблицу стилей, чтобы оформить меню:

#menu {
  margin: 0;
  padding: 0.5em;
  font-family: Verdana,sans-serif;
}

#menu li {
  float: left;
  list-style-type: none;
  margin: 0 0 0 0.5em;
  padding: 0.25em;
  background-color: #600;
  color: #ff9;
  border: 2px solid #f00;
}

#menu a {
  color: #ff9;
  text-decoration: none;
}

.wrap {
  float: left;
  margin-bottom: 2em;
}

.clear {
  clear: left;
  height: 1px;
  margin-top: -1px;
}

3. Сохраните оба файла и обновите страницу в браузере. Вы увидите свое меню в верхнем левом углу. Давайте сделаем его горизонтально центрированным.

4. Сместите элемент оболочки на половину страницы, модифицируя правило для .wrap, как показано ниже:

.wrap {
  float: left;
  margin-bottom: 2em;
  position: relative;
  left: 50%;
}

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

5. Модифицируем правило #menu следующим образом:

#menu {
  margin: 0;
  padding: 0.5em;
  font-family: Verdana,sans-serif;
  position: relative;
  left: -50%;
}

Меню теперь центрировано; единственная проблема состоит в том, что вы можете получить горизонтальную панель прокрутки в зависимости от ширины списка и окна браузера. Это связано с тем, что вы сместили элемент оболочки на половину экрана; если список будет шире половины окна, часть его окажется за пределами экрана.

6. Можно избавиться от этого, задавая свойство overflow:hidden на подходящем элементе предке, чтобы сделать переполнение скрытым. В этом случае предком оболочки является body. Иногда невозможно скрыть переполнение на элементе body, и в этом случае нужно будет создать оболочку для оболочки, однако в данном случае все нормально.

Добавьте следующее правило в таблицу стилей:

body {
  overflow: hidden;
}

7. В действительности имеется еще одна проблема. Если посмотреть на это в Internet Explorer вы увидите, что все по прежнему работает неправильно. Решение проблемы в том, чтобы сделать плавающим сам список, но только в Internet Explorer, так как это не работает в других браузерах. Это можно обойти, используя небольшой прием, который гарантирует, что это правило применяет только браузер Internet Explorer.

Добавьте следующее правило в таблицу стилей:

* html #menu {
  float: left;
}

Ошибки!

Плавающие элементы и очистка являются очень полезными, но, к сожалению, большинство - если не все - браузеры имеют ошибки реализации этих свойств. Internet Explorer 6 содержит огромный массив странного поведения с плавающими элементами, включая исчезающий контент, удвоение полей и печально известную ошибку с 3-пиксельным зазором. Но даже Firefox и Opera не полностью свободны от ошибок, когда речь идет о плавающих элементах и очистке. Сайт Position Is Everything (http://positioniseverything.net/) является бесценным источником, где документируются эти ошибки - вместе со средствами их обхода в большинстве случаев.

Заключение

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

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

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

Центрирование плавающего бокса в оболочке возможно с помощью добавления элемента оболочки и некоторого осмотрительного использования относительного позиционирования.

Контрольные вопросы

  • Что произойдет, если плавающий элемент появляется в середине параграфа; т.е, если перед плавающим элементом имеется текст? Обязательно проверьте это в различных браузерах, так как они ведут себя по разному. Opera и Safari делают это правильно, в то время как Firefox и Internet Explorer - нет.
  • Как плавающие элементы можно использовать для вывода пиктограмм изображений в галереи "ячеек" одинакового размера, не используя таблицу компоновки?
  • Как можно создать вертикальное навигационное меню на левой стороне страницы и столбец контента на правой, так чтобы текст контента не заворачивался под меню?
  • Очень распространенная компоновка Web-сайта состоит из заголовка в полную ширину, ниже которой находятся три столбца контента и затем нижний колонтитул в полную ширину. Как можно получить такую компоновку с помощью плавающих элементов и очистки?
  • Об авторе

    Томми Олссон является прагматичным пропагандистом стандартов Web и доступности, который живет в малонаселенной области центральной Швеции. Он написал свой первый документ HTML в 1993 г. и является в настоящее время техническим Web-мастером для правительственного агентства Швеции.

    Он написал пока одну книгу - Полный справочник по CSS (совместно с Полем О'Брайеном) - и поддерживает крайне нерегулярно блог с названием Кукушка-аутист (http://www.autisticcuckoo.net/).

    Материалы этого курса имеют лицензию Creative Commons Attribution, Non Commercial - Share Alike 2.5 license.
    Страницы:

    Введение

    В этой статье мы познакомимся с плавающими элементами (float) и очисткой (clearing) -- двумя обязательными инструментами современного Web-дизайнера. Они являются многогранными инструментами, которые можно использовать для реализации обтекания текстом изображений и даже создания много-столбцовых компоновок.

    Статья имеет следующую структуру:

    Для чего нужны плавающие элементы и очистка?
    Немного теории
    Как работают плавающие элементы? 
    	Детали 
    	Дополнительные плавающие элементы 
    	Поля плавающих элементов
    Очистка 
    Контейнерные плавающие элементы 
    Заключение в оболочку 
    Центрирование плавающих элементов 
    Ошибки!
    Заключение 
    Контрольные вопросы

    Для чего нужны плавающие элементы и очистка?

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

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

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

    Немного теории

    Чтобы объяснить, как работает float, необходимо посмотреть, как браузеры Web воспроизводят документ HTML/CSS. Не беспокойтесь, это будет коротко.

    Каждый видимый элемент HTML генерирует бокс, который затем воспроизводится. Если вы просматриваете документ на экране компьютера или мобильного телефона, боксы воспроизводятся на экране. При печати документа боксы воспроизводятся на бумаге. Если используется считыватель экрана, содержимое бокса воспроизводится вслух, как речь.

    Также как в HTML имеются элементы блочного и строкового уровней, в CSS имеются боксы блочного и строкового уровней. По умолчанию элементы блочного уровня генерируют боксы блочного уровня, а строковые элементы генерируют строковые боксы. Кроме боксов, генерируемых элементами, будут также генерироваться дополнительные боксы, например, для текстового контента документа. Блочные боксы обычно располагаются в том порядке, в котором элементы появляются в разметке, сверху вниз. Блочные боксы не могут появляться рядом бок о бок, если не используется некоторый код CSS. Строковые боксы располагаются горизонтально. Свойство direction определяет, будут ли они располагаться слева направо или справа налево (по умолчанию используется слева направо, если оно не определено).

    Это называется потоком документа: строковые боксы текут горизонтально в боксах своих блоков предков, а боксы блоков текут вертикально. Боксы появляются в том же порядке, что и элементы в разметке HTML.

    Рассмотрим следующий простой документ HTML (я включил только часть в элементе body ):

    <p>This is a very simple document. </p>
    <p>It consists of <em>two</em> paragraphs. </p>

    рис 35.1 показывает снимок с экрана этого документа с дополнительной графикой, которая показывает два блочных бокса, сгенерированных элементами p, и строковым боксом, сгенерированным элементом em.(рис 35.1) Демонстрация блочных боксов, сгенерированных элементами p, и строкового блока, сгенерированного элементом em

    Все строковые боксы, которые составляют одну "строку" на устройстве вывода, заключаются в воображаемые прямоугольники, называемые линейными боксами. Линейные боксы всегда размещаются сверху вниз без интервала между ними, как показано на рис 35.2.(рис 35.2) Каждая воспроизведенная строка заключается в отдельный линейный бокс

    Как работают плавающие элементы?

    Теперь, познакомившись с основами теории, давайте перейдем к рассмотрению синтаксиса плавающих элементов и очистки, и рассмотрим несколько примеров.

    Свойство float имеет четыре допустимых значения: left, right, none и inherit. Первые два используются значительно чаще и будут заставлять бокс смещаться влево или вправо. Объявление float:none, которое используется по умолчанию, обычно объявляется только для "отмены" объявления в некотором другом правиле. float:inherit используется очень редко и существует скорее просто для единообразия. Оно заставляет элемент наследовать значение float от элемента предка.

    Плавающий бокс исключается из потока документа и смещается как можно дальше влево или вправо, в зависимости от указанного направления смещения. "Как можно дальше" обычно означает, пока внешний край плавающего элемента не коснется края содержащего его блока (внутреннего края его заполнения, если имеется). Таким образом, для float:left бокс смещается влево, пока левое поле плавающего элемента не коснется левого края предка.

    Внимательный читатель мог заметить, что выше было сказано "обычно". Если уже имеется бокс, смещенный влево, когда мы смещаем другой бокс в том же направлении, то второй бокс остановится, когда коснется первого бокса. Другими словами, плавающие элементы не накладываются друг на друга.

    Пришло время посмотреть на плавающие элементы в действии, поэтому приготовьте текстовый редактор.

    1. Создайте новый файл, скопируйте в него приведенный ниже код, и сохраните документ как float.html.

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd" >
    <html>
        <head>
          <meta http-equiv="Content-Type" content="text/html; charset=utf-8" >
          <title>Floating</title>
        </head>
        <body>
          <p id="p1" > <span id="span-a" >Lorem ipsum</span>
          <span id="span-b" >dolor sit amet</span>
          <span id="span-c" >consectetuer</span> adipiscing elit.
          Curabitur feugiat feugiat purus.
          Aenean eu metus. Nulla facilisi.
          Pellentesque quis justo vel massa suscipit sagittis.
          Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos.
          Quisque mollis, justo vel rhoncus aliquam, urna tortor varius lacus, ut tincidunt metus arcu vel lorem.
          Praesent metus orci, adipiscing eget, fermentum ut, pellentesque non, dui.
          Sed sagittis, metus a semper dictum, sem libero sagittis nunc, vitae adipiscing leo neque vitae tellus.
          Duis quis orci quis nisl nonummy dapibus.
          Etiam ante. Phasellus imperdiet arcu at odio.
          In hac habitasse platea dictumst. Aenean metus.
          Quisque a nibh. Morbi mattis ullamcorper ipsum.
          Nullam odio urna, feugiat sed, bibendum sed, vulputate in, magna.
          Nulla tortor justo, convallis iaculis, porta condimentum, interdum nec, arcu.
          Proin lectus purus, vehicula et, cursus ut, nonummy et, diam. </p>
    
          <p id="p2" >Nunc ac elit. Vestibulum placerat dictum nibh. Proin massa.
          Curabitur at lectus egestas quam interdum mollis.
          Cras id velit a lacus sollicitudin faucibus.
          Proin at ante id nisi porttitor scelerisque.
          In metus. Aenean nonummy semper enim.
          Aenean tristique neque quis arcu tincidunt auctor.
          Fusce consequat auctor ligula.
          Fusce nulla lorem, sagittis a, lacinia et, nonummy in, eros.
          In nisi augue, aliquam eget, convallis vel, malesuada quis, libero. </p>
    
          <p id="p3" >Hello, World! </p>
        </body>
      </html>

    Файл содержит много контента, но он нам понадобится, чтобы показать, как все работает.

    2. Откройте документ в Web-браузере, чтобы увидеть, как он выглядит. Скучновато, не правда ли?

    3. Создайте другой документ в текстовом редакторе, введите в него представленный ниже код, и сохраните как style.css в том же каталоге, что и файл HTML шага 1.

    #span-a {
      float: left;
      background-color: #cfc;
      color: #030;
    }

    4. Соедините таблицу стилей с документом HTML, вставляя следующую строку сразу перед тегом </head>:

    <link rel="stylesheet" type="text/css" href="style.css" >

    5. Сохраните и обновите страницу в браузере. Вы увидите теперь элемент span, содержащий слова "Lorem ipsum", смещенный влево. Я задал для него также светло-зеленый фон, чтобы слегка его выделить.

    6. По прежнему не так просто увидеть, что здесь происходит, поэтому давайте сделаем плавающий элемент немного больше. Добавьте следующее объявление в таблицу стилей:

    #span-a {
      float: left;
      background-color: #cfc;
      color: #030;
      padding: 1em;
    }

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

    Детали

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

    1. Добавьте еще одно правило CSS в таблицу стилей следующим образом:

    p {
      border: 1px solid #f00;
    }

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

    3. Давайте модифицируем последнее правило, чтобы проверить, что плавающие элементы останавливаются на внутреннем крае области заполнения предка:

    p {
      border: 1px solid #f00;
      padding: 1em;
      background-color: #ff9;
    }

    4. Сохраните и обновите, и вы увидите доказательство того, что было сказано ранее: плавающий бокс смещается до края содержащего его блока, в то время как заполнение предка находится вне его. Вы увидите также, что желтый фон параграфа распространяется под плавающим боксом. Плавающий бокс потомок очевидно не влияет на бокс параграфа, только на линейные боксы внутри.

    5. Давайте поэкспериментируем еще - что произойдет, если плавающий элемент будет выше чем его предок? Модифицируем правило для плавающего элемента следующим образом:

    #span-a {
      float: left;
      background-color: #cfc;
      color: #030;
      padding: 1em 1em 10em;
    }

    Примечание: Если вы используете более узкое окно браузера, то может понадобиться использовать для нижнего заполнения значение больше 10em, чтобы зеленая область распространилась за пределы нижней границы параграфа.

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

    Дополнительные плавающие элементы

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

    1. Добавьте новое правило в таблицу стилей, сохраните и обновите страницу как и раньше:

    #span-b {
      float: left;
      background-color: #ccf;
      color: #003;
      padding: 1em;
    }

    Теперь элемент span, содержащий слова "dolor sit amet", также смещается влево. Вы увидите, что он смещается влево, пока не коснется первого плавающего элемента; другими словами, "насколько возможно".

    2. Зачем останавливаться на двух плавающих элементах? Давайте сделаем третий - добавим следующее правило в таблицу стилей:

    #span-c {
      float: left;
      background-color: #fcc;
      color: #300;
      padding:2em 1em;
    }

    3. Я хочу также, чтобы вы добавили временное правило, чтобы увидеть на примере, что происходит, когда в строке недостаточно места для плавающего элемента. Добавьте следующее правило в конце таблицы стилей:

    span {
      width: 34%;
    }

    4. Как и раньше, сохраните таблицу стилей и обновите документ в браузере - вы увидите что-то похожее на вывод, показанный на рис 35.3.(рис 35.3) Не совсем то, что ожидали?

    Ну! Что же произошло? Третий плавающий элемент теперь оказался ниже второго! (А браузер Internet Explorer 6 делает другую странную вещь, которую мы пока проигнорируем.) Так как ширина каждого элемента span составляет 34% от ширины параграфа (как определено правилом, добавленным на шаге 3), плюс некоторое заполнение, то пространства для всех трех в строке не хватает (3 x 34% = 102%). Два первые плавающие элемента находятся на одной линии, но для третьего места не хватает, и он сдвигается вниз. Важно то, что он сдвигается вниз только настолько, чтобы поместиться в строке. Он не сдвигается вниз ниже высокого первого плавающего элемента, так как справа от него имеется пространство.

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

    Поля плавающих элементов

    Теперь посмотрим, что можно делать с полями плавающих элементов.

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

    span {
      width: 34%;
    }

    Теперь плавающие элементы тесно соединены вместе, и смежный текст начинается сразу после последнего плавающего элемента (если только вы не используете Microsoft Internet Explorer 6 или более старый, в этому случае появляется 3-пиксельный зазор справа в связи с трех-пиксельной ошибкой соединения). Как можно создать некоторое пространство вокруг плавающего бокса? Ответом будут поля!

    2. Давайте сделаем это на среднем плавающем элементе - измените правило CSS для среднего плавающего элемента следующим образом, затем сохраните и обновите:

    #span-b {
      float: left;
      background-color: #ccf;
      color: #003;
      padding: 1em;
      margin-left: 1em;
      margin-right: 1em;
    }

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

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

    #span-c {
      float: left;
      background-color: #fcc;
      color: #300;
      padding:2em 1em;
      margin-top: 2em;
      margin-bottom: 2em;
    }

    Это заставляет третий плавающий элемент переместиться вниз, и также имеется некоторое дополнительное пространство ниже его.

    4. Так как мы занимаемся экспериментами, давайте посмотрим, что произойдет, если мы зададим отрицательные поля! Сделайте следующие изменения в правиле для третьего плавающего элемента, затем сохраните и обновите:

    #span-c {
      float: left;
      background-color: #fcc;
      color: #300;
      padding:2em 1em;
      margin-top: 2em;
      margin-bottom: 2em;
      margin-left: -4em;
    }

    Вы увидите теперь вывод, показанный на рис 35.4.(рис 35.4) Теперь плавающие элементы перекрывают друг друга!

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

    Очистка

    Теперь, после рассмотрения основ плавающих элементов, мы переходим к тесно связанной теме очистки.

    Как вы видели в примерах в этой статье, текст будет обтекать вокруг плавающего элемента, а блочные боксы не затрагиваются плавающими элементами. Иногда желательно гарантировать, что элемент не заканчивается рядом с плавающим элементом. Например, заголовок, который вводит новый раздел статьи, не должен появляться рядом с изображением из предыдущего раздела. Значительно лучше если заголовок появится ниже изображения, даже если изображение высовывается ниже последнего параграфа. Единственным способом сделать это является использование свойства clear на заголовке.

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

    Свойство clear имеет три используемых значения: left, right и both. Также допустимыми значениями являются значения none (по умолчанию) и inherit.

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

    Очистка достигается смещением элемента вниз (над его верхним полем добавляется пустое место), если потребуется, пока его верхний край не будет ниже всех плавающих боксов в указанном направлении. Давайте рассмотрим пример с целью дополнительной иллюстрации.

    1. Прежде чем делать это, давайте изменим таблицу стилей. Удалите правила для #span-b и #span-c, так чтобы слева остался только зеленый плавающий элемент. Проверьте, что его нижнее заполнение достаточно большое, чтобы распространиться на второй параграф.

    2. Добавьте следующее правило для второго параграфа, затем сохраните и обновите:

    #p2 {
      clear: left;
    }

    Видите! Второй параграф смещается вниз, пока не освободится полностью от плавающего элемента, как видно на рис 35.5.(рис 35.5) Второй параграф теперь смещен ниже первого

    Чтобы еще больше все запутать, можно использовать float и clear в одном элементе.

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

    #span-b {
      float: left;
      clear: left;
      padding: 1em;
      background-color: #ccf;
      color: #003;
    }

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

    Контейнерные плавающие элементы

    Как вы видели выше, бокс предок обычно не расширяется, чтобы охватить плавающего потомка. Это часто может создавать путаницу, например, когда все потомки элемента являются плавающими, когда создается горизонтальное меню из неупорядоченного списка, делая плавающими все элементы li. Так как плавающие боксы извлекаются из потока и не влияют на бокс предок, то все плавающие потомки делают по сути предка пустым и он схлопнется до нулевой высоты. Иногда это нежелательно, например, если вы хотите задать для предка фон. Если предок имеет нулевую высоту, то никакой фон не будет виден.

    Очевидно, что нужен некоторый механизм, позволяющий расширить бокс предок, чтобы он охватил своих плавающих потомков. Традиционный метод состоит в добавлении в разметку дополнительного элемента, сразу перед закрывающим тегом предка, и задание на нем clear:both. Это работает, но это недостаточно хорошо, так как включает использование дополнительной ненужной, несемантической разметки. К счастью имеются другие способы, которые будут сейчас рассмотрены.

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

    1. Чтобы проверить это в нашем примере документа, снова удалите правило для #span-b, и сделайте следующим образом первый параграф плавающим, прежде чем сохранить и обновить:

    #p1 {
      float: left;
    }

    Параграф теперь расширяется, пока не охватит зеленый плавающий элемент. Все это прекрасно работает, но иногда предок не может быть плавающим элементом. Другим способом, который не требует плавающего предка, является задание для свойства overflow элемента предка значения отличного от visible. Если задать его как hidden и не определить высоту, то предок будет охватывать плавающих потомков.

    2. Замените последнее правило следующим, затем сохраните и обновите страницу:

    #p1 {
      overflow: hidden;
    }

    Отметим, что последний метод не работает в браузере Internet Explorer 6 или более старой версии.

    Заключение в оболочку

    Я упоминал ранее, что превращение строкового бокса в плавающий делает его блочным боксом, позволяя тем самым определить для него размеры и вертикальные поля. Плавающий блочный бокс также имеет удивительные свойства: если ширина не определена, то бокс будет сжиматься "создавая оболочку" вокруг своего контента. Это не было видно в примере документа, когда плавающим был сделан первый параграф, так как он имел достаточное количество контента, чтобы заполнить все окно (если только у вас не слишком широкий монитор).

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

    Добавьте следующее правило в таблицу стилей, затем сохраните и обновите страницу:

    #p3 {
      float: right;
    }

    Параграф, который содержит "Hello, World!", будет теперь смещаться вправо, и будет иметь ширину имеющегося текста плюс некоторое заполнение, которое было определено в предыдущем правиле для всех параграфов.

    Центрирование плавающего элемента

    Иногда вы захотите сделать элемент плавающим - возможно, чтобы заставить его охватить плавающих потомков -- сохраняя его при этом горизонтально центрированным в его предке. Здесь имеется проблема: вы не можете использовать обычный прием задания левого и правого полей как auto для плавающих элементов, и не существует такого значения как float:center. Существует ли здесь какой-то способ обойти эту проблему?

    Такое решение имеется. Специалист по CSS Поль О'Брайен объясняет, как это можно сделать, в своей статье "Когда float не является float"? (http://www.search-this.com/2007/09/19/when-is-a-float-not-a-float/). Это включает дополнительный элемент оболочки, но с этим можно смириться. Метод использует относительное позиционирование, которое мы рассмотрим в следующей статье о статическом и относительном позиционирование CSS. Смещая элемент оболочки вправо, а затем смещая плавающий элемент снова влево, вы можете в действительности центрировать завернутый в оболочку плавающий элемент неизвестной ширины!

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

    1. Вставьте следующую разметку сразу после тега <body> в документе HTML:

    <div class="wrap">
    <ul id="menu">
        <li><a href="#">Home</a></li>
        <li><a href="#">News</a></li>
        <li><a href="#">Products</a></li>
        <li><a href="#">Services</a></li>
      </ul>
    </div>
    
    <!--Internet Explorer needs this-->
    <div class="clear" > </div>

    2. Добавьте следующие правила CSS в таблицу стилей, чтобы оформить меню:

    #menu {
      margin: 0;
      padding: 0.5em;
      font-family: Verdana,sans-serif;
    }
    
    #menu li {
      float: left;
      list-style-type: none;
      margin: 0 0 0 0.5em;
      padding: 0.25em;
      background-color: #600;
      color: #ff9;
      border: 2px solid #f00;
    }
    
    #menu a {
      color: #ff9;
      text-decoration: none;
    }
    
    .wrap {
      float: left;
      margin-bottom: 2em;
    }
    
    .clear {
      clear: left;
      height: 1px;
      margin-top: -1px;
    }

    3. Сохраните оба файла и обновите страницу в браузере. Вы увидите свое меню в верхнем левом углу. Давайте сделаем его горизонтально центрированным.

    4. Сместите элемент оболочки на половину страницы, модифицируя правило для .wrap, как показано ниже:

    .wrap {
      float: left;
      margin-bottom: 2em;
      position: relative;
      left: 50%;
    }

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

    5. Модифицируем правило #menu следующим образом:

    #menu {
      margin: 0;
      padding: 0.5em;
      font-family: Verdana,sans-serif;
      position: relative;
      left: -50%;
    }

    Меню теперь центрировано; единственная проблема состоит в том, что вы можете получить горизонтальную панель прокрутки в зависимости от ширины списка и окна браузера. Это связано с тем, что вы сместили элемент оболочки на половину экрана; если список будет шире половины окна, часть его окажется за пределами экрана.

    6. Можно избавиться от этого, задавая свойство overflow:hidden на подходящем элементе предке, чтобы сделать переполнение скрытым. В этом случае предком оболочки является body. Иногда невозможно скрыть переполнение на элементе body, и в этом случае нужно будет создать оболочку для оболочки, однако в данном случае все нормально.

    Добавьте следующее правило в таблицу стилей:

    body {
      overflow: hidden;
    }

    7. В действительности имеется еще одна проблема. Если посмотреть на это в Internet Explorer вы увидите, что все по прежнему работает неправильно. Решение проблемы в том, чтобы сделать плавающим сам список, но только в Internet Explorer, так как это не работает в других браузерах. Это можно обойти, используя небольшой прием, который гарантирует, что это правило применяет только браузер Internet Explorer.

    Добавьте следующее правило в таблицу стилей:

    * html #menu {
      float: left;
    }

    Ошибки!

    Плавающие элементы и очистка являются очень полезными, но, к сожалению, большинство - если не все - браузеры имеют ошибки реализации этих свойств. Internet Explorer 6 содержит огромный массив странного поведения с плавающими элементами, включая исчезающий контент, удвоение полей и печально известную ошибку с 3-пиксельным зазором. Но даже Firefox и Opera не полностью свободны от ошибок, когда речь идет о плавающих элементах и очистке. Сайт Position Is Everything (http://positioniseverything.net/) является бесценным источником, где документируются эти ошибки - вместе со средствами их обхода в большинстве случаев.

    Заключение

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

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

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

    Центрирование плавающего бокса в оболочке возможно с помощью добавления элемента оболочки и некоторого осмотрительного использования относительного позиционирования.

    Контрольные вопросы

  • Что произойдет, если плавающий элемент появляется в середине параграфа; т.е, если перед плавающим элементом имеется текст? Обязательно проверьте это в различных браузерах, так как они ведут себя по разному. Opera и Safari делают это правильно, в то время как Firefox и Internet Explorer - нет.
  • Как плавающие элементы можно использовать для вывода пиктограмм изображений в галереи "ячеек" одинакового размера, не используя таблицу компоновки?
  • Как можно создать вертикальное навигационное меню на левой стороне страницы и столбец контента на правой, так чтобы текст контента не заворачивался под меню?
  • Очень распространенная компоновка Web-сайта состоит из заголовка в полную ширину, ниже которой находятся три столбца контента и затем нижний колонтитул в полную ширину. Как можно получить такую компоновку с помощью плавающих элементов и очистки?
  • Об авторе

    Томми Олссон является прагматичным пропагандистом стандартов Web и доступности, который живет в малонаселенной области центральной Швеции. Он написал свой первый документ HTML в 1993 г. и является в настоящее время техническим Web-мастером для правительственного агентства Швеции.

    Он написал пока одну книгу - Полный справочник по CSS (совместно с Полем О'Брайеном) - и поддерживает крайне нерегулярно блог с названием Кукушка-аутист (http://www.autisticcuckoo.net/).

    Материалы этого курса имеют лицензию Creative Commons Attribution, Non Commercial - Share Alike 2.5 license.
    Вернуться к учебному плану