为什么overflow-x:hidden让我绝对定位的元素变得固定? [英] Why does overflow-x: hidden make my absolutely positioned element become fixed?
问题描述
我想弄清楚,为什么设置 overflow-x:hidden
到HTML页面的主体使我的元素 position:fixed
即使我将它设置为 position:absolute
。
效果更好理解此演示。
以下是代码:
HTML:
< div class ='background'> ; / div>
< div class ='page'>< / div>
< div class ='page'>< / div>
< div class ='page'>< / div>
< div class ='page'>< / div>
CSS:
html,body {
width:100%;
height:100%;
padding:0; margin:0;
overflow-x:hidden; / *如果我删除这行一切都是我期望它是! * /
}
div.page {
positon:relative;
width:100%;
height:100%;
min-height:100%;
border:1px solid red;
margin-bottom:200px;
}
div.background {
background:blue;
position:absolute;
width:100%;
height:20%;
}
问题
overflow-x:hidden
和定位之间的关系是什么?为什么设置该属性导致我的元素变成 position:fixed
而不是 position:absolute
?
元素仍然是 position:absolute
,但它看起来是固定的,和位置
,溢出
和框模型之间的交互。令人难以置信的是,这些行为都不是未指定的,或者是任何浏览器中的错误 - 实际上完全是通过设计,如果有点反直觉。
基本上归结为以下:
-
您在其他答案中添加
position:relative
有width:100%; height:100%;
在html和body上; -
由于视口不会滚动,绝对定位的元素也不会滚动。
奇怪的是,这也适用于IE6 。
< hr>
更长的解释:
-
溢出属性上的visufx.html#overflow =nofollow> spec ,这附带地包含您观察到的另一个示例,元素与
overflow:scroll
正在与绝对定位的后代元素交互,描述如下:
此属性指定当块容器元素的内容溢出元素的框时是否剪裁它。它影响所有元素的内容的剪辑,除了包含块是视口或元素的祖先的任何后代元素(及其相应的内容和后代)。
你绝对定位的元素是一个后代,它的包含块是视口(也是html元素的包含块),因为html和body都没有定位。这是根据规范的另一部分。
-
您拥有
width:100%; height:100%;
在html和body上;
然后,该规范说明了以下内容,进一步向下放在同一节:
UA必须将根元素上设置的overflow属性应用于视口。当根元素是HTMLHTML元素或XHTMLhtml元素,并且该元素具有HTMLBODY元素或XHTMLbody元素作为子代时,用户代理必须改为应用overflow属性从第一个这样的子元素到视口,如果根元素上的值是'visible'。用于视口的可见值必须解释为自动。传播值的元素必须具有visible的overflow的已使用值。
更简单:
-
如果html不是
overflow:visible ,但是body不是,将它应用到视口,并将body转换为overflow:visible
视口,然后将html转换为overflow:visible
。overflow:visible
。 li>
(设置
overflow-x
或overflow-y
指向可见 rel =nofollow>导致该元素的缩写overflow
不再等于visible
>。)
通常,这意味着视口应随html和body一起自然滚动,因为一次只能有一个滚动条。
但是... ,您还可以同时给予html和body的宽度和高度
100%
!这意味着100%的容器。 body的容器是html,html的容器是视口。但是,由于你实际上不能使用CSS来控制视口的大小 - 这完全由浏览器处理 - 你剩下的两个元素被约束为100%的可见部分的高度的视口(也称为折叠)。视口本身不必扩展到折叠以外,因为它的内容不需要比可见的更多的空间(注意绝对定位的元素从不被考虑)。因此,视口不会生成滚动条(也不会生成html);
如果您未设置
width
或height
属性,那么它们将默认为auto
,导致html和body都扩展其内容,并且总是与整个视口区域,包括折叠下面的区域。这可以防止主体产生滚动条,因为它总是伸展以适合其内容,因此您只能看到视口滚动条,绝对定位的元素将与页面的其余部分一起滚动。 -
-
由于视口不滚动,绝对定位的元素也不会滚动。
当你滚动的时候会发生什么,那就是你真的在滚动身体元素。因为绝对定位的元素被锚定到视口,它从不滚动,它似乎是固定的,而不是滚动。
顺便说一下,这也是为什么元素出现以在滚动条完全不滚动时与滚动条重叠。滚动条属于body,它在绝对定位的元素下面。如果您删除
overflow-x
声明或width
和height
声明从html和body,你看到的滚动条属于视口。但是,如果你定位body,滚动条仍然属于body,但元素也会成为body的子元素,所以它不会重叠滚动条。
I'm trying to figure out, why setting overflow-x: hidden
to body of an HTML page makes my element position: fixed
even if I set it to position: absolute
.
The effect is better understood in this demo.
Here is the code:
HTML:
<div class='background'></div>
<div class='page'></div>
<div class='page'></div>
<div class='page'></div>
<div class='page'></div>
CSS:
html, body {
width: 100%;
height: 100%;
padding: 0; margin: 0;
overflow-x: hidden; /* If I remove this line everything is how I expect it to be! */
}
div.page {
positon: relative;
width: 100%;
height: 100%;
min-height: 100%;
border: 1px solid red;
margin-bottom:200px;
}
div.background {
background: blue;
position: absolute;
width: 100%;
height: 20%;
}
Question
What's the relationship between overflow-x: hidden
and positioning? Why does setting that property cause my element to become position: fixed
instead of position: absolute
?
The element is still position: absolute
, but it appears fixed thanks to some rather complicated interactions between position
, overflow
and the box model. Incredibly, none of these behaviors is unspecified or a bug in any browser — it's actually completely by design, if a little counter-intuitive.
It basically boils down to the following:
An absolutely positioned element is anchored to the viewport unless any of its ancestors is positioned. (This is why adding
position: relative
to body works as suggested in another answer.)You have
width: 100%; height: 100%;
on both html and body; this prevents the viewport from ever expanding beyond its visible area, so the viewport never scrolls.Since the viewport doesn't scroll, neither does the absolutely positioned element. This causes it to appear fixed even though the rest of the page does scroll.
Oddly enough, this works on IE6 too.
Longer explanation:
An absolutely positioned element is anchored to the viewport unless any of its ancestors is positioned.
The spec on the
overflow
property, which incidentally contains another example of the same issue you're observing where an element withoverflow: scroll
is interacting with an absolutely positioned descendant element, states the following:This property specifies whether content of a block container element is clipped when it overflows the element's box. It affects the clipping of all of the element's content except any descendant elements (and their respective content and descendants) whose containing block is the viewport or an ancestor of the element.
Your absolutely positioned element is a descendant whose containing block is the viewport (also the containing block of the html element), because both html and body are not positioned. This is according to another section of the spec. This prevents overflow clipping on html and body from having any effect on your absolutely positioned element since it's anchored to the viewport.
You have
width: 100%; height: 100%;
on both html and body; this prevents the viewport from ever expanding beyond its visible area, so the viewport never scrolls.The spec then states the following, further down the same section:
UAs must apply the 'overflow' property set on the root element to the viewport. When the root element is an HTML "HTML" element or an XHTML "html" element, and that element has an HTML "BODY" element or an XHTML "body" element as a child, user agents must instead apply the 'overflow' property from the first such child element to the viewport, if the value on the root element is 'visible'. The 'visible' value when used for the viewport must be interpreted as 'auto'. The element from which the value is propagated must have a used value for 'overflow' of 'visible'.
To put it more simply:
If html is not
overflow: visible
, apply that to the viewport instead, and turn html tooverflow: visible
. Theoverflow
value given to body is not affected.If html is
overflow: visible
, but body is not, apply that to the viewport instead, and turn body tooverflow: visible
.
(Setting
overflow-x
oroverflow-y
to anything other thanvisible
for an element causes the shorthandoverflow
to no longer be equal tovisible
for that element.)Normally, this means the viewport should scroll naturally along with html and body, since only one scrollbar should exist at a time.
However... you also give both html and body a width and height of
100%
! That means 100% those of its container. The container of body is html, and the container of html is the viewport. But since you can't actually use CSS to control the size of the viewport — that's entirely handled by the browser — you're left with the two elements being constrained to 100% the height of the visible portion of the viewport (also known as the fold). The viewport itself does not have to expand beyond the fold since none of its contents require more space than is visible (note that absolutely positioned elements are never taken into account). The viewport therefore does not generate a scrollbar (and neither does html); the scrollbar that you see belongs to body.If you had not set the
width
orheight
properties, then they would have defaulted toauto
, causing both html and body to expand with their contents and always be the same size as the entire viewport area, including the area below the fold. This prevents body from ever generating a scrollbar because it will always stretch to fit its contents, so you only see the viewport scrollbar, and the absolutely positioned element will scroll with the rest of the page.Since the viewport doesn't scroll, neither does the absolutely positioned element. This causes it to appear fixed even though the rest of the page does scroll.
What happens when you scroll, then, is that you're really scrolling the body element. Since the absolutely positioned element is anchored to the viewport, which never scrolls, it appears to be fixed instead of scrolling.
By the way, this is also why the element appears to overlap the scrollbar when it doesn't scroll at all. The scrollbar belongs to body, which is beneath the absolutely positioned element. If you remove the
overflow-x
declaration or thewidth
andheight
declarations from html and body, the scrollbar that you see belongs to the viewport instead. However, if you position body, the scrollbar still belongs to body, but the element also becomes a child of body so it won't overlap the scrollbar.
这篇关于为什么overflow-x:hidden让我绝对定位的元素变得固定?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!