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.
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.
Tested in Chrome Version 43.0.2357.81 m & FF 36.0.1 & Opera 20.0.1387.91 on Windows 8.1
Here is the code as requested:
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;
}
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:
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 thewindow
(including the scroll bar). I use this to add it to the 100% of the body, seeplusScrollBar
variable.JS:
CSS:
Why I like this: it takes in consideration that not all scrollbars are the same width or considered as conserved space at all. :)
Here's my solution to the problem of 100vw adding a horizontal scroll:
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/egZKpmMy approach was to determine the width of the scroll bar and use
calc()
to reduce the100vw
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.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.Also, this does not guarantee that 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.Full Code:
Then this Javascript will set the CSS Custom Property:
As a side note, Mac users can test this by going to System Preferences -> General -> Show Scroll Bars = Always
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.
warning: I have not tested these solutions for browser support
tl;dr
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.
1. Set all ancestor elements to position static
If you make sure that all of
.box
's ancestors are set toposition: static;
then set.box
towidth: 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 beposition: absolute;
orposition: relative;
.Example
2. Move the element outside of non-static ancestors
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.Example
3. Remove Vertical Scrollbar
If you don't need vertical scrolling you can just remove the vertical scrollbar by setting the
<html>
element tooverflow-y: hidden;
.Example
4. Remove Horizontal Scrollbar This does not fix the problem, but may be suitable for some situations.
Setting the
<html>
element tooverflow-y: scroll; overflow-x: hidden;
will prevent the horizontal scrollbar from appearing, but the 100vw element will still overflow.Example
Viewport-Percentage Lengths Spec
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.Example
Paddings and borders can interfere. So can margin. Use box-sizing to calculate width including these attributes. And maybe remove margin (if any) from the width.
It seems you have to add
max-width: 100%;
if there is a reflow which is causing the scrollbar to appear after the 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.Here's what I do:
}