absolute模拟fixed效果(解决fixed失效问题)
在IE6下, position:fixed
不会生效, 元素依旧会随着滚动条而滚动, 我们可以用position:absolute
来模拟fixed
的效果。
1. overflow滚动条归属问题
当只设置html
或body
其中一个overflow
时,都会作用到document
上,滚动条的归属也是如此;
如果同时设置两个的overflow
,html
的overflow
会作用到document
,而body
的overflow
会作用到自身。值都为scroll
时,可以看到页面会出现两个滚动条,一个属于body
,一个属于document
。
html{
margin: 20px;
height: 100%;
border: 1px solid;
overflow: scroll;
}
body{
height: 100%;
border: 1px solid red;
overflow: scroll;
}
<body>
<div style="height: 1000px;"></div>
</body>
效果图:
2. 绝对定位中的包含块
依据MDN文档中对position: absolute
的解释,绝对定位元素相对于最近的非 static
祖先元素定位,当这样的祖先元素不存在时,则相对于ICB
(inital container block, 初始包含块)进行定位。
什么是包含块?根据CSS2.1官方文档:
一个元素的盒子的位置和尺寸根据一个确定的矩形计算,这个确定的矩形叫做这个元素的包含块。
根元素所在的包含块叫做初始包含块。
对于连续媒体设备,初始包含块的大小等于视口viewport
的大小,基点在画布的原点(视口左上角);对于分页媒体,初始包含块是页面区域。
3. 模拟fixed的效果
要用absolute
来实现fixed
的效果,只能从其定位所依据的元素上入手,这个元素必须是不随滚动条所变动的。
html{
height: 100%; //这是浏览器视口的高度
overflow: hidden;
}
body{
height: 100%; //这是浏览器视口的高度
overflow: auto;
}
#fixed{
position: absolute;
left: 50px;
top: 50px;
width: 100px;
height: 100px;
background-color: green;
}
<body>
<div id="fixed"><div>
<div style='height: 1000px;'>这是一个可以滚动的div<div>
</body>
上方的代码,将document
的滚动条禁用,并开启了body
的滚动条。
此时body
的高度等于视口的高度,而且body
内会出现一个滚动条,在滚动的时候实际上是height
为1000px
的div
中的内容滚动。
而id
为fixed
的div
由于没有开启定位的祖先元素,会始终依据初始包含块来偏移,又因为html
的overflow
为hidden
,document
没有滚动条,初始包含块的位置不会变化,也不受body
的滚动条影响,所以依据其定位的div
不会随滚动条而滚动,这样就实现了fixed
的效果。
4. 后记
尽管现在基本已经不需要考虑IE6的兼容性问题了,但这种解决思路还是值得学习,并且在移动端也时常会应用到。