7

我试图弄清楚,为什么设置overflow-x: hidden为 HTML 页面的正文会使我的元素position: fixed即使我将其设置为position: absolute.

在这个演示中效果更好地理解。

这是代码:

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 {
  position: relative;
  width: 100%;
  height: 100%;
  min-height: 100%;
  border: 1px solid red;
  margin-bottom: 200px;
}

div.background {
  background: blue;
  position: absolute;
  width: 100%;
  height: 10%;
}
<div class='background'></div>
<div class='page'></div>
<div class='page'></div>
<div class='page'></div>
<div class='page'></div>

问题

和定位有什么关系overflow-x: hidden?为什么设置该属性会导致我的元素变为position: fixed而不是position: absolute

4

2 回答 2

26

元素仍然是position: absolute,但由于position,overflow和盒子模型之间的一些相当复杂的交互作用,它看起来是固定的。令人难以置信的是,这些行为都不是未指定的,也不是任何浏览器中的错误——它实际上完全是设计使然,如果有点违反直觉的话。

它基本上归结为以下几点:

  • 一个绝对定位的元素被锚定到最初的包含块,除非它的任何祖先被定位。(这就是为什么添加position: relative到 body 工作如另一个答案中所建议的那样。)

  • 你有width: 100%; height: 100%;html 和 body;这可以防止初始包含块扩展超出视口(可见区域),因此初始包含块永远不会滚动。

  • 由于初始包含块不滚动,因此绝对定位的元素也不滚动。即使页面的其余部分确实滚动,这也会导致它看起来是固定的。

奇怪的是,这也适用于 IE6


更长的解释:

  • 一个绝对定位的元素被锚定到最初的包含块,除非它的任何祖先被定位。

    该属性的规范overflow顺便说一句,包含您正在观察的同一问题的另一个示例,其中元素与overflow: scroll绝对定位的后代元素交互,说明如下:

    此属性指定块容器元素的内容在溢出元素的框时是否被剪裁。它影响所有元素内容的剪辑,除了包含块是元素的视口或祖先的任何后代元素(及其各自的内容和后代)。

    您的绝对定位元素是其包含块是初始包含块(也是 html 元素的包含块)的后代,因为 html 和 body 都没有定位。这是根据规范的另一部分。这可以防止 html 和 body 上的溢出剪辑对您的绝对定位元素产生任何影响,因为它锚定到初始包含块。

  • 你有width: 100%; height: 100%;html 和 body;这可以防止初始包含块扩展超出视口(可见区域),因此初始包含块永远不会滚动。

    规范然后在同一部分进一步说明以下内容:

    UA 必须将根元素上设置的“溢出”属性应用于视口。当根元素是 HTML "HTML" 元素或 XHTML "html" 元素,并且该元素具有 HTML "BODY" 元素或 XHTML "body" 元素作为子元素时,用户代理必须改为应用 'overflow' 属性如果根元素上的值为“可见”,则从第一个此类子元素到视口。用于视口时的“可见”值必须解释为“自动”。从中传播值的元素必须具有用于“可见”的“溢出”的使用值。

    更简单地说:

    • 如果 html 不是overflow: visible,则将其应用于视口,然后将 html 转换为overflow: visible. 赋予 body的overflow值不受影响。

    • 如果 html 是overflow: visible,但 body 不是,则将其应用于视口,然后将 body 转换为overflow: visible.

    (设置overflow-x或到一个元素overflow-y以外的任何东西都会导致速记不再等于那个元素。)visibleoverflowvisible

    通常,这意味着视口应该与 html 和 body 一起自然滚动,因为一次只能存在一个滚动条。

    但是......你也给 html 和 body 一个宽度和高度100%!这意味着 100% 的容器。body的容器是html,html的容器是初始的包含块。但是由于您实际上不能使用 CSS 来控制视口的大小——这完全由浏览器处理——所以你的两个元素被限制在 100% 的视口高度(也称为折叠)。视口本身不必扩展到折叠之外,因为它的任何内容都不需要比可见更多的空间(请注意,绝对定位的元素永远不会被考虑在内)。因此,视口不会生成滚动条(html 也不会);您看到的滚动条属于正文。

    如果您没有设置widthorheight属性,那么它们将默认为auto,从而导致 html 和 body 随内容一起扩展,并且始终与初始包含块所覆盖的整个区域相同大小,包括折叠下方的区域。这可以防止 body 生成滚动条,因为它总是会拉伸以适应其内容,因此您只能看到视口滚动条,而绝对定位的元素将与页面的其余部分一起滚动。

  • 由于初始包含块不滚动,因此绝对定位的元素也不滚动。即使页面的其余部分确实滚动,这也会导致它看起来是固定的。

    那么,当您滚动时会发生什么,您实际上是在滚动 body 元素。由于绝对定位的元素被锚定到从不滚动的初始包含块上,因此它看起来是固定的而不是滚动的。

    顺便说一句,这也是元素在根本不滚动时似乎与滚动条重叠的原因。滚动条属于body,它位于绝对定位元素的下方。如果您从 html 和 body 中删除overflow-x声明或widthandheight声明,则您看到的滚动条属于视口。但是,如果定位 body,滚动条仍然属于 body,但该元素也成为 body 的子元素,因此不会与滚动条重叠。

于 2013-02-06T23:03:47.433 回答
4

您需要添加position: relativebody. 你div.backgroundposition: absolute它,这导致它粘在 HTML 文档的顶部。如果你不想这样,你需要给它的父母(在这种情况下,身体标签)position: relative

演示#1:http ://tinkerbin.com/nmI74RpC

或者,您可以从 中删除position: absolutediv.background但我不确定这将如何影响您的其余布局。

演示#2:http ://tinkerbin.com/PP5PpbuC

于 2013-02-05T22:50:31.040 回答