Skip to content

Latest commit

 

History

History
119 lines (85 loc) · 19.5 KB

text.md

File metadata and controls

119 lines (85 loc) · 19.5 KB

Вводная

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

  • static
  • relative
  • absolute
  • fixed
  • sticky

relative

Первый тип позиционирования – относительное. Определение (перевод отсюда)

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

  • table-row-group, table-header-group, table-footer-group и table-row смещаются относительно своей нормальной позиции в таблице. Если ячейка таблицы растягивается на несколько строк, то только ячейки, находящиеся в соответствующих относительно спозиционированных строках имеют смещение (если что у меня не получилось заставить это работать).
  • table-column-group, table-column не смещаются относительно соответствующей колонки и по факту никакого эффекта от position: relative не происходит
  • table-caption и table-cell смещаются относительно нормального положения в таблиец. Если ячейка объединяет несколько, то все они смещаются относительно своего нормального положения.

Относительно спозиционированный блок создаёт новый содержащий блок – это самое распостранное использование данного значения.

Смещение регулируется свойствами top, left, right, bottom. Красивого свойства для задания всех значений разом нет. Относительные значения считаются от размеров содержащего блока. Задание данных свойств никак не изменяет размеры самого блока.

По-умолчанию, когда left/right auto, то они равны 0. Когда кто-то один из left/right auto, то по факту выполняется равенство left = -right. Если же задать и left, и right то одно из свойств просто игнорируется. Какое именно зависит от свойства direction. ltr – right, rtl – left.

Примерно такой же алгоритм работы у top/bottom, за исключением двух но. Во-первых, если содержащему блоку не задана высота, то top/bottom заданные в процентах всегда будут равны auto, т.е 0. И второе, что нет свойства, которое бы меняло приоритеты, при задании top/bottom вместе. Т.е top всегда побеждает bottom.

Содержащий блок

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

Содержащий блок для static, relative и sticky элементов определяется следующим образом (ссылка):

  • Для корневых элементов это премоугольник размерами с вьюпорт, который привяз к размерам видимой области окна для непрерывных страниц или страницы для листаемых источников. Такой содержащий блок называется стартовым (инициализационным). Значения свойств 'direction' и 'block-progression' в таком случае будут такими же как и у корневого
  • В остальных случаях содержащий блок это прямоугольник, который формируется границами контентной области ближайшего родителя блочного уровня. В том числе это может быть анонимный бокс.

Содержащий блок у fixed элементов – это всегда viewport. Во всех случаях.

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

  • Если этот родитель блочного уровня, то прямоугольник содержащего блока определяется padding'овыми границами
  • Если этот родитель строчного уровня, то:
    • Если direction ltr, то левая верхняя граница содержащего блока будет равна левой верхней границе первого элемента внутри абсолютного блока, а нижняя правая граница будет равна нижней правой границе последнего ребенка абсолютно спозиционированного блока (грубо говоря, высота блока определяется под контент, ширина – максимум из ширин блоков внутри)
    • При direction rtl, всё точно так же, только уже рост блока идёт от правой границы.
  • Во всех остальных случаях берется стартовый блок (чаще всего это viewport).

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

Примеры

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

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

У абсолютно позиционированного блока есть ограничение сверху на размер, оно выражается формулой:

left + margin-left + border-left-width + padding-left + width + padding-right + border-right-width + margin-right + right = width содержащего блока

Вот таблица рассчёта параметров, ✔ – означает auto значение данного параметра. Примечание, предполгается, что direction равен ltr.

left width right margin-left margin-right Результат
любое любое авто margin -> 0 пример / иначе margin-left побеждает margin-right пример, left -> то же как static, width -> под контент, right -> вычисляется по формуле
margin-left -> оставшееся место (вычисляется), пример
margin-right -> оставшееся место (вычисляется), пример
свободное место делится пополам между margin'ами, пример
right -> auto, пример
любое любое margin -> 0, left -> то же как static, width -> сколько указано, right -> вычисляется, пример
любое любое margin -> 0, left -> вычисляется, width -> под контент, right -> сколько указано, пример
любое любое margin -> 0, left -> сколько указано, width -> под контент, right -> вычисляется, пример
любое любое margin -> 0, right вычисляется по формуле, пример
любое любое margin -> 0, width вычисляется по формуле, пример
любое любое margin -> 0, left вычисляется по формуле, пример

