Почему не работает верх: 0 работает над абсолютно позиционируемыми элементами относительно тела?
В приведенном ниже коде вы можете видеть, что h1
отбрасывает тело, а абсолютно позиционированный блок .absolute
не прилипает к вершине. Но вы также можете видеть, что тот же самый блок прикреплен к вершине его родительского .wrapper
. Почему?
Я не спрашиваю, как это сделать. Я знаю, как, например. padding вместо margin на h1, или clearfix для родителя и т.д.
Меня интересует только одно: почему маркер h1
отбрасывает body
, но не нажимает .wrapper
?
body {
position: relative;
margin: 0;
padding: 0;
overflow: hidden;
background-color: silver;
}
.absolute {
position: absolute;
top: 0;
left: 0;
width: 50px;
height: 50px;
background-color: darkblue;
}
.wrapper {
position: relative;
overflow:hidden;
width: 50%;
height: 200px;
overflow: hidden;
background-color: yellow;
}
.wrapper > .absolute {
background-color: darkcyan;
}
<div class="absolute"></div>
<h1>Some title</h1>
<div class="wrapper">
<div class="absolute"></div>
<h1>Some title</h1>
</div>
Ответы
Ответ 1
Как уже упоминалось, содержащий блок абсолютно позиционированного элемента верхнего уровня body
, поскольку body
относительно позиционируется. Когда поле h1
обрушивается с таковым body
, это заставляет маржу влиять на body
, а в свою очередь абсолютно который он содержит. И наоборот, если body
не было относительно позиционировано, абсолютно позиционированный элемент привязывался бы к исходному содержащему блоку и придерживался вершины видового экрана, не подверженного влиянию каких-либо эффективных полей на body
(поскольку body
больше не его содержащий блок).
Что касается того, почему серебристый фон выходит за пределы элемента body
, по дизайну:
3.11.1. Фон холста и корневой элемент
Фон корневого элемента становится фоном холста, а его область рисования фона распространяется на весь холст. Однако любые изображения имеют размер и расположение относительно корневого элемента, как если бы они были окрашены только для этого элемента. (Другими словами, область фонового позиционирования определяется как для корневого элемента.) Корневой элемент снова не нарисовал этот фон, т.е. Используемое значение его фона прозрачно.
3.11.2. Фон холста и HTML <body> Элемент
Для документов, корневым элементом которых является элемент HTML HTML
или элемент XHTML HTML
: если вычисленное значение "background-image на корневом элементе" равно "none" и его "фоновый цвет" является прозрачным, пользователь агенты должны вместо этого распространять вычисленные значения свойств фона из этого элемента сначала HTML body
или XHTML body
дочерний элемент. Используемые значения этих свойств фона элемента BODY являются их начальными значениями, а распространяемые значения обрабатываются так, как если бы они были указаны в корневом элементе. Рекомендуется, чтобы авторы HTML-документов указывали фон canvas для элемента body
, а не элемент HTML
.
Цвет фона по умолчанию для корневого элемента всегда transparent
, поэтому установка цвета фона в элементе HTML
предотвращает истечение серебристого фона из элемента body
(и вы увидите, что инспектор находится в факт не лжет вам):
html {
background-color: white;
}
body {
position: relative;
margin: 0;
padding: 0;
overflow: hidden;
background-color: silver;
}
.absolute {
position: absolute;
top: 0;
left: 0;
width: 50px;
height: 50px;
background-color: darkblue;
}
.wrapper {
position: relative;
overflow:hidden;
width: 50%;
height: 200px;
overflow: hidden;
background-color: yellow;
}
.wrapper > .absolute {
background-color: darkcyan;
}
<div class="absolute"></div>
<h1>Some title</h1>
<div class="wrapper">
<div class="absolute"></div>
<h1>Some title</h1>
</div>
Ответ 2
Это потому, что сворачивает поля. Как отключить его, вы можете прочитать в некоторых статьях/ответах, например, this.
Вы используете overflow: hidden
для .wrapper
, и он отключает сбрасывание полей для этого блока. Из спецификация:
Поля поля с "переполнением, отличным от" видимы, не сворачиваются с его дочерними полями.
Но, похоже, overflow: hidden
не работает для <body>
, потому что если я задаю
height: 0
/max-height: 0
он тоже не работает:
body {
height: 0;
max-height: 0;
}
<div>Some test text</div>
Ответ 3
Это еще один пример явления, известного как margin-collapsing
.
Я попытаюсь объяснить, что происходит:
Когда вы перемещаете div.absolute
с абсолютным положением, он вытаскивает его из потока содержимого. Это приводит к тому, что первый h1
будет действовать как первый ребенок его родителя, который в этом случае body
.
Поля h1
затем сбрасываются за пределы тела из-за разворота краев. Вот почему top: 0;
не находится в верхнем левом углу окна просмотра. Он находится в верхнем левом углу body
.
Если вам нужно заставить это работать, добавьте html {position: relative; overflow: hidden:}
.
Ответ 4
Это интересное поведение с небольшим количеством документации, которую можно найти в Интернете (по крайней мере, при базовом поиске).
Начну с того, что я не знаю, почему абсолютно позиционированный блок не выравнивается с углом body
, как и следовало ожидать. Но вот несколько замечаний:
-
Ожидаемое позиционирование работает на IE11. Этот разрыв существует в Chrome и FF.
-
Если вы удалите position: relative
из body
, ожидаемое позиционирование работает (как проверено в Chrome, FF и IE11). демонстрация
-
Если вы применяете только 1px padding
к body
, он также работает кросс-браузер. демонстрация
-
Если вы добавите границу в body
, она также будет работать. демонстрация
UPDATE
В качестве быстрого добавления к @BoltClock принятому отвечу эту проблему можно было легко проиллюстрировать и понять, просто добавив цвет фона корневому элементу исходного кода...
html { background-color: red; }
демонстрация
... и удалив поле по умолчанию на h1
:
h1 { margin: 0; }
демонстрация
Ответ 5
Это вызвано тем, что h1
имеет значение по умолчанию, которое сохраняет body
отдельно от h1
и его sibling .absolute
.
Итак, все, что вам нужно сделать, это reset margin в h1
, как вы это делали для body
:
фрагмент с каждым сбросом поля
body {
position: relative;
margin: 0;
padding: 0;
overflow: hidden;
background-color: silver;
}
h1 {
margin: 0;
/*if you want to see full text, put this into the flow*/
position:relative;
z-index:1;
}
.absolute {
position: absolute;
top: 0;
left: 0;
width: 50px;
height: 50px;
background-color: darkblue;
}
.wrapper {
position: relative;
overflow: hidden;
width: 50%;
height: 200px;
overflow: hidden;
background-color: yellow;
}
.wrapper > .absolute {
background-color: darkcyan;
}
<div class="absolute"></div>
<h1>Some title</h1>
<div class="wrapper">
<div class="absolute"></div>
<h1>Some title</h1>
</div>