Подробнее о позиционировании

Комментарии

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

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

В этом уроке мы начнём с краткого обзора того, как обуздать float. После этого мы рассмотрим более детальные методы позиционирования, в том числе точное позиционирование элементов по осям х и у, а также оси z.

Обуздание float

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

При обтекании позиционирование элемента зависит от расположения других элементов вокруг него. Будет ли элемент находиться на одной строке? Появится ли он на новой строке? Всё это зависит от DOM (Document Object Model, объектная модель документа) и того, что окружает элемент.

Что такое DOM?

DOM или Document Object Model — это API для HTML и XML-документов, который обеспечивает их структурное представление. В нашем случае мы говорим конкретно об HTML-документах, таким образом, DOM представляет все различные элементы и их взаимосвязи друг с другом.

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

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

Если вложенные элементы не выстраиваются правильно, могут появиться ошибки стилизации. Взгляните ниже на демонстрацию, раздел box-set должен содержать светло-серый фон, однако фон не виден, пока все вложенные в него элементы обтекаемые. При инспектировании раздела box-set вы увидите, что height у него равен 0.

HTML

<div class="box-set">
  <figure class="box">Блок 1</figure>
  <figure class="box">Блок 2</figure>
  <figure class="box">Блок 3</figure>
</div>

CSS

.box-set {
  background: #eaeaed;
}
.box {
  background: #2db34a;
  float: left;
  margin: 1.858736059%;
  width: 29.615861214%;
}

Демонстрация обуздания float

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

К счастью, есть несколько разных методов, которые мы можем использовать для обуздания float, наиболее популярные включают технику overflow и технику clearfix.

Техника overflow

Одним из способов обуздания float в родительском элементе является использование стилевого свойства overflow. Установка у свойства overflow значения auto внутри родительского элемента обуздает float, в результате чего у родителя появится реальная высота, в том числе серый фон в нашем примере.

Чтобы это работало в Internet Explorer 6 для родителя требуется добавить height или width. Поскольку height, вероятно, будет переменной, то ширина 100% обеспечит этот трюк. С помощью overflow: auto; в Internet Explorer на компьютере Apple к родительскому элементу также добавятся полосы прокрутки, поэтому лучше использовать запись overflow: hidden;.

.box-set {
  overflow: auto;
}

Демонстрация техники overflow

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

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

Демонстрация ошибок overflow

Техника clearfix

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

Метод clearfix базируется на использовании псевдоэлементов :before и :after для родительского элемента. С помощью этих псевдоэлементов вы можете создать скрытые элементы выше и ниже содержимого родителя, содержащего float. Псевдоэлемент :before используется для предотвращения схлопывания верхнего margin у дочерних элементов путём создания анонимного табличного элемента с помощью записи display: table;. Это также помогает обеспечить стойкость в Internet Explorer 6 и 7. Псевдоэлемент :after используется для предотвращения схлопывания нижнего margin у дочерних элементов, а также для очистки вложенных float.

Добавление свойства *zoom к родительскому элементу запускает механизм hasLayout специально для Internet Explorer 6 и 7, который определяет, как элементы должны рисоваться и связаны с их содержимым, а также как элементы должны взаимодействовать и относятся к другим элементам.

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

.box-set:before,
.box-set:after {
  content: "";
  display: table;
}
.box-set:after {
  clear: both;
}
.box-set {
  *zoom: 1;
}

Демонстрация техники clearfix

Эффективное обуздание float

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

Одной распространённой практикой является присвоение класса родительскому элементу, который включает в себя float, нуждающиеся в обуздании. Техника clearfix, к примеру, помогла Дэну Седерхольму в виде шаблона класса с именем group. Название класса group затем может быть применено к любому родительскому элементу нуждающемуся в обуздании float.

.group:before,
.group:after {
  content: "";
  display: table;
}
.group:after {
  clear: both;
}
.group {
  *zoom: 1;
}

Одиночные псевдоэлементы

Стоит отметить, что для каждого элемента допускается только один псевдоэлемент :before и один :after за раз. При попытке использовать технику clearfix с другим :before и :after можно не получить желаемого результата.

