Наверняка вы слышали о свойстве position
, и скорей всего, со значением absolute
. Но при применении этого свойства к какому либо элементу могли столкнуться со странным его поведением.
Что касается самого свойства position, то по умолчанию для всех элементов оно имеет значение static
, но может принимать и другие значения:
1 | position: static / relative / absolute / fixed / sticky |
Для 4-х последних значений свойства position (т.е.. всех, кроме static) можно назначить координаты с помощью свойств left - слева и right - справа (по горизонтали), а также top - сверху и bottom - снизу (по вертикали):
1 2 3 4 5 6 7 8 9 10 11 | #some { position: relative; left: 10%; top: 20px; } #temp { position: relative; right: 0; top: 2em; } |
Также для всех позиций, кроме static
, можно задать свойство z-index
, которое определяется цифрой (0, -1, 10, 999) без указания единиц, т.к. это свойство показывает, на каком уровне (или слое) находится спозиционированный элемент по сравнению с другими позиционированными элементами (выше или ниже). Чем меньше цифра, тем ниже будет находится элемент среди себе подобных (т.е. тех элементов, у которых свойство position имеет значение relative, absolute, fixed или sticky. Для элементов с position: static свойства z-index или любая из координат (left, right, top, bottom) будут проигнорированы.
1 2 3 4 5 6 | #card { position: absolute; top: 10px; left: 20px; z-index: 1; } |
Элементы с position: relative
Для таких элементов визуальное отображение не меняется до тех пор, пока не заданы координаты. Т.е. относительно позиционированные блоки не смещаются и не меняют своей ширины в отличие от абсолютно или фиксированно позиционированных элементов.
Если вы добавите координаты top
и left
с положительными значениями, то элемент сместиться вниз и вправо, с отрицательными значениями - вверх и влево относительно своего первоначального положения. Можно сравнить относительно позиционированный элемент с собакой на цепочке, которая привязана к колышку - бегать она может только относительно этого колышка и на расстояние, не превышающее длину цепи - для нашего элемента это расстояние, заданное с помощью координат.
В примере ниже вы можете изменять координаты выделенного блока с position: relative
, используя ползунки или поля ввода. Обратите внимание, что при заданных координатах left
и top
изменения для right
и bottom
не учитываются - так работает приоритет координат при позиционировании. Сам элемент смещается в разные стороны от своего первоначального положения, оставляя пустое место там, где был изначально и накладываясь на контент до и после него.
Следует обратить внимание на то, что элементы с position: relative
без заданных координат или с нулевыми координатами никак не выделяются из общего, статического потока элементов. Тем не менее, они как бы приобретают новый статус в глазах браузера, приподнимаются над своими соседями и, что самое главное, - позволяют размещать внутри себя элементы с position: absolute
. Об этом читайте ниже.
Элементы с position: absolute
При абсолютном позиционировании элемента без указания координат он будет привязан своим левым краем к левому краю родительского контейнера, но его ширина изменится: если текста мало - уменьшится, если текста (контента) много, то ширина блока увеличится, и он "вылезет" за пределы контейнера справа.
Как только этому элементу будут заданы координаты, он "сбежит" из родительского контейнера и разместится относительно body
, заняв при этом все доступное пространство внутри body
, если имеет приличное количество контента. Если контента мало (1-2 слова, например), то блок "примостится" сверху статического контента, не оставив и следа там, где был в первоначальной разметке.
Чтобы "вернуть беглеца" обратно в пределы родительского элемента, необходимо родителю задать свойство ... position: relative
, причем без указания каких-либо координат для него. В этом случае координаты дочернего элемента будут отсчитываться в пределах родительского контейнера, что, как правило, значительно удобнее.
В примере ниже вы можете посмотреть, как изменяется положение и вид блока, которому назначили свойство position: absolute
. Для этого вам нужно будет нажать на соответствующую кнопку внизу примера. Обратите внимание, что элемент уменьшил свою ширину. Высота осталась примерно такой же за счет добавления кнопки вместо второго параграфа. Учтите, что первоначально для элемента с position: absolute
ни одна координата не задана. Они добавятся только после того, как вы начнете перемещать ползунки. Кроме того, для абсолютно позиционированного элемента можно назначить все 4 координаты (left, top, right, bottom
). Если их значения не будут противоречить друг другу, элемент ... растянется. Нажмите на кнопку "Все координаты в 0" и посмотрите на ширину элемента. Она займет все доступное пространство внутри body
или элемента-родителя. Кстати, кнопка "Вернуть в пределы родительского элемента" позволит вам посмотреть на разницу в расчете координат. В самом блоке есть кнопка "Убрать координаты", которая поможет в случае слишком большой растяжки элемента с position: absolute
.
Вы можете поэкспериментировать с примером, рассматривающим абсолютное позиционирование, в отдельной вкладке. Красной двойной рамкой в этом примере выделены размеры body
, синей точечной - пределы родительского элемента.
Абсолютно позиционированные элементы часто используются внутри слайдеров. Это позволяет создавать различные эффекты при переходе от одного слайдера к другому.
Элементы с position: fixed
Это фиксированные элементы, которые без указания координат "прилипают" к левому краю родительского блока и не смещаются при прокрутке страницы. Как только координаты заданы, элемент "открепляется" от родителя и позиционируется относительно окна просмотра, т.е. для нас это относительно body
. Опять-таки он не смещается при прокрутке страницы, т.к. зафиксирован в определенных координатах.
В примере ниже вы можете назначить синему элементу свойство position: fixed
, нажав на кнопку "Добавить синему блоку position: fixed". До тех пор, пока вы не начали изменять координаты этого элемента с помощью ползунков или цифр, он будет держаться в пределах родительского элемента. Но, как только вы задали две координаты, блок вырвется в координаты документа и не вернется внутрь родителя, даже, если вы назначите последнему position: relative
. Это видно по изображению ниже.
Остальное его поведение подобно абсолютно позиционированному блоку: изменение ширины и высоты, растяжение при назначении всех координат, если значения координат не противоречат друг другу.
В этом примере красная рамка ограничивает размеры body
, синяя - размеры родительского элемента.
Протестируйте пример с фиксированным позиционированием элемента в отдельной вкладке.
Обратите внимание, что при назначении отрицательных координат элементы с position: absolute и fixed
уходят под рамки браузера (элемента), поэтому их часто используют для создания выезжающих меню, форм, баннеров и кнопок для прокрутки вверх, которые прячутся, когда не нужны.
Практический пример position:fixed
для footer и создания прокручиваемого контента
В примере ниже position: fixed
назначен для футера. Основной контент с position: relative
прокручивается до тех пор, пока снизу не покажется футер. Обратите внимание на то, что при создании медиа-запросов приходится изменять height
или min-height
для футера.
See the Pen A CSS slide-out fixed footer by Elen (@ambassador) on CodePen.
Практический пример position: absolute
и position:fixed
В этом примере с codepen.io абсолютно позиционировано изображение внутри разметки header
+ задано фоновое изображение в css-свойствах для того же header
. Заголовок h1
имеет position:fixed
. В результате прокрутка фона поверх изображения и заголовка дает эффект скрытия текста и нижнего изображения "под облаками" наполовину прозрачной png-картинки.
See the Pen Fixed Disappearing Scrolling Header by Dudley Storey (@dudleystorey) on CodePen.
Элементы с position: sticky
Такие элементы нужны для оформления содержания или заголовков каких-либо блоков внутри одной и той же статьи. Они никак не выделяются из текста до назначения им координат, зато после указания, как правило, координаты top
, прокручиваются только до значения этой координаты, "прилипают" к краю контейнера и не двигаются при прокрутке страницы.
Следует учитывать, что это новое значение давно используемого свойства, и для некоторых браузеров необходимо добавление вендорных префиксов:
1 2 3 4 5 | #sticky{ position: -webkit-sticky; position: sticky; top: 10px; } |
В примере ниже вам необходимо прокрутить файл, разбитый на несколько секций, чтобы увидеть, как каждый заголовок типа "Section 1" "прилипает" к верхнему краю из-за назначенного ему свойства top: 0
. После того, как его сменяет Section 2, "прилипает" уже этот заголовок.
Код для заголовков здесь таков:
1 2 3 4 5 6 7 8 9 | h2 { background-color: #fff; color: #ff9300; margin: 0; padding: 10px 0; position: -webkit-sticky; position: sticky; top: 0; } |
Фоновый цвет для заголовка нужен, чтобы его текст лучше читался. В примере он белый и совпадает с цветом фона страницы. Также имеет смысл убрать прозрачные внешние отступы (margin: 0
) и вместо них добавить внутренние (padding: 10px 0
), чтобы фоновый цвет занимал больше пространства.
Свойство position: sticky
достаточно удобное использовать для длинных статей, разделенных на части, однако пока применять его нужно с осторожностью из-за неполной поддержки. Посмотреть, какие браузеры поддерживают это значение, можно на сайте caniuse.com.
See the Pen Pretty Sticky by Burmese Potato (@BurmesePotato) on CodePen.
Использование свойства z-index
До этого момента мы не рассматривали порядок наложения позиционированных элементов друг на друга, т.к. у нас был только один такой элемент в тестовых файлах. Тем не менее ситуация, когда в пределах одного блока может быть несколько относительно, абсолютно или фиксированно спозиционированных элементов, часто встречается на практике. Тогда следует использовать свойство z-index
, позволяющее определять порядок наложения спозиционированных блоков друг на друга. Поскольку раскладка элементов определяется в основном в двумерном пространстве, т.е. по осям X и Y, то определение наложения происходит по оси Z, перпендикулярной плоскости экрана. Каждый их таких элементов может находиться как ниже, так и выше других объектов веб-страницы при заданном свойстве z-index
. Рассмотрим его подробнее.
Свойство z-index
задается цифрой. Это может быть 0, положительное или отрицательное значение. По умолчанию у каждого позиционированного элемента (position: relative | absolute | fixed
) свойство z-index
имеет значение auto
. В этом случае каждый следующий в разметке элемент с заданным свойством position из перечисленных значений накладывается на предыдущий. При явном указании z-index
в виде числа элемент перемещается выше или ниже соседних элементов.
В примере ниже представлены карты, для которых задано абсолютное позиционирование и координаты left
и top
таким образом, чтобы они накладывались друг на друга. Разметка и css-свойства этого примера таковы:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | <style> img { display: block; position: absolute; cursor: pointer; } #ten { left: 70px; top: -20px; } #jack { left: 50px; top: 30px; } #queen { left: 80px; top: 60px; } #king { left: 130px; top: 30px; } #ace { left: 110px; } </style> <img src="img/diamonds_10.gif" alt="10 of diamonds" height="96" width="70" id="ten"> <img src="img/diamonds_jack.gif" alt="Jack of diamonds" height="96" width="70" id="jack"> <img src="img/diamonds_queen.gif" alt="Queen of diamonds" height="96" width="70" id="queen"> <img src="img/diamonds_king.gif" alt="King of diamonds" height="96" width="70" id="king"> <img src="img/diamonds_ace.gif" alt="Ace of diamonds" height="96" width="70" id="ace"> |
По умолчанию все карты имеют z-index: auto
и накладываются в порядке размещения в html-коде. Вы можете щелкнуть по любой карте (она приобретет красную обводку) и изменять свойство z-index
с помощью ползунка или цифр в специальном поле.
Обратите внимание на то, что отрицательный z-index
закрывает доступ к элементу - вы уже не можете выделить его, чтобы назначить другое значение. Если бы внутри этого элемента были ссылки, вы бы не смогли щелкнуть по ним. Поэтому использовать отрицательные значения z-index
нужно с осторожностью. Воспользуйтесь кликом на тексте "значение auto для всех карт", чтобы вернуть начальное состояние элементам.
Контекст наложения (stacking context)
Использование z-index
вроде бы не предпоагает никаких сложностей. Обычно их и не бывает. Однако в спецификации есть один нюанс, связанный с термином контекст наложения (stacking context). Это концепция трехмерного расположения html-элементов вдоль оси Z, перпендикулярной к пользователю, находящемуся перед экраном. Обычно эти элементы занимают место по порядку друг за другом, но есть ряд свойств, который меняет позицию элемента по оси Z.
Контекст может формироваться в любом месте документа и любым элементом, который соответствует одному из перечисленных условий:
- является корневым элементом (
html
), - позиционирован абсолютно (
position:absolute
) или относительно (position:relative
) сz-index
значением отличным от"auto"
, или имеетposition: fixed
- flex-элемент
с z-index
отличным от"auto"
, чей родительский элемент имеет свойствоdisplay: flex|inline-flex
, - элементы с
opacity
меньше чем 1. (См. the specification for opacity), - элементы с
transform
отличным от "none", - элементы с
mix-blend-mode
значением отличным от "normal", - элементы с
filter
значением отличным от "none", - элементы с
isolation
установленным в "isolate", - если мы указываем элементу атрибут
will-change
при этом не обязательно присваивать ему значения (См. эту статью) - элементы с
-webkit-overflow-scrolling
установленым в "touch"
В том, что касается z-index
, контекст наложения работает таким образом, что при назначении родительскому элементу одного из перечисленных свойств, порядок наложения соседних элементов несколько изменится при наличии у них вложенных элементов с позиционированием.
В примере ниже у нас есть несколько элементов с относительным (position: relative
) или абсолютным (position: absolute
) позиционированием. Разметка этого примера такова:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <div id="d1">div#1 with position:relative <br> z-index: 5 </div> <div id="d2">div#2 with position: absolute <br> z-index: auto <div id="d4">div#4 with position: relative; <br>z-index: 6</div> <div id="d5">div#5 with position: absolute; <br>z-index: 3</div> <div id="d6">div#6 with position: relative; <br>z-index: 2</div> <div id="d7">div#7 with position: relative; <br>z-index: -1</div> </div> <div id="d3">div#3 with position:relative <br> z-index: 2 </div> |
Каждому div-у в этой разметке задан z-index
. Тестовым элементом у нас является div#2
, для которого изначально z-index
НЕ задан, т.е. он имеет значение auto
по умолчанию. Желтый div#4 с z-index:6
, который размещен внутри div#2
как дочерний элемент, сейчас накладывается на зеленый div#1 с z-index:5
, т.к. его цифра 6 предполагает более высокое расположение позиционированного элемента по оси Z по сравнению с цифрой 5. Однако стоит задать div#2
свойство z-index: 1 или 2
- и его вложенные элементы спрячутся под зеленые блоки, т.к. контекст наложения сейчас учитывает z-index
только родительского элемента в ряду с его соседними - это div#1 и div#3
.
Второй способ изменить контекст наложения div#2
- это задать этому div-у свойство opacity < 1
при стандартном значении свойства z-index: auto
. В нашем приме opacity
уменьшается до значения 0.7
, чтобы это было четко видно, хотя достаточно назначить и 0.99
, которое визуально почти не отличается от 1
.
Все остальные значения z-index
для div#2
поднимают его выше или опускают ниже зеленых блоков, но все вложенные в него элементы определяют свое расположение по оси Z относительно друг друга, но не относительно соседних элементов родителя.
Ссылка по теме на developer.mozilla.org
Очень крутая статья. Но остался вопрос. У меня такая структура (Это слайдер в карточке товара)
И я не могу решить вопрос - как в этом случае сделать высоту главного блока равного контенту? Решается исключительно задав параметр height в пикселях. Но, как видно из примера, высота всегда разная, в зависимости от ширины. Как только ни пробовал - высота блока схлопывается и ничего не могу поделать...
Добрый день.
Вы привели css-код, но не показали разметку. Полагаю, что у вас все элементы вложены в
.brazzers-wrapper
.От чего зависит размер вашего
.brazzers-wrapper
? От размера изображения? Размера текста? От того и другого?В принципе, можно сделать для
.brazzers-wrapper
следующее:То есть мы задаем некую постоянную высоту для
.brazzers-wrapper
(в примере 300px, но можно и другую) и обрезаем все, что выходит за ее пределы с помощьюoverflow: hidden
. Для изображения задаем максимальную ширину, как у его контейнера.Еще есть вариант попробовать использовать в разметке Flexbox-модель с
flex-direction: column
.