垂直滚动条出现时,如何停止我的Web内容左移? 总结2017年的build议

许多程序员已经询问如何在垂直滚动条出现时停止其网页内容(特别是其居中的网页内容( margin: 0 auto; ))。 对于像我这样使用隐藏的div和制表符来组织数据的Ajax用户来说,这一直是个问题。

当前显示的页面发生变化时,会出现问题,使得显示的材料的高度(内部窗口高度)突然大于物理窗口高度。

所有的滚动条并非一律平等的现实加剧了这个问题。 不同的浏览器给他们的滚动条不同的宽度,这种差异不能(至less不应该)被预测。 总之,理想的解决scheme是独立于滚动条宽度。

因此,这是一个自我回答的问题,在2017年8月5日之前,将所有这些答案和有用的评论(如果可能)以及我自己的解决scheme汇总成一个答案。我已经标记为重复的以前的问题,我可以find,让人们可以find一个全面的讨论这个问题。

请注意,这个答案解决了BODY内容转移的问题。 如果你有一个固定高度的DIV有移位问题,你应该把DIV的宽度设置为一个固定的( px )宽度,这样它的滚动条浮在文本上方,并添加一些右边的填充以防止文本掉落下来。 贡献者: Hashbrown , Avrahamcool , Edward Newsome

在进入个别解决scheme之前,应该提到它们分为三类:基于CSS,CSS3和Javascript的解决scheme。

CSS解决scheme往往是相当的,但非常可预测,得到很好的支持。

CSS3解决scheme像Javascript一样具有CPU计算成本,但易于实现。 然而,在2017年之前的几年里,他们在浏览器上有零星的支持。 随着时间的推移, 最终,他们可能是最好的解决scheme,但是我今天的调查表明,这种支持还不够一致,而且,传统的浏览器支持是不存在的。

Javascript解决scheme(无论是直接的JavaScript还是jQuery)都需要额外的编码,以使它们更健壮,因为它们没有内在的支持(例如)窗口大小调整。 但是,它们是最可预测的,也是最向后兼容的,同时还保留了页面的美感。 我认为传统浏览器的线路介于IE6和IE7之间。 坦率地说,我对任何仍然使用旧版浏览器的人表示哀悼。

请注意,我没有包括以前发布到Stack Exchange的所有CSS3和Javascript解决scheme。 有些虽然新颖,但有很大的弱点,所以不包括在这里。


解决scheme#1:CSS解决scheme

贡献者: Hive7 , koningdavid , Christofer Eliasson , Alec Gorge , Scott Bartell , Shawn Taylor , mVChr , fsn , Damb , Sparky , Ruben , Michael Krelin – 黑客 , Melvin Guerrero

强制滚动条始终处于打开状态。

 <style> html { overflow-y: scroll; } </style> 

这个解决scheme基本上可以保证总能正常工作(有一些例外,但是非常less见),但这在美学上是不合适的。 无论是否需要,滚动条总会被看到。 虽然共识是在html标签中使用这个解决scheme,但有些人build议在body标签中使用它。

后果

微软(IE10 +)已经实现了浮动滚动条,这意味着你的页面可能不会像在其他浏览器中那样居中。 但是,这似乎是一个很小的问题。

当使用像FancyBox,Flex-Box或Twitter Bootstrap Modal这样的结构化接口时,这会导致双滚动条出现,因为这些接口创build了自己的滚动条。

程序员应该避免使用overflow: scroll因为这将导致垂直和水平滚动条出现。

解决scheme#1a:替代scheme

贡献者: koningdavid , Nikunj Madhogaria

一个聪明的select,但只有一个小的美学差异,是这样做的:

 <style> html { height: 101%; } </style> 

这将激活滚动条背景,但不会激活滚动条选项卡,除非垂直内容实际上溢出窗口的底部边缘。 尽pipe如此,它也有一个相同的缺点,即无论是否需要,滚动条空间都会被永久消费。

解决scheme#1b:更现代的解决scheme

贡献者: Kyle Dumovic , SimonDos

浏览器开始使用滚动条的overlay值,模仿IE10 +的浮动滚动条。

 <style> html { overflow-y: overlay; } </style> 

这个解决scheme模仿了IE10 +中的浮动滚动条,但它在所有的浏览器中都不可用,并且仍然存在一些实现问题。 已知此解决scheme不适用于Bootstrap Modal等基础结构环境。


解决scheme2:CSS3解决scheme

使用CSS3来计算宽度。 有很多方法可以做到这一点,各有利弊。 (a)不知道实际的滚动条宽度,(b)处理屏幕大小调整,以及(c)CSS正在慢慢变成另一个完全正常运行的编程语言,比如Javascript,还没有完全演变成这样。 它是否有意义成为另一个问题还是有争议的。

用户可能会禁用Javascript,所以只有CSS的解决scheme的说法是最好的,变得无关紧要。 客户端编程变得如此无处不在,只有最偏执狂的人仍然在禁用Javascript。 就我个人而言,我不再认为这是一个成功的论据。