В приведённых выше примерах стили clearfix не будут жить под классом box-set. Вместо этого должен быть добавлен класс group к родителю, содержащему обтекаемые элементы.

Свойство position

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

Статичное позиционирование

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

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

HTML

<div class="box-set">
  <figure class="box box-1">Блок 1</figure>
  <figure class="box box-2">Блок 2</figure>
  <figure class="box box-3">Блок 3</figure>
  <figure class="box box-4">Блок 4</figure>
</div>

CSS

.box-set {
  background: #eaeaed;
}
.box {
  background: #2db34a;
  height: 80px;
  width: 80px;
}

Демонстрация статичного позиционирования

Относительное позиционирование

Значение relative для свойства position очень похоже на значение static. Основное отличие заключается в том, что relative принимает свойства смещения блока top, right, bottom и left. Эти свойства позволяют точно позиционировать элемент, сдвигая его из положения по умолчанию в любом направлении.

Как работают свойства смещения блока

Свойства смещения блока top, right, bottom и left указывают, как элементы могут быть позиционированы и в каком направлении. Эти свойства работают только для элементов со значениями relative, absolute или fixed у свойства position.

Для относительно позиционируемых элементов эти свойства определяют, как элемент должен быть перемещён из позиции по умолчанию. К примеру, использование значения 20px у свойства top будет толкать элемент на 20 пикселей вниз от исходного положения. Переключение значения top на -20px вместо этого потянет элемент на 20 пикселей вверх от исходного положения.

Для абсолютного или фиксированного позиционирования эти свойства определяют расстояние между элементом и краями родительского элемента. Например, использование значения 20px у top для абсолютно позиционируемого элемента будет толкать элемент на 20 пикселей вниз от верхнего края его относительно позиционированного родителя. Переключение значения top на -20px затем будет тянуть элемент на 20 пикселей вверх от верхнего края его относительно позиционированного родителя.

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

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

HTML

<div class="box-set">
  <figure class="box box-1">Блок 1</figure>
  <figure class="box box-2">Блок 2</figure>
  <figure class="box box-3">Блок 3</figure>
  <figure class="box box-4">Блок 4</figure>
</div>

CSS

.box-set {
  background: #eaeaed;
}
.box {
  background: #2db34a;
  height: 80px;
  position: relative;
  width: 80px;
}
.box-1 {
  top: 20px;
}
.box-2 {
  left: 40px;
}
.box-3 {
  bottom: -10px;
  right: 20px;
}

Демонстрация относительного позиционирования

В случае, если свойства смещения top и bottom заданы одновременно для относительно позиционированного элемента, свойство top будет иметь приоритет. Кроме того, если оба свойства смещения left и right заданы одновременно для относительно позиционированного элемента, приоритет отдаётся в направлении, на котором написан язык страницы. Например, для русских страниц отдаётся приоритет свойству смещения left, а для арабских страниц приоритет отдаётся свойству right.

Абсолютное позиционирование

Абсолютно позиционируемые элементы принимают свойства смещения блока, однако они удаляются из обычного потока документа. При удалении элемента из обычного потока элементы располагаются непосредственно относительно родителя, который позиционирован относительно или абсолютно. Если относительно или абсолютно позиционированного родителя нет, то абсолютно позиционированный элемент будет располагаться на странице относительно <body>.

Используя абсолютно позиционированные элементы и указав вертикальные и горизонтальные свойства смещения мы переместим элемент с этими значениями по отношению к его относительно позиционированному родителю. Например, элемент со значением top как 50px и right как 100px будет опущен вниз на 50 пикселей от верхнего края его относительно позиционированного родителя и сдвинут на 100 пикселей от правого края.

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

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

HTML

<div class="box-set">
  <figure class="box box-1">Блок 1</figure>
  <figure class="box box-2">Блок 2</figure>
  <figure class="box box-3">Блок 3</figure>
  <figure class="box box-4">Блок 4</figure>
</div>

CSS

.box-set {
  background: #eaeaed;
  height: 200px;
  position: relative;
}
.box {
  background: #2db34a;
  height: 80px;
  position: absolute;
  width: 80px;
}
.box-1 {
  top: 6%;
  left: 2%;
}
.box-2 {
  top: 0;
  right: -40px;
}
.box-3 {
  bottom: -10px;
  right: 20px;
}
.box-4 {
  bottom: 0;
}

