在实际开发的过程当中,内容溢出是常常见到的。若是不深刻了解这个机制,你常常会碰到这样的问题:为何这个元素没有受到祖先元素的overflow:hidden的影响?这里出现的滚动条是哪一个元素的?如何消除这个滚动条?如何在指定的元素上增长滚动功能?
在这篇文章,咱们将会从CSS标准出发,讨论CSS溢出机制的细节。css
当一个盒子(block container box)的内容(子元素、孙子元素等后裔)超过盒子自己的大小的时候,就会出现溢出。这个时候CSS属性overflow决定如何处理溢出。这个css属性你们都知道,在这里不讨论了,在这里指出须要注意的几点:html
<A><B><C><C/><B/><A/>
,通常来讲,B的overflow会影响C,可是若是C是相对于viewport或者A定位的(好比使用了position:absolute),那么C的显示就不受B的裁剪、滚动的影响。overflow
属性是从<html>或者<body>元素窃取来的:若是<html>的overflow
不是'visible'(默认值),那就从<html>窃取;不然,从<body>窃取。若是viewport窃取来的overflow
是'visible',那么将它视为'auto'(由于不可能在viewport以外显示内容)。被窃取的元素,它的overflow
被设置为'visible'。能够推断出:chrome
通常来讲只有元素才能拥有滚动条(更准确地说,只有产生block container box的元素才能拥有滚动条)。但visual viewport是个例外。它虽然不是一个元素,可是也能够拥有滚动条。若是在<html>和<body>上都没有设置overflow属性而使用默认值visible(大部分场景都是这样),那么,visual viewport的overflow就是auto:当网页中有内容超出visual viewport时,visual viewport上会出现滚动条。canvas
关于viewport的讨论在 【响应式布局】initial containing block、viewport以及相关尺寸。
小练习:利用以上原理,使visual viewport和<body>都拥有横、竖滚动条,总共4个滚动条。不能使用overflow: scroll(这样就太简单了)。
步骤:segmentfault
代码+注释:浏览器
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"> <title>test</title> <style> * { padding: 0; margin: 0; box-sizing: border-box; } html { /* 使html的尺寸始终与visual viewport相同(即便你缩放、调整浏览器窗口的大小),从而body能够设置一个比visual viewport还大的尺寸(110%)。 对于默认为block的元素能够省略width: 100%; */ width: 100%; height: 100%; /* 非visible的值冒泡到visual viewport上,使visual viewport能够出现滚动条 */ overflow: auto; border: 15px solid red; } body { /* 使得body能够出现滚动条 */ overflow: auto; /* body溢出html,从而溢出initial containning block,从而溢出visual viewport,使得visual viewport出现滚动条。 固然,你也能够经过不少其余的方式来触发visual viewport的溢出,好比增大html元素,或者在body中弄一个position: absolute的div */ width: 110%; height: 110%; border: 15px solid green; } main { /* main溢出body,使得body出现滚动条 */ width: 110%; height: 110%; border: 15px solid blue; } </style> </head> <body> <main> </main> </body> </html>
结果:app
本身在chrome中打开以上代码,能更加清晰地看出是怎么作到的。
也能够经过absolute的方式来溢出initial containing block:布局
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"> <title>test</title> <style> * { padding: 0; margin: 0; box-sizing: border-box; } html { /* 使html的尺寸始终与visual viewport相同(即便你缩放、调整浏览器窗口的大小),从而body能够设置一个比visual viewport还大的尺寸(110%)。 对于默认为block的元素能够省略width: 100%; */ width: 100%; height: 100%; /* 非visible的值冒泡到visual viewport上,使visual viewport能够出现滚动条 */ overflow: auto; border: 15px solid red; } body { /* 使得body能够出现滚动条 */ overflow: auto; /* 为body设置一个尺寸,从而main能够设置一个比body还大的尺寸(110%)。 对于默认为block的元素能够省略width: 100%; */ height: 100%; border: 15px solid green; } main { /* main溢出body,使得body出现滚动条 */ width: 110%; height: 110%; border: 15px solid blue; } .abs { /* 经过absolute的方式来溢出initial containing block,从而溢出viewport */ position: absolute; width: 100px; height: 100px; right: -100px; bottom: -100px; border: 15px solid blueviolet; } </style> </head> <body> <main> </main> <div class="abs"></div> </body> </html>
结果:学习
本身在chrome中打开以上代码,能更加清晰地看出是怎么作到的。
经过Chrome DevTools就能够看出滚动条的所属元素。
前面已经说过,滚动条的位置在元素的border与padding之间。当你使用Chrome DevTools选中某个元素,发现滚动条刚好在高亮区域(border)内部时,滚动条就属于当前元素。spa
要判断滚动条是否属于visual viewport,首先先将右边、下边的滚动条分别滚动到最下、最右(这一步很重要,它保证没有内容藏在滚动条下面)。而后,Ctrl+Shift+C
选择右边或下边的滚动条,若是高亮的区域不包含这个滚动条,就说明这个滚动条不属于任何元素,也就是属于visual viewport。
https://developer.mozilla.org...
https://developer.mozilla.org...
获取或设置元素的内容被滚动的距离。这两个属性适用于全部Element。
若是想要获取visual viewport的滚动距离,除了这个方法之外,还有更多等效的方法。见【响应式布局】initial containing block、viewport以及相关尺寸。