应该指出的是,一些解决scheme修改margin和其他修改padding 。 那些修改margin的问题有一个共同的问题:如果你有导航条,标题,边框等使用不同的颜色比页面背景,这个解决scheme将暴露不合需要的边界。 使用margin任何解决scheme都可能被重新devise为使用padding ,反之亦然。

解决scheme#2a:基于HTML的解决scheme

贡献者: TranslucentCloud , Mihail Malostanidis

 <style> html { margin-left: calc(100vw - 100%); margin-right: 0; } </script> 

解决scheme#2b:基于BODY的解决scheme

贡献者: Greg St.Onge , Moesio , Jonathan SI

 <style> body { padding-left: 17px; width: calc(100vw - 17px); } @media screen and (min-width: 1058px) { body { padding-left: 17px; width: calc(100vw - 17px); } } </style> 

100vw是视口宽度的100%。

后果

一些用户build议这个解决scheme在调整窗口大小时会产生不希望的屏幕噪声(在resize的过程中可能会发生多次计算过程)。 可能的解决方法是避免使用margin: 0 auto; 以中心内容,而是使用以下(示例中显示的1000px500px代表您的内容的最大宽度和一半的数量):

 <style> body { margin-left: calc(50vw - 500px); } @media screen and (max-width: 1000px) { body { margin-left: 0; } } </style> 

这是一个固定滚动条宽度的解决scheme,它不是独立于浏览器的。 为了使浏览器独立,您必须包含Javascript来确定滚动条的宽度。 计算宽度但不重新包含该值的示例是:

请注意下面的代码片段已经多次在Stack Exchange和Internet上的其他位置发布,没有任何公司归属。

 function scrollbarWidth() { var div = $('<div style="width:50px;height:50px;overflow:hidden;position:absolute;top:-200px;left:-200px;"><div style="height:100px;"></div>'); // Append our div, do our calculation and then remove it $('body').append(div); var w1 = $('div', div).innerWidth(); div.css('overflow-y', 'scroll'); var w2 = $('div', div).innerWidth(); $(div).remove(); return (w1 - w2); } 

解决scheme#2c:基于DIV的解决scheme

贡献者: Rapti

使用直接应用于容器DIV元素的CSS3计算。

 <body> <div style="padding-left: calc(100vw - 100%);"> My Content </div> </body> 

后果

像所有的CSS3解决scheme一样,所有的浏览器都不支持。 即使那些支持视口计算的浏览器也不支持(截至撰写本文时)任意使用它。

解决scheme#2d:Bootstrap模式

贡献者: Mihail Malostanidis , kashesandr

Twitter Bootstrap Modal的用户发现将以下CSS3应用于其HTML元素非常有用。

 <style> html { width: 100%; width: 100vw; } </style> 

另一个build议是在内容包装器上创build一个包装器,用于自动检测视口宽度的变化。

 <style> body { overflow-x: hidden; } #wrap-wrap { width: 100vw; } #content-wrap { margin: 0 auto; width: 800px; } </style> 

我没有尝试过这些,因为我不使用Bootstrap。


解决scheme3:Javascript解决scheme

贡献者: Sam , JBH

这是我最喜欢的解决scheme,因为它处理所有问题,并且与传统浏览器相当兼容。 最重要的是,它是独立的滚动条宽度。

 <script> function updateWindow(){ document.body.style.paddingLeft = (window.innerWidth - document.body.clientWidth); document.body.onclick=function(){ document.body.style.paddingLeft = (window.innerWidth - document.body.clientWidth); } } window.onload=updateWindow(); window.addEventListener("resize", updateWindow()); updateWindow(); </script> 

后果

最后的命令updateWindow(); 应该在</body>标签之前出现,以避免dynamic加载的内容(如Facebook Like-Boxes)出现问题。 这似乎是多余的window.onload事件,但不是每个浏览器对待onload同样的方式。 一些等待asynchronous事件。 其他人不。

每次用户在网页中单击时,都会执行该function。 感谢,现代电脑速度不够,这不是一个问题。 仍然…。

最后,该函数应该在任何divasynchronous更新(AJAX)后执行。 这个例子中没有显示,但是将成为就绪状态的一部分。 例如:

 xmlhttp.onreadystatechange=function(){ if(xmlhttp.readyState==4 && xmlhttp.status==200){ if(xmlhttp.responseText == 'false'){ //Error processing here } else { //Success processing here updateWindow(); } } } 

解决scheme#3a:测量滚动条宽度

贡献者: Lwyrn

这是一个不太有价值的解决scheme,需要花时间来测量滚动条宽度。

 <script> var checkScrollBars = function(){ var b = $('body'); var normalw = 0; var scrollw = 0; if(b.prop('scrollHeight')>b.height()){ normalw = window.innerWidth; scrollw = normalw - b.width(); $('#container').css({marginRight:'-'+scrollw+'px'}); } } </script> <style> body { overflow-x: hidden; } </style> 

后果

像其他解决scheme一样,这个永久禁用水平滚动条。