CSS 防止 100vw 创建水平滚动
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30489594/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Prevent 100vw from creating horizontal scroll
提问by Hal Carleton
If an element is set to width: 100vw;
and there is a vertical scrollbar the width of the element will be equal to the viewport plus the width of the scrollbar.
如果元素设置为width: 100vw;
并且有垂直滚动条,则元素的宽度将等于视口加上滚动条的宽度。
Is it possible to prevent this?
有没有可能防止这种情况?
Is it possible to prevent this without disabling horizontal scrolling on the entire page? Aside from changing my css/markup to make the element 100% of the body width I can't think of anything.
是否可以在不禁用整个页面上的水平滚动的情况下防止这种情况发生?除了更改我的 css/markup 使元素成为主体宽度的 100% 之外,我想不出任何事情。
Tested in Chrome Version 43.0.2357.81 m & FF 36.0.1 & Opera 20.0.1387.91 on Windows 8.1
在 Windows 8.1 上的 Chrome 版本 43.0.2357.81 m & FF 36.0.1 & Opera 20.0.1387.91 中测试
Here is the code as requested:
这是要求的代码:
html
html
<div class="parent">
<div class="box"></div>
</div>
<div class="tall"></div>
css
css
body { margin: 0; }
html { box-sizing: border-box; }
*, *::before, *::after {
box-sizing: inherit;
position: relative;
}
.parent {
background: rgba(0, 0, 0, .4);
height: 100px;
width: 5rem;
margin-bottom: 25px;
}
.box {
position: absolute;
top: 0;
left: 0;
background: rgba(0, 0, 0, .4);
height: 50px;
width: 100vw;
}
.tall {
height: 100rem;
}
采纳答案by Hal Carleton
Basically the answer is no, if you have a vertical scrollbar there is no way to make 100vw equal the width of the visible viewport. Here are the solutions that I have found for this issue.
基本上答案是否定的,如果您有垂直滚动条,则无法使 100vw 等于可见视口的宽度。以下是我为这个问题找到的解决方案。
warning:I have not tested these solutions for browser support
警告:我尚未针对浏览器支持测试这些解决方案
tl;dr
tl;博士
If you need an element to be 100% width of the visible viewport(viewport minus scrollbar) you will need to set it to 100% of the body. You can't do it with vw units if there is a vertical scrollbar.
如果您需要一个元素为可见视口的 100% 宽度(视口减去滚动条),您需要将其设置为正文的 100%。如果有垂直滚动条,则无法使用 vw 单位执行此操作。
1. Set all ancestor elements to position static
1.将所有祖先元素设置为静态定位
If you make sure that all of .box
's ancestors are set to position: static;
then set .box
to width: 100%;
so it will be 100% of the body's width. This is not always possible though. Sometimes you need one of the ancestors to be position: absolute;
or position: relative;
.
如果您确保所有.box
的祖先都设置为position: static;
然后设置.box
为width: 100%;
,那么它将是主体宽度的 100%。但这并不总是可能的。有时您需要其中一个祖先为position: absolute;
or position: relative;
。
2. Move the element outside of non-static ancestors
2. 将元素移到非静态祖先之外
If you can't set the ancestor elements to position: static;
you will need to move .box
outside of them. This will allow you to set the element to 100% of the body width.
如果您不能将祖先元素设置为,position: static;
您将需要移到.box
它们之外。这将允许您将元素设置为主体宽度的 100%。
3. Remove Vertical Scrollbar
3. 移除垂直滚动条
If you don't need vertical scrolling you can just remove the vertical scrollbar by setting the <html>
element to overflow-y: hidden;
.
如果您不需要垂直滚动,您可以通过将<html>
元素设置为来删除垂直滚动条overflow-y: hidden;
。
4. Remove Horizontal ScrollbarThis does not fix the problem, but may be suitable for some situations.
4. 移除水平滚动条这不能解决问题,但可能适用于某些情况。
Setting the <html>
element to overflow-y: scroll; overflow-x: hidden;
will prevent the horizontal scrollbar from appearing, but the 100vw element will still overflow.
将<html>
元素设置为overflow-y: scroll; overflow-x: hidden;
将阻止水平滚动条出现,但 100vw 元素仍然会溢出。
Viewport-Percentage Lengths Spec
视口百分比长度规范
The viewport-percentage lengths are relative to the size of the initial containing block. When the height or width of the initial containing block is changed, they are scaled accordingly. However, when the value of overflow on the root element is auto, any scroll bars are assumed not to exist. Note that the initial containing block's size is affected by the presence of scrollbars on the viewport.
视口百分比长度与初始包含块的大小有关。当初始包含块的高度或宽度发生变化时,它们会相应地缩放。但是,当根元素上的overflow 值为auto 时,则假定任何滚动条都不存在。请注意,初始包含块的大小受视口上滚动条的影响。
It appears that there is a bug because vw units should only include the scrollbar width when overflow is set to auto on the root element. But I've tried setting the root element to overflow: scroll;
and it did not change.
似乎存在一个错误,因为当根元素上的溢出设置为 auto 时, vw 单位应仅包含滚动条宽度。但是我已经尝试将根元素设置为overflow: scroll;
并且它没有改变。
回答by bassplayer7
I know this is an old question, but the bug still exists in modern browsers. I didn't like the idea of doing overflow-x: hidden
so this is what I did. A full example is available here: http://codepen.io/bassplayer7/pen/egZKpm
我知道这是一个老问题,但该错误仍然存在于现代浏览器中。我不喜欢这样做的想法,overflow-x: hidden
所以这就是我所做的。这里有一个完整的例子:http: //codepen.io/bassplayer7/pen/egZKpm
My approach was to determine the width of the scroll bar and use calc()
to reduce the 100vw
by the amount of the scroll bar. This is a little more complicated because in my case, I was pulling the width of the content out from a box that had a defined with so I needed to declare the margin as well.
我的方法是确定滚动条的宽度并用于calc()
减少100vw
滚动条的数量。这有点复杂,因为在我的情况下,我从一个定义了 with 的盒子中拉出内容的宽度,所以我还需要声明边距。
A few notes regarding the code below: first, I noticed that 20px seems to be a rather broad magic number for the scroll bars. I use a SCSS variable (it doesn't have to be SCSS) and code outside of @supports
as a fallback.
关于以下代码的一些注意事项:首先,我注意到 20px 似乎是滚动条的一个相当广泛的幻数。我使用 SCSS 变量(它不一定是 SCSS)和外部代码@supports
作为后备。
Also, this does not guaranteethat there will never be scroll bars. Since it requires Javascript, users that don't have that enabled will see horizontal scroll bars. You could work around that by setting overflow-x: hidden
and then adding a class to override it when Javascript runs.
此外,这并不能保证永远不会有滚动条。由于它需要 Javascript,没有启用它的用户将看到水平滚动条。您可以通过设置overflow-x: hidden
然后在 Javascript 运行时添加一个类来覆盖它来解决这个问题。
Full Code:
完整代码:
$scroll-bar: 20px;
:root {
--scroll-bar: 8px;
}
.screen-width {
width: 100vw;
margin: 0 calc(-50vw + 50%);
.has-scrollbar & {
width: calc(100vw - #{$scroll-bar});
margin: 0 calc(-50vw + 50% + #{$scroll-bar / 2});
}
@supports (color: var(--scroll-bar)) {
.has-scrollbar & {
width: calc(100vw - var(--scroll-bar));
margin: 0 calc(-50vw + 50% + (var(--scroll-bar) / 2));
}
}
}
Then this Javascript will set the CSS Custom Property:
然后这个 Javascript 将设置 CSS 自定义属性:
function handleWindow() {
var body = document.querySelector('body');
if (window.innerWidth > body.clientWidth + 5) {
body.classList.add('has-scrollbar');
body.setAttribute('style', '--scroll-bar: ' + (window.innerWidth - body.clientWidth) + 'px');
} else {
body.classList.remove('has-scrollbar');
}
}
handleWindow();
As a side note, Mac users can test this by going to System Preferences -> General -> Show Scroll Bars = Always
作为旁注,Mac 用户可以通过转到 System Preferences -> General -> Show Scroll Bars = Always 进行测试
回答by Cyd
I was also struggling with this, and I also thought of CSS variables as the solution. CSS variables aren't supported in IE11 though so I tried something else:
我也在为此苦苦挣扎,我也想到了 CSS 变量作为解决方案。IE11 不支持 CSS 变量,所以我尝试了其他方法:
I fixed it by calculating the width of the scroll bar: subtracting the width of the body
(not including scroll bar) from the width of the window
(including the scroll bar). I use this to add it to the 100% of the body, see plusScrollBar
variable.
我通过计算滚动条的宽度来修复它:从body
(包括滚动条)的宽度中减去(不包括滚动条)的宽度window
。我用它来将它添加到主体的 100%,参见plusScrollBar
变量。
JS:
JS:
// calculate width of scrollbar and add it as inline-style to the body
var checkScrollBars = function() {
var b = $('body');
var normalw = 0;
var scrollw = 0;
normalw = window.innerWidth;
scrollw = normalw - b.width();
var plusScrollBar = 'calc(' + '100% + ' + scrollw + 'px)'
document.querySelector('body').style.minWidth = plusScrollBar;
}();
CSS:
CSS:
html{
overflow-x: hidden;
}
Why I like this:it takes in consideration that not all scrollbars are the same width or considered as conserved space at all. :)
我喜欢这个的原因:它考虑到并非所有滚动条的宽度都相同,或者根本就被认为是守恒的空间。:)
回答by Niklas Brunberg
Paddings and borders can interfere. So can margin. Use box-sizingto calculate width including these attributes. And maybe remove margin (if any) from the width.
填充和边框可能会干扰。保证金也可以。使用box-sizing计算包含这些属性的宽度。并且可能从宽度中删除边距(如果有)。
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
body {
margin: 0; /* interferes with 100vw */
}
.parent {
width: 100vw;
max-width: 100%; /* see below */
}
.box {
width: 100%; /* For those good old-fashioned browsers with no vw or calc() support */
width: -webkit-calc(100vw - [your horizontal margin, if any]);
width: -moz-calc(100vw - [your horizontal margin, if any]);
width: calc(100vw - [your horizontal margin, if any]);
max-width: 100%
}
It seems you have to add max-width: 100%;
if there is a reflow which is causing the scrollbar to appear afterthe initial viewport width calculation. This does not seem to happen in browsers without an interfering scrollbar (iOS, OS X, IE 11 Metro), but can affect all other browsers.
max-width: 100%;
如果有回流导致在初始视口宽度计算后出现滚动条,您似乎必须添加。这在没有干扰滚动条的浏览器(iOS、OS X、IE 11 Metro)中似乎不会发生,但会影响所有其他浏览器。
回答by Pedro Amaral Couto
I had the same issue and it was fixed when I added:
我有同样的问题,当我添加时它被修复了:
html, body { overflow-y: auto; }
I added the comment:
我添加了评论:
/* this fixes a 100vw issue, removing the horizontal scrollbar when it's unneeded */
It works at least with Firefox, Chrome, Opera and Internet Explorer 11 (I used browserling for IE).
它至少适用于 Firefox、Chrome、Opera 和 Internet Explorer 11(我使用 IE 浏览器)。
I don't know why it works and if it works in all cases, though.
不过,我不知道它为什么有效,以及它是否在所有情况下都有效。
EDIT:The horizontal scrollbar disappeared, but I noticed it's still horizontally scrollable using the cursor keys and touch screens...
编辑:水平滚动条消失了,但我注意到它仍然可以使用光标键和触摸屏水平滚动......
回答by Shiju Nambiar
I had the same problem. When I changed the vw units to percentage, horizontal scrollbar disappeared.
我有同样的问题。当我将 vw 单位更改为百分比时,水平滚动条消失了。
回答by moy2010
Here's my solution to the problem of 100vw adding a horizontal scroll:
这是我对100vw添加水平滚动问题的解决方案:
html {
width: calc(100% + calc(100vw - 100%));
overflow-x: hidden;
}
.box {
width: calc(100% + calc(100vw - 100%));
}
回答by redelschaap
An element with width: 100vw
only causes horizontal scrollbars when one of it's parents has a horizontal padding. Otherwise it should fit in well.
一个元素width: 100vw
只有当它的父元素之一具有水平填充时才会导致水平滚动条。否则它应该很好地适应。
Check this fiddle: http://jsfiddle.net/1jh1cybc/The .parent2
has a padding, which causes the inner .box
to break out of it's parent width.
检查此琴:http://jsfiddle.net/1jh1cybc/的.parent2
具有填充,从而导致内.box
打破它的母公司宽度出来。
Edit:
编辑:
In your case I guess your body
has a margin. Check this fiddle out with you code and try to remove the body css rule: http://jsfiddle.net/1jh1cybc/1/
在你的情况下,我猜你body
有一个保证金。用你的代码检查这个小提琴并尝试删除 body css 规则:http: //jsfiddle.net/1jh1cybc/1/
回答by innocuous_name
Here's what I do:
这是我所做的:
div.screenwidth{
width:100%; /* fallback for browsers that don't understand vw or calc */
width: calc(100vw - 17px); /* -17 because vw is calculated without the scrollbar being considered & 17px is width of scrollbars */
position:relative; /* use this if the parent div isn't flush left */
right: calc((100vw - 17px - 100% )/2);
}
}
回答by Adam
I fixed this on my site by adding body{overflow-x:hidden} to the page in question.
我通过向相关页面添加 body{overflow-x:hidden} 来修复此问题。
Works on your example too.
也适用于您的示例。