为什么overflow-x:hidden使我的绝对定位元素变得固定?

时间:2013-02-05 22:36:56

标签: html css

我想知道,为什么将overflow-x: hidden设置为HTML网页的正文会使我的元素position: fixed即使我将其设置为position: absolute

demo中可以更好地理解效果。

以下是代码:

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

2 个答案:

答案 0 :(得分:23)

该元素仍为position: absolute,但由于positionoverflow与框模型之间的一些相当复杂的交互,它似乎已修复。令人难以置信的是,这些行为中没有一个是未指定的或任何浏览器中的错误 - 它实际上完全是设计上的,如果有点违反直觉。

它基本归结为以下几点:

  • 除非定位任何祖先,否则绝对定位的元素将锚定到初始包含块。 (这就是adding position: relative to body works as suggested in another answer。)

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

  • 由于初始包含块不会滚动,因此绝对定位的元素也不会滚动。即使页面的其余部分滚动,这也会使其显示为固定。

奇怪的是,this works on IE6 too


更长的解释:

  • 绝对定位的元素将锚定到初始包含块,除非定位其任何祖先。

    overflow属性上的spec,它偶然包含您正在观察同一问题的另一个示例,其中overflow: scroll的元素与绝对定位的后代元素进行交互,陈述如下:

      

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

    你的绝对定位元素是一个后代,其包含块是初始包含块(也是html元素的包含块),因为html和body都没有定位。这是根据another section of the spec。这可以防止html和body上的溢出剪切对绝对定位的元素产生任何影响,因为它会锚定到初始包含块。

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

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

      

    UA必须应用&#39;溢出&#39;属性设置在视口的根元素上。当根元素是HTML&#34; HTML&#34;元素或XHTML&#34; html&#34;元素,该元素有一个HTML&#34; BODY&#34;元素或XHTML&#34; body&#34;作为孩子的元素,用户代理必须改为应用溢出&#39;从第一个这样的子元素到视口的属性,如果根元素上的值是“可见的”#39;可见&#39;用于视口时的值必须解释为&#39; auto&#39;。传播值的元素必须具有“溢出”的使用值。 &#39;可见&#39;。

    更简单地说:

    • 如果html不是overflow: visible,请将其应用于视口,然后将html转为overflow: visible。给予身体的overflow值不受影响。

    • 如果html为overflow: visible,但实体不是,请将其应用于视口,并将正文转为overflow: visible

    (将overflow-xoverflow-y设置为元素causes the shorthand overflow to no longer be equal to visible for that element以外的visible以外的任何内容。)

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

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

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

  • 由于初始包含块不会滚动,因此绝对定位的元素也不会滚动。即使页面的其余部分滚动,这也会使其显示为固定。

    滚动时会发生什么,那就是你真正滚动了body元素。由于绝对定位元素锚定到从不滚动的初始包含块,因此它似乎是固定的而不是滚动。

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

答案 1 :(得分:3)

您需要将position: relative添加到body。您的div.background上有position: absolute,这会导致它粘贴在HTML文档的顶部。如果你不想这样,你需要给它的父(在这种情况下,身体标签)position: relative

DEMO#1:http://tinkerbin.com/nmI74RpC

或者,您可以从position: absolute移除div.background,但我不确定这会对您的布局的其余部分产生什么影响。

DEMO#2:http://tinkerbin.com/PP5PpbuC