Если ширина и высота имеют вычисленные значения auto, при этом у элемента есть внутренняя ширина (например у картинок), то используется внутреннее значение.

Если ширина и высота имеют значение auto, при этом у элемента нет внутренней ширины, но есть внутренняя высота и пропорция; или если ширина auto, высота имеет какое-то значение отличное от auto и у элемента есть внутреннее значение пропорции, то ширина вычисляется по формуле:

(высота) * (внутренняя пропорция)

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

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

Если же ширина auto и ничего выше не подходит, то ширина элемента просто становится 300px. Если 300px – это больше ширины экрана, тогда девайс должен выставить такое значение, которое будет назначено ширине максимального большого прямоугольника с пропорциями 2:1, который вмещается в экран девайса.

После вычисления ширины для позиционирования элемента применяются следующие правила:

  1. Если left и right auto и direction статического родителя ltr, то left будет равно left статического контейнера, а right вычисляется. При rtl соответственно наоборот.
  2. Если left auto, right задано, то если margin-left и margin-right auto, то они автоматически равны 0, а затем вычисляется left
  3. То же самое что и в 2, но наоборот при left не auto.
  4. Если margin-left и margin-right всё ещё auto, то в уравнение вводится доп.условие, что вычисленные значения margin-left/margin-right должны быть одинаковыми. Это не относится к ситуации, когда при этом вычисленные значения будут отрицательными, тогда при ltr direction содержащего блока margin-left будет равен 0 и вычисляется margin-right. Для rtl всё наоборот
  5. Если всё ещё есть auto значения, то нужно вычислить их по уравнению для незамещаемых элементов
  6. Если значений больше, чем можно применить, то нужно проигнорировать значение свойства left (при ltr).

Здесь правила похожи, есть формула:

top + margin-top + border-top-width + padding-top + height + padding-bottom + border-bottom-width + margin-bottom + bottom = высота содержащего блока

Если top, bottom и height имеют значение auto. То auto значения margin-top/bottom становятся 0. Затем top присваивается значение top в статической позиции, и затем применяется правило 3, ниже.

Если наоборот из тройки ни одно не имеет значения auto, то для разрешения auto margin-top/bottom вводится доп.ограничение, что их значения должны быть равны. Если при этом значений больше чем нужно, то игнорируется значение bottom.

Во всех остальных случаях auto margin-top/bottom присваивается значение 0 и выбирается одно из следующих правил:

  1. If top and height are auto and bottom is not auto, then the height is based on the Auto heights for block formatting context roots, and solve for top.
  2. If top and bottom are auto and height is not auto, then set top to the static position, then solve for bottom.
  3. If height and bottom are auto and top is not auto, then the height is based on the Auto heights for block formatting context roots, and solve for bottom.
  4. If top is auto, height and bottom are not auto, then solve for top.
  5. If height is auto, top and bottom are not auto, then solve for height.
  6. If bottom is auto, top and height are not auto, then solve for bottom.

Плавающий или флоат (транскрипция float) блок – это блок, который сдвигается влево или вправо на текущей строке. Наиболее интересная характеристика таких блоков – это то что контент выстраивает вдоль границы такого блока.

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

Если в строке не достаточно места, то блок смещается вниз до тех пор, пока не находит места для себя. При этом float блоки в порядке объявления в DOM'е формируют отдельный float поток и при выборе места для следующего блока браузер изначально смотрит на позицию последнего блока во float потоке.

Для более понятного понимания float'ов можно использовать аналогию с тетрисом, в котором при размещении блока браузер руководствуется правилом: вниз и влево. Простой пример