Демонстрация абсолютного позиционирования

Когда элемент содержит фиксированный height и width и он абсолютно позиционирован, свойство top имеет приоритет по сравнению с двумя объявленными свойствами смещения top и bottom. Как и в случае относительно позиционируемых элементов, для элемента с фиксированной шириной, у которого заданы сразу свойства left и right, приоритет отдаётся направлению, на котором написан язык страницы.

Если у элемента нет заданной высоты или ширины и он абсолютно позиционирован, то с помощью комбинации свойств top и bottom элемент отображается с высотой, охватывающей весь заданный размер. То же самое касается одновременного использования свойств left и right, в результате чего полная ширина элемента основывается на свойствах left и right. Использование всех четырёх свойств смещения отобразит элемент с полной заданной высотой и шириной.

Фиксированное позиционирование

Значение fixed у позиционирования работает очень похоже на absolute, однако позиционирует относительно области просмотра браузера и не прокручивает вместе со страницей. Другими словами, элементы всегда будут присутствовать, независимо от того, где пользователь остановился на странице. Единственное предостережение про фиксированное позиционирование — оно не работает в Internet Explorer 6. Если вы хотите заставить фиксированное позиционирование работать в Internet Explorer 6 есть подходящие хаки.

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

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

HTML

<div class="box-set">
  <figure class="box box-1">Блок 1</figure>
  <figure class="box box-2">Блок 2</figure>
  <figure class="box box-3">Блок 3</figure>
  <figure class="box box-4">Блок 4</figure>
</div>

CSS

.box {
  background: #2db34a;
  height: 80px;
  position: fixed;
  width: 80px;
}
.box-1 {
  top: 6%;
  left: 2%;
}
.box-2 {
  top: 0;
  right: -40px;
}
.box-3 {
  bottom: -10px;
  right: 20px;
}
.box-4 {
  bottom: 0;
}

Демонстрация фиксированного позиционирования

Фиксированная шапка или подвал

Одним из наиболее распространённым использованием фиксированного позиционирования является создание фиксированной шапки или подвала, закрепленной на одной стороне страницы. Когда пользователь прокручивает страницу, элемент остаётся на месте, в пределах области просмотра, и пользователи всегда могут с ним взаимодействовать.

Код и демонстрация ниже показывает, как этого можно достичь. Обратите внимание, что объявлены оба свойства left и right. Это позволяет элементу <footer> охватить всю ширину нижней части страницы и он делает это не нарушая блочную модель, позволяя margin, border и padding применяться свободно.

HTML

<footer>Фиксированный подвал</footer>

CSS

body {
  background: #eaeaed;
}
footer {
  background: #2db34a;
  bottom: 0;
  left: 0;
  position: fixed;
  right: 0;
}

Демонстрация фиксированного позиционирования

Свойство z-index

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

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

Чтобы применить свойство z-index к элементу, необходимо сначала задать значение position как relative, absolute или fixed. То же, как если бы вы хотели применить свойства смещения блока.

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

Поменяйте значения свойства z-index и обратите внимание, как элементы меняют свой порядок.

HTML

<div class="box-set">
  <figure class="box box-1">Блок 1</figure>
  <figure class="box box-2">Блок 2</figure>
  <figure class="box box-3">Блок 3</figure>
  <figure class="box box-4">Блок 4</figure>
</div>

CSS

.box-set {
  background: #eaeaed;
  height: 160px;
  position: relative;
}
.box {
  background: #2db34a;
  border: 2px solid #ff7b29;
  position: absolute;
}
.box-1 {
  left: 10px;
  top: 10px;
}
.box-2 {
  bottom: 10px;
  left: 70px;
  z-index: 3;
}
.box-3 {
  left: 130px;
  top: 10px;
  z-index: 2;
}
.box-4 {
  bottom: 10px;
  left: 190px;
  z-index: 1;
}

Демонстрация z-index

Ресурсы и ссылки

Автор: Шэй Хоу
Последнее изменение: 03.09.2017
Редакторы: Влад Мержевич

Рекомендуем