Фиксированный, относительный, абсолютный и др.
Я работал разработчиком веб-интерфейса и довольно много использовал CSS. Я думал, что знаю почти все об основах CSS. Но откуда-то в глубине души я знал, что мои знания CSS не охватывают все. Я еще много чего не знаю. Поэтому я решил отправиться в путешествие, чтобы исследовать мир CSS, и это первая глава.
В этой статье я расскажу о функции CSS position, о которой все вы, возможно, уже знаете, но я постараюсь затронуть то, о чем вы, возможно, не слышали раньше.
До чтения
Я попытался организовать это с помощью некоторых примеров из моих исследований после прочтения спецификации CSS.
Конечно, было бы намного лучше прочитать официальную документацию, чтобы получить более точную информацию. Кроме того, информация может быть неверной или отсутствующей - я всегда буду признателен, если вы меня поправите.
Что такое сдерживающий блок?
В CSS существует концепция, называемая содержащим блоком (CB), о которой вы должны знать, прежде чем приступить к работе с CSS position.
Содержащий блок - это абстрактная область созданного вами элемента DOM. Он используется дочерними элементами, когда их нужно вычислить, когда речь идет о width, height, top и left. CB является критерием для его дочерних элементов. Другими словами, CB обычно называют родительским элементом - технически это неправильно, но многие документы считают CB равным родительскому элементу для упрощения объяснения.
Каждый элемент DOM создает свой CB при создании. CB точно такой же, как то, что его делает. Разница в том, что CB на самом деле не используется для рисования элементов DOM в браузере, поскольку они являются абстрактными концепциями. Они помогают дочерним элементам решить, какими должны быть их width или height или какими должны быть их top и left.
Отношения между элементами и CB показаны на диаграмме ниже:

