防止 100vw 创建水平滚动
Prevent 100vw from creating horizontal scroll
如果元素设置为 width: 100vw;
并且存在垂直滚动条,则元素的宽度将等于视口加上滚动条的宽度。
是否可以避免这种情况?
是否可以在不禁用整个页面的水平滚动的情况下防止这种情况发生?除了更改我的 css/markup 使元素成为主体宽度的 100% 之外,我想不出任何东西。
在 Chrome 版本 43.0.2357.81 m & FF 36.0.1 & Opera 20.0.1387.91 中测试 Windows 8.1
这是请求的代码:
html
<div class="parent">
<div class="box"></div>
</div>
<div class="tall"></div>
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;
}
填充和边框可能会干扰。保证金也是如此。使用 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%
}
如果在 初始视口宽度计算后出现回流导致滚动条显示 ,您似乎必须添加 max-width: 100%;
。这似乎不会在没有干扰滚动条的浏览器中发生(iOS,OS X,IE 11 Metro),但会影响所有其他浏览器。
具有 width: 100vw
的元素仅当其中一个父元素具有水平填充时才会导致水平滚动条。否则它应该很合适。
检查此 fiddle:http://jsfiddle.net/1jh1cybc/ .parent2
有填充,导致内部 .box
超出其父级宽度。
编辑:
在你的情况下,我猜你的 body
有余量。用你的代码检查这个 fiddle 并尝试删除正文 css 规则:http://jsfiddle.net/1jh1cybc/1/
基本上答案是否定的,如果你有一个垂直滚动条,就没有办法让 100vw 等于可见视口的宽度。以下是我针对此问题找到的解决方案。
警告:我没有测试这些解决方案的浏览器支持
tl;dr
如果您需要一个元素的宽度为可见视口的 100%(视口减去滚动条),您需要将其设置为 body 的 100%。如果有垂直滚动条,则不能使用 vw 单位。
1.将所有祖先元素设置为 static
如果您确保 .box
的所有祖先都设置为 position: static;
,则将 .box
设置为 width: 100%;
,这样它将是 [的 100% =91=]的宽度。但这并不总是可能的。有时您需要其中一位祖先是 position: absolute;
或 position: relative;
.
2。将元素移到 non-static ancestors
之外
如果不能将祖先元素设置为 position: static;
,则需要将 .box
移到它们之外。这将允许您将元素设置为 body 宽度的 100%。
3。删除垂直滚动条
如果不需要垂直滚动条,只需将 <html>
元素设置为 overflow-y: hidden;
.
即可删除垂直滚动条
4.删除水平滚动条
这不能解决问题,但可能适用于某些情况。
将<html>
元素设置为overflow-y: scroll; overflow-x: hidden;
会阻止水平滚动条出现,但100vw元素仍然会溢出。
Viewport-Percentage 长度规格
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.
这似乎是一个错误,因为当根元素上的溢出设置为自动时,vw 单位应该只包括滚动条宽度。但是我已经尝试将根元素设置为 overflow: scroll;
并且它没有改变。
这是我的做法:
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);
}
我通过将 body{overflow-x:hidden} 添加到有问题的页面来修复我网站上的这个问题。
也适用于您的示例。
这是一种更 full-fledged 的方法来解决这个错误,因为它仍然存在于现代浏览器中。在许多情况下,设置 overflow-x: hidden
可能会导致问题或不合需要。
此处提供完整示例:http://codepen.io/bassplayer7/pen/egZKpm
我的方法是确定滚动条的宽度,然后使用 calc()
将 100vw
减少滚动条的宽度。这有点复杂,因为在我的例子中,我从一个定义了 with 的框中拉出内容的宽度,所以我也需要声明边距。
关于下面代码的一些注意事项:首先,我注意到 20px 似乎是滚动条的一个相当宽泛的幻数。我使用 SCSS 变量(不必是 SCSS)并在 @supports
之外编写代码作为备用。
此外,这并不保证永远不会有滚动条。由于它需要 Javascript,因此未启用该功能的用户将看到水平滚动条。您可以通过设置 overflow-x: hidden
然后在 Javascript 运行时添加 class 来覆盖它来解决这个问题。
全SCSS码:
$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));
}
}
}
只需删除 #{$scroll-bar}
引用并替换为 px 值
,即可将上面的内容转换为纯 CSS
然后这个 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();
附带说明,Mac 用户可以通过转到系统偏好设置 -> 常规 -> 显示滚动条 = 始终
来测试它
下面是我对100vw添加水平滚动问题的解决方法:
html {
width: calc(100% + calc(100vw - 100%));
overflow-x: hidden;
}
.box {
width: calc(100% + calc(100vw - 100%));
}
我也在为此苦苦挣扎,我也想到了 CSS 变量作为解决方案。 CSS IE11 不支持变量,所以我尝试了其他方法:
我通过计算滚动条的宽度来修复它:从window
(包括滚动条)的宽度减去body
(不包括滚动条)的宽度。我用它来将它添加到正文的 100%,请参阅 plusScrollBar
变量。
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:
html{
overflow-x: hidden;
}
为什么我喜欢这个: 它考虑到并非所有滚动条的宽度都相同或被认为是保守的 space。 :)
我遇到了同样的问题,添加后问题得到解决:
html, body { overflow-y: auto; }
我添加了评论:
/* this fixes a 100vw issue, removing the horizontal scrollbar when it's unneeded */
它至少适用于 Firefox、Chrome、Opera 和 Internet Explorer 11(我使用 IE 浏览器)。
虽然我不知道它为什么有效,也不知道它是否在所有情况下都有效。
编辑:
水平滚动条消失了,但我注意到它仍然可以使用光标键和触摸屏水平滚动...
我遇到了同样的问题。当我将 vw 单位更改为百分比时,水平滚动条消失了。
将 max-width
属性与 width:100vw
一起使用,它解决了我的问题。
这是我用的。
.full{
height: 100vh;
width: 100vw;
max-width: 100%;
}
基本上它所做的是固定视口的最大宽度,从而消除水平滚动。
更多@https://www.w3schools.com/cssref/pr_dim_max-width.asp
The max-width property defines the maximum width of an element.
If the content is larger than the maximum width, it will automatically
change the height of the element.
If the content is smaller than the maximum width, the max-width
property has no effect.
如果您在框架中工作(例如 ASP.NET),其中可能有父元素环绕 html,则设置 html 的 max-width
到 100% 将在不使用“创可贴”解决方案的情况下解决问题 overflow-x: hidden
.
html {
max-width: 100%;
}
overflow-x: clip;
完成任务。
如果元素设置为 width: 100vw;
并且存在垂直滚动条,则元素的宽度将等于视口加上滚动条的宽度。
是否可以避免这种情况?
是否可以在不禁用整个页面的水平滚动的情况下防止这种情况发生?除了更改我的 css/markup 使元素成为主体宽度的 100% 之外,我想不出任何东西。
在 Chrome 版本 43.0.2357.81 m & FF 36.0.1 & Opera 20.0.1387.91 中测试 Windows 8.1
这是请求的代码:
html
<div class="parent">
<div class="box"></div>
</div>
<div class="tall"></div>
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;
}
填充和边框可能会干扰。保证金也是如此。使用 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%
}
如果在 初始视口宽度计算后出现回流导致滚动条显示 ,您似乎必须添加 max-width: 100%;
。这似乎不会在没有干扰滚动条的浏览器中发生(iOS,OS X,IE 11 Metro),但会影响所有其他浏览器。
具有 width: 100vw
的元素仅当其中一个父元素具有水平填充时才会导致水平滚动条。否则它应该很合适。
检查此 fiddle:http://jsfiddle.net/1jh1cybc/ .parent2
有填充,导致内部 .box
超出其父级宽度。
编辑:
在你的情况下,我猜你的 body
有余量。用你的代码检查这个 fiddle 并尝试删除正文 css 规则:http://jsfiddle.net/1jh1cybc/1/
基本上答案是否定的,如果你有一个垂直滚动条,就没有办法让 100vw 等于可见视口的宽度。以下是我针对此问题找到的解决方案。
警告:我没有测试这些解决方案的浏览器支持
tl;dr
如果您需要一个元素的宽度为可见视口的 100%(视口减去滚动条),您需要将其设置为 body 的 100%。如果有垂直滚动条,则不能使用 vw 单位。
1.将所有祖先元素设置为 static
如果您确保 .box
的所有祖先都设置为 position: static;
,则将 .box
设置为 width: 100%;
,这样它将是 [的 100% =91=]的宽度。但这并不总是可能的。有时您需要其中一位祖先是 position: absolute;
或 position: relative;
.
2。将元素移到 non-static ancestors
之外如果不能将祖先元素设置为 position: static;
,则需要将 .box
移到它们之外。这将允许您将元素设置为 body 宽度的 100%。
3。删除垂直滚动条
如果不需要垂直滚动条,只需将 <html>
元素设置为 overflow-y: hidden;
.
4.删除水平滚动条 这不能解决问题,但可能适用于某些情况。
将<html>
元素设置为overflow-y: scroll; overflow-x: hidden;
会阻止水平滚动条出现,但100vw元素仍然会溢出。
Viewport-Percentage 长度规格
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.
这似乎是一个错误,因为当根元素上的溢出设置为自动时,vw 单位应该只包括滚动条宽度。但是我已经尝试将根元素设置为 overflow: scroll;
并且它没有改变。
这是我的做法:
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);
}
我通过将 body{overflow-x:hidden} 添加到有问题的页面来修复我网站上的这个问题。
也适用于您的示例。
这是一种更 full-fledged 的方法来解决这个错误,因为它仍然存在于现代浏览器中。在许多情况下,设置 overflow-x: hidden
可能会导致问题或不合需要。
此处提供完整示例:http://codepen.io/bassplayer7/pen/egZKpm
我的方法是确定滚动条的宽度,然后使用 calc()
将 100vw
减少滚动条的宽度。这有点复杂,因为在我的例子中,我从一个定义了 with 的框中拉出内容的宽度,所以我也需要声明边距。
关于下面代码的一些注意事项:首先,我注意到 20px 似乎是滚动条的一个相当宽泛的幻数。我使用 SCSS 变量(不必是 SCSS)并在 @supports
之外编写代码作为备用。
此外,这并不保证永远不会有滚动条。由于它需要 Javascript,因此未启用该功能的用户将看到水平滚动条。您可以通过设置 overflow-x: hidden
然后在 Javascript 运行时添加 class 来覆盖它来解决这个问题。
全SCSS码:
$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));
}
}
}
只需删除 #{$scroll-bar}
引用并替换为 px 值
然后这个 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();
附带说明,Mac 用户可以通过转到系统偏好设置 -> 常规 -> 显示滚动条 = 始终
来测试它下面是我对100vw添加水平滚动问题的解决方法:
html {
width: calc(100% + calc(100vw - 100%));
overflow-x: hidden;
}
.box {
width: calc(100% + calc(100vw - 100%));
}
我也在为此苦苦挣扎,我也想到了 CSS 变量作为解决方案。 CSS IE11 不支持变量,所以我尝试了其他方法:
我通过计算滚动条的宽度来修复它:从window
(包括滚动条)的宽度减去body
(不包括滚动条)的宽度。我用它来将它添加到正文的 100%,请参阅 plusScrollBar
变量。
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:
html{
overflow-x: hidden;
}
为什么我喜欢这个: 它考虑到并非所有滚动条的宽度都相同或被认为是保守的 space。 :)
我遇到了同样的问题,添加后问题得到解决:
html, body { overflow-y: auto; }
我添加了评论:
/* this fixes a 100vw issue, removing the horizontal scrollbar when it's unneeded */
它至少适用于 Firefox、Chrome、Opera 和 Internet Explorer 11(我使用 IE 浏览器)。
虽然我不知道它为什么有效,也不知道它是否在所有情况下都有效。
编辑: 水平滚动条消失了,但我注意到它仍然可以使用光标键和触摸屏水平滚动...
我遇到了同样的问题。当我将 vw 单位更改为百分比时,水平滚动条消失了。
将 max-width
属性与 width:100vw
一起使用,它解决了我的问题。
这是我用的。
.full{
height: 100vh;
width: 100vw;
max-width: 100%;
}
基本上它所做的是固定视口的最大宽度,从而消除水平滚动。
更多@https://www.w3schools.com/cssref/pr_dim_max-width.asp
The max-width property defines the maximum width of an element.
If the content is larger than the maximum width, it will automatically change the height of the element.
If the content is smaller than the maximum width, the max-width property has no effect.
如果您在框架中工作(例如 ASP.NET),其中可能有父元素环绕 html,则设置 html 的 max-width
到 100% 将在不使用“创可贴”解决方案的情况下解决问题 overflow-x: hidden
.
html {
max-width: 100%;
}
overflow-x: clip;
完成任务。