Why does vw include the scrollbar as part of the viewport?
It would be convenient if viewport units didn't include cause scrollbars but it is the display size (screen) after all. Have look at this solution with a pseudo element though:
http://www.mademyday.de/css-height-equals-width-with-pure-css.html
Makes for a square in your example as well:
https://jsfiddle.net/3z887swo/4/
.box {
float: left;
width: 50%;
}
.box::before {
content: "";
display: block;
padding-top: 100%;
}
Edit - if anyone is wondering why this works (vertical padding responding to the original element's width)... that's basically how it's defined in the specification:
The percentage is calculated with respect to the width of the generated box's containing block, even for 'padding-top' and 'padding-bottom'.
http://www.w3.org/TR/CSS2/box.html#padding-properties
After coming across my own answer, I think it needed some refinement. Semantic ambiguity is why I replaced the word "include" with "cause" at the top. Because it's more the fact that vw
units only take the viewport size into account - not including any scrollbar and causing overflow and a scrollbar in the other direction when its width is added to 100vw
(making the total space that is needed the viewport plus scrollbar width, exceeding the screen).
As with the question here, the best way to handle vw
units is likely to avoid them if you can because they just aren't very compatible with desktop browser (that don't have overlaying scrollbars).
I edited out the idea that included a CSS variable, however hopeful it seemed.
vertical scrollbar appears when width is larger than 100vw
The viewport unit are relative to the viewport so if a horizontal scroll bar appear it means that this scroll bar will take space thus we need the vertical scroll in order to see the part hidden by the horizontal one.
To avoid this keep using only the vw
unit and use % instead of vh
so the height will be relative to the parent instead of the viewport. I have also removed the margin and adjusted the top
and left
values to make the block centred
* { padding: 0; margin: 0;}
body,html { height: 100%;}
.outer { position: relative; top: 0; left: 0; height: 100%; width: 105vw; /* This won't create a vertical scroll*/ overflow: hidden; background-color: lightyellow;}
.bg { height: 80%; width: 80vw; top: 50%; transform: translateY(-50%); position: absolute;}
.bg1 { background-color: #80c9be; left: 10vw;}
.bg2 { background-color: #e99790; left: 110vw;}
.bg3 { background-color: #f2e2cd; left: 210vw;}
.bg4 { background-color: #48697f; left: 310vw;}
<div class="outer"> <div class="bg bg1"> </div> <div class="bg bg2"> </div> <div class="bg bg3"> </div> <div class="bg bg4"> </div></div>
100vw causing horizontal overflow, but only if more than one?
As already explained by wf4, the horizontal scroll is present because of the vertical scroll. which you can solve by giving max-width: 100%
.
.box {
width: 100vw;
height: 100vh;
max-width:100%; /* added */
}
Working Fiddle
Why there is a scroll on x-axis when width is 100vw?
Because setting width to 100vw
will give 100vw
width to the element + any padding or margins which results in overflow
100vw element = 100vw width + padding + margin
which is not the case with 100%;
100% element = 100% width inclusve of margin + padding
Mostly the reason is body
margin. So set body -> margin
to 0
and see it working as 100%.
Prevent 100vw from creating horizontal scroll
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 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;
.
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 to overflow-y: hidden;
.
Example
4. Remove Horizontal Scrollbar
This does not fix the problem, but may be suitable for some situations.
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.
Example
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.
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
Related Topics
Easiest Way to Extract the Urls from an HTML Page Using Sed or Awk Only
Html5 Doctype Putting IE9 into Quirks Mode
How to Make a Chevron Arrow Using CSS
$Http Doesn't Send Cookie in Requests
Setting a Width and Height on an a Tag
How to Prevent Line Break at Hyphens in All Browsers
Internet Explorer 11 Disable "Display Intranet Sites in Compatibility View" via Meta Tag Not Working
Low Latency (< 2S) Live Video Streaming HTML5 Solutions
Difference Between Overflow-Wrap and Word-Break
Href="Tel:" and Mobile Numbers
Why Are My Div Margins Overlapping and How to Fix It
Is It Alright to Use Multiple H1 Tags on the Same Page, But Style Them Differently
Access Control Allow Origin Issue in Angular 2
How to Disable Form Fields Using CSS