CB может отличаться в зависимости от типа свойства position.
div {
position: fixed;
}
p {
position: absolute;
}
h1 {
position: relative;
}
section {
position: sticky;
}
div-fixedи всегда относится к области просмотраp-absoluteи относится к CB ближайшего родительского элемента,positionкоторого неstatic. Если ни один из них не соответствует условию, используется область просмотра.h1-relativeи следует обычному потоку DOM. Интересно, чтоrelativeэлементов используют координаты верхнего левого угла (0, 0) в качестве координаты CB. Я объясню это более подробно позже в этой статье.section-stickyотносится к CB родительского элементаnearest, в которомoverflowустановлен наscrollилиauto. Если ни один из них не соответствует условию, используется область просмотра. Я объясню это немного глубже позже в этой статье.
Положение Абсолютное
Элемент absolute не включен в обычный поток DOM. Его никогда не заботит положение или размер других элементов.
Положение элемента absolute может варьироваться в зависимости от того, к какому элементу он относится. По сути, элемент absolute относится к CB ближайшего родителя, свойство position которого не равно static.
<div id="outer">
Outer
<div id="inner">
Inner
<p id="p1">
Position Absolute
</p>
</div>
</div>
Предположим, у нас есть такое дерево DOM.
Позиция элемента inner теперь равна static, что является значением по умолчанию, когда свойство position не задано. Таким образом, p1 относится к CB outer.
Теперь позиция outer равна static, что является значением по умолчанию. Если ни один из родительских элементов не имеет значения, отличного от static, элемент absolute, в данном случае p1, относится к области просмотра.
Но я должен уточнить одну вещь. Элементы со значением absolute находятся вне нормального потока DOM. p1, однако, похоже, что он все еще в процессе. Действительно, положение элемента p1 следующее.
Первое, что вы можете увидеть, это margin из p1. p1 margin значения в этот момент равны 1 em, что преобразуется в 16 пикселей. По умолчанию на em влияет значение font-size родительского элемента, которое может быть унаследовано дочерними элементами. По умолчанию font-size в Chrome составляет 16 пикселей, что означает, что font-size родительского элемента p1 также имеет размер 16 пикселей, поскольку я не касался его. Таким образом, размер margin p1 также будет 16px * 1em = 16px.
#inner {
font-size: 10px;
}
Что, если я изменю inner font-size на 10 пикселей, учитывая, что inner является родительским элементом для p1?
Затем margins p1 также пересчитываются в 10 пикселей.
Более того, я также не задавал никаких значений свойству p1 top, но почему оно смещено от самого верхнего элемента на несколько пикселей? Казалось бы, это будет примерно сумма высот текстов «внешний» и «внутренний». Что ж, правильно.
Спецификация CSS описывает свойство top следующим образом:
«Top» и «bottom» - это «auto», а «height» - не «auto», тогда установите «top» в статическое положение ».
Другими словами, это означает, что даже если p1 является элементом с положением absolute, он работает как элемент с положением relative, если только его top или left не установлены.
#p1 {
top: 0;
}
После присвоения p1 значения top, наконец, он перешел на вершину CB.
Быстрая викторина
p1 все еще не на 0 слева. Это почему? (Подсказка: p1left по-прежнему auto.)
Позиция фиксированная
Элементы fixed очень похожи на элементы absolute, за исключением одного огромного различия - они всегда ссылаются на область просмотра как на CB.
В этом примере outer смещен сверху на 50 пикселей, а left и top установлены на 0 для position: fixed.
Вы можете видеть, что p1 прилипает к верхней части области просмотра.
Относительная позиция
relative элементов следуют обычному потоку DOM. Они всегда ссылаются на CB родительского элемента для размеров и позиций (top, left и т. Д.). Однако они ссылаются на позицию своего собственного CB, которая включена в поток DOM родительского элемента для начальной позиции.
Элементы relative и absolute имеют одну и ту же общую черту - они могут перекрывать другие элементы.
#p1 {
top: 50%;
}
p1 здесь на 50%. А поскольку p1 относится к CB родительского элемента, значение top будет составлять 50% от высоты родительского элемента. Но он не смещен от вершины CB родительского элемента. Это сверху его CB.
Есть разница между relative и absolute. absolute элементы должны отображаться в браузере независимо от того, что, если их display не установлен на none - например, relative элементы определяют, должны ли отображаться в браузере, в зависимости от свойства overflow их родительского элемента.
Я объясню это немного глубже. После создания элемента DOM он выполняет две задачи. Первая задача - установить CB, который выглядит точно так же, как и он сам, для своих дочерних элементов, которые позже обратятся к нему, когда им понадобится. Другая задача - определить CB, к которому он будет относиться при необходимости.
Это похоже на prototype в JavaScript. Когда дочерний элемент находится вне CB, на который он ссылается, браузер решает, отображать ли дочерний элемент или нет, просматривая свойство overflow элемента, CB которого ссылается дочерний элемент. Если для свойства overflow установлено значение scroll или auto, браузер должен сделать дочерний элемент видимым.
Более простое объяснение: если свойство overflow элемента, на который ссылается CB, равно scroll или auto, дочерний элемент будет отображаться.
Давайте проверим, правда ли это.
#inner {
overflow: scroll;
}
#p1 {
top: 200%;
}
inner имеет overflow: scroll, а p1 находится довольно далеко от вершины, поэтому сначала вы его не увидите. Но браузер позволяет вам увидеть это, если вы прокрутите вниз.
Напротив, он не будет отображаться, если inner’s overflow = hidden. А если overflow не задан, по умолчанию будет visible.
Позиция липкая
sticky очень полезно, но в то же время очень странно. Спецификация CSS описывает его как похожий на relative. sticky работает как relative, пока элемент не будет расположен в определенной пороговой точке. Определенная пороговая точка в этом контексте относится к значениям, которые определяют положение элемента, например top или left. Но чьи top и left?
Элемент sticky относится к CB ближайшего родительского элемента, для которого overflow установлено scroll. Если ни один из них не соответствует условию, элемент sticky относится к области просмотра.
Например, если top составляет 50 пикселей, элемент sticky работает как элемент relative, пока он не смещается от верха CB на 50 пикселей.
Дополнительная полезная информация
Если left и right установлены одновременно, left выигрывает. Если top и bottom установлены одновременно, top выигрывает.
Однако, если для свойства direction родительского элемента установлено значение rtl, справа налево, указанные выше приоритеты будут противоположными.
div {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
Выражение CSS выше на самом деле выглядит следующим образом.
div {
position: absolute;
top: 0;
left: 0;
}
Заключение
Я попытался систематизировать спецификацию CSS, описывающую позицию CSS, привел несколько примеров для лучшего понимания. Хотя я знал, как их использовать, я не знал, почему они работают так или работают так. Так что это исследование было для меня весьма значимым.
Кстати, position: sticky был добавлен в спецификацию позже других функций. Так что на данный момент не многие браузеры поддерживают эту функцию. Для этого есть полифилл. Надеюсь, я смогу поговорить об этом позже, если у меня будет возможность.