I have a website with center-aligned DIV. Now, some pages need scrolling, some don't. When I move from one type to another, the appearance of a scrollbar moves the page a few pixels to the side. Is there any way to avoid this without explicitly showing the scrollbars on each page?
overflow-y:scroll is correct, but you should use it with the html tag, not body or else you get a double scrollbar in IE 7
So the correct css would be:
html {
overflow-y: scroll;
}
Wrap the content of your scrollable element into a div and apply padding-left: calc(100vw - 100%);.
<body>
<div style="padding-left: calc(100vw - 100%);">
Some Content that is higher than the user's screen
</div>
</body>
The trick is that 100vw represents 100% of the viewport including the scrollbar. If you subtract 100%, which is the available space without the scrollbar, you end up with the width of the scrollbar or 0 if it is not present. Creating a padding of that width on the left will simulate a second scrollbar, shifting centered content back to the right.
Please note that this will only work if the scrollable element uses the page's entire width, but this should be no problem most of the time because there are only few other cases where you have centered scrollable content.
html {
overflow-x: hidden;
margin-right: calc(-1 * (100vw - 100%));
}
Example. Click "change min-height" button.
With calc(100vw - 100%) we can calculate the width of the scrollbar (and if it is not displayed, it will be 0). Idea: using negative margin-right, we can increase the width of <html> to this width. You will see a horizontal scroll bar — it should be hidden using overflow-x: hidden.
I think not. But styling body with overflow: scroll should do. You seem to know that, though.
With scroll always being shown, maybe be not good for layout.
Try to limit body width with css3
body {
width: calc(100vw - 34px);
}
vw is the width of the viewport (see this link for some explanation)
calc calculate in css3
34px stands for double scrollbar width (see this for fixed or this to calculate if you don't trust fixed sizes)
If changing size or after loading some data it is adding the scroll bar then you can try following, create class and apply this class.
.auto-scroll {
overflow-y: overlay;
overflow-x: overlay;
}
I don't know if this is an old post, but i had the same problem and if you want to scroll vertically only you should try overflow-y:scroll
body {
scrollbar-gutter: stable both-edges;
}
New css spec that will help with scrollbar repositioning is on its way:
https://developer.mozilla.org/en-US/docs/Web/CSS/scrollbar-gutter
Summary
I see three ways - each with their own quirks:
scrollbar-gutter as mentioned by Markus T.
overflow: overlay as mentioned by kunalkamble
Add spacing with calc(100vw - 100%) as mentioned Rapti
Here is a StackBlitz demo
Press the "Toggle height" to see the content shift.
scrollbar-gutter
This has limited support but with a #support media query we can use a combination of this and overflow-y: scroll:
html {
overflow-y: scroll;
}
#supports (scrollbar-gutter: stable) {
html {
overflow-y: auto;
scrollbar-gutter: stable;
}
}
In this way content will never shift.
The "problem" with this solution is that there is always a fixed space for the scrollbar.
overflow: overlay
Limited support and it obviously hides anything it overlays. Special care is needed to make sure nothing vital is hidden (also on zoom and text size changes).
Can be combined with scrollbar-gutter:
html {
overflow-y: scroll;
}
#supports (scrollbar-gutter: stable) {
html {
overflow-y: auto;
scrollbar-gutter: stable;
}
}
#supports (overflow-y: overlay) {
html {
overflow-y: overlay;
scrollbar-gutter: auto;
}
}
It is possible to do some negative margin and overflow-x: hidden but this has a risk of hiding vital content under certain situations. Small screen, custom font/zoom size, browser extensions, etc.
calc(100vw - 100%)
This can be done with RTL support like this:
html[dir='ltr'] main {
padding-left: calc(100vw - 100%);
}
html[dir='rtl'] main {
padding-right: calc(100vw - 100%);
}
Where <main> in this case would be the container for the centered content.
Content here will not shift as long as the centered container is smaller than <main>. But as soon as it is 100% of the container a padding will be introduced. See the StackBlitz demo and click "Toggle width".
The "problem" with this solution is that you need media queries to prevent padding on "small screens" and that even on small screens - when the scrollbar should be visible - some shifting will occur because there is no room for 100% content and a scrollbar.
Conclusion
Use scrollbar-gutter perhaps combined with overlay. If you absolutely don't want empty spacing, try the calc solution with media queries.
Simply setting the width of your container element like this will do the trick
width: 100vw;
This will make that element ignore the scrollbar and it works with background color or images.
#kashesandr's solution worked for me but to hide horizontal scrollbar I added one more style for body. here is complete solution:
CSS
<style>
/* prevent layout shifting and hide horizontal scroll */
html {
width: 100vw;
}
body {
overflow-x: hidden;
}
</style>
JS
$(function(){
/**
* For multiple modals.
* Enables scrolling of 1st modal when 2nd modal is closed.
*/
$('.modal').on('hidden.bs.modal', function (event) {
if ($('.modal:visible').length) {
$('body').addClass('modal-open');
}
});
});
JS Only Solution (when 2nd modal opened from 1st modal):
/**
* For multiple modals.
* Enables scrolling of 1st modal when 2nd modal is closed.
*/
$('.modal').on('hidden.bs.modal', function (event) {
if ($('.modal:visible').length) {
$('body').addClass('modal-open');
$('body').css('padding-right', 17);
}
});
I've solved the issue on one of my websites by explicitly setting the width of the body in javascript by the viewport size minus the width of the scrollbar. I use a jQuery based function documented here to determine the width of the scrollbar.
<body id="bodyid>
var bodyid = document.getElementById('bodyid');
bodyid.style.width = window.innerWidth - scrollbarWidth() + "px";
Extending off of Rapti's answer, this should work just as well, but it adds more margin to the right side of the body and hides it with negative html margin, instead of adding extra padding that could potentially affect the page's layout. This way, nothing is changed on the actual page (in most cases), and the code is still functional.
html {
margin-right: calc(100% - 100vw);
}
body {
margin-right: calc(100vw - 100%);
}
Expanding on the answer using this:
body {
width: calc(100vw - 17px);
}
One commentor suggested adding left-padding as well to maintain the centering:
body {
padding-left: 17px;
width: calc(100vw - 17px);
}
But then things don't look correct if your content is wider than the viewport. To fix that, you can use media queries, like this:
#media screen and (min-width: 1058px) {
body {
padding-left: 17px;
width: calc(100vw - 17px);
}
}
Where the 1058px = content width + 17 * 2
This lets a horizontal scrollbar handle the x overflow and keeps the centered content centered when the viewport is wide enough to contain your fixed-width content
If the width of the table won't change, you can set the width of the element (such as tbody) that contains the scrollbar > 100% (allowing extra space for the scrollbar) and set overflow-y to "overlay" (so that the scrollbar stays fixed, and won't shift the table left when it appears). Also set a fixed height for the element with the scrollbar, so the scrollbar will appear once the height is exceeded. Like so:
tbody {
height: 100px;
overflow-y: overlay;
width: 105%
}
Note: you will have to manually adjust the width % as the % of space the scrollbar takes up will be relative to your table width (ie: smaller width of table, more % required to fit the scrollbar, as it's size in pixels is constant)
A dynamic table example:
function addRow(tableID)
{
var table = document.getElementById(tableID);
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);
var colCount = table.rows[0].cells.length;
for(var i=0; i<colCount; i++)
{
var newRow = row.insertCell(i);
newRow.innerHTML = table.rows[0].cells[i].innerHTML;
newRow.childNodes[0].value = "";
}
}
function deleteRow(row)
{
var table = document.getElementById("data");
var rowCount = table.rows.length;
var rowIndex = row.parentNode.parentNode.rowIndex;
document.getElementById("data").deleteRow(rowIndex);
}
.scroll-table {
border-collapse: collapse;
}
.scroll-table tbody {
display:block;
overflow-y:overlay;
height:60px;
width: 105%
}
.scroll-table tbody td {
color: #333;
padding: 10px;
text-shadow: 1px 1px 1px #fff;
}
.scroll-table thead tr {
display:block;
}
.scroll-table td {
border-top: thin solid;
border-bottom: thin solid;
}
.scroll-table td:first-child {
border-left: thin solid;
}
.scroll-table td:last-child {
border-right: thin solid;
}
.scroll-table tr:first-child {
display: none;
}
.delete_button {
background-color: red;
color: white;
}
.container {
display: inline-block;
}
body {
text-align: center;
}
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="test_table.css">
</head>
<body>
<h1>Dynamic Table</h1>
<div class="container">
<table id="data" class="scroll-table">
<tbody>
<tr>
<td><input type="text" /></td>
<td><input type="text" /></td>
<td><input type="button" class="delete_button" value="X" onclick="deleteRow(this)"></td>
</tr>
</tbody>
</table>
<input type="button" value="Add" onclick="addRow('data')" />
</div>
<script src="test_table.js"></script>
</body>
</html>
I tried to fix likely the same issue which caused by twitter bootstrap .modal-open class applied to body. The solution html {overflow-y: scroll} doesn't help. One possible solution I found is to add {width: 100%; width: 100vw} to the html element.
I use to have that problem, but the simples way to fix it is this (this works for me):
on the CSS file type:
body{overflow-y:scroll;}
as that simple! :)
The solutions posted using calc(100vw - 100%) are on the right track, but there is a problem with this: You'll forever have a margin to the left the size of the scrollbar, even if you resize the window so that the content fills up the entire viewport.
If you try to get around this with a media query you'll have an awkward snapping moment because the margin won't progressively get smaller as you resize the window.
Here's a solution that gets around that and AFAIK has no drawbacks:
Instead of using margin: auto to center your content, use this:
body {
margin-left: calc(50vw - 500px);
}
Replace 500px with half the max-width of your content (so in this example the content max-width is 1000px). The content will now stay centered and the margin will progressively decrease all the way until the content fills the viewport.
In order to stop the margin from going negative when the viewport is smaller than the max-width just add a media query like so:
#media screen and (max-width:1000px) {
body {
margin-left: 0;
}
}
Et voilà!
After trying most of the above CSS or JS-based solutions that haven't worked in my case, just wanted to add up to it.
My solution worked for the case where the scrollbar had to disappear on an event (e.g. a button click, cause you've just opened a full-screen menu that should block the page from being scrollable).
This should work when the below styles are applied to the element that turns overflow-y to hidden (in my case it's the body tag):
body {
overflow-x: hidden;
width: 100vw;
margin-right: calc(100vw - 100%);
}
Explanation: The width of your body tag is 100vw (so it includes the scrollbar's width).
By setting the margin-right, the margin only gets applied if your vertical scrollbar is visible (so your page content isn't actually under the scrollbar), meaning the page content will not reposition once overflow-y has changed.
Note: this solution only works for the pages that are not horizontally-scrollable.
Tested on Chrome 89.0, Firefox 87.0, Safari 14.0.3
Update: unfortunately it only works with centered container that doesn't take 100% width - otherwise the scrollbar overlays the piece of content on the right.
My approach is to make the track transparent. The scroll bar thumb color is #C1C1C1 to match the default scrollbar thumb color. You can make it anything you prefer :)
Try this:
html {
overflow-y: scroll;
}
body::-webkit-scrollbar {
width: 0.7em;
background-color: transparent;
}
body::-webkit-scrollbar-thumb {
background: #C1C1C1;
height:30px;
}
body::-webkit-scrollbar-track-piece
{
display:none;
}
I know the question is very old, but there is a new better method.
scrollbar-gutter: stable;
I tried overflow scroll but it didn't work for my case. the scroll bar still adds some kind of (white) padding. what works is changing the width from 100vw to 100%, but for the height it is ok to use 100vh. so this:
const Wrapper = styled.div`
min-height: 100vh
`
const Parent = styled.div`
width: 100%
`
const Children = styled.div`
width: 100%
`
Edit
I've set the width twice because the parent component held a sidebar, and the children. Depending on your use case, you can set it once.
Since I haven't found my solution here I would like to add it:
I did not want a permanent scrollbar (accepted solution) and I also decided to not use negative margins. They didn't (instantly) work for me in chrome and I also did not want to have content possibly disappearing below the scrollbar.
So this is a padding solution.
My web page consists of three parts:
Header (content is left aligned)
MainContent (content is centered)
Footer (content is left and right aligned)
Since the header would look bad with a left padding and since the logo should stay in the corner of the page, I kept it unchanged since the appearing of a scrollbar does not affect it in most cases (except when window width is very small).
Since an even padding is acceptable for both the MainContent and the footer I used only for those both containers the following css:
.main-content, .footer {
/*
* Set the padding to the maximum scrollbar width minus the actual scrollbar width.
* Maximum scrollbar width is 17px according to: https://codepen.io/sambible/post/browser-scrollbar-widths
*/
padding-right: calc(17px - (100vw - 100%));
padding-left: 17px;
}
This will keep the MainContent in the exact center and also work for all scrollbar width up to 17px. One could add a media query removing these paddings for mobile devices that have an overlay scrollbar.
This solution is similar to only adding the left padding and setting the width to "width: calc(100vw - 17px);". I cannot say if it would behave equally in all cases though.
I used some jquery to solve this
$('html').css({
'overflow-y': 'hidden'
});
$(document).ready(function(){
$(window).load(function() {
$('html').css({
'overflow-y': ''
});
});
});
#media screen and (min-width: 1024px){
body {
min-height: 700px
}
}
Contrary to the accepted answer which suggests a permanent scroll bar on the browser window even if the content doesn't overflow the screen, I would prefer using:
html{
height:101%;
}
This is because the appearance of scroll bar makes more sense if the content actually overflows.
This makes more sense than this.
Related
This question already has answers here:
100vw causing horizontal overflow, but only if more than one?
(8 answers)
Closed 4 months ago.
As mentioned in the title, is it possible to calculate the vw without the scrollbars in css only?
For example, my screen has a width of 1920px. vw returns 1920px, great. But my actual body width is only something like 1903px.
Is there a way for me to retrieve the 1903px value with css only (not only for direct children of the body), or do I absolutely need JavaScript for this?
One way to do this is with calc. As far as i know, 100% is the width including scrollbars. So if you do:
body {
width: calc(100vw - (100vw - 100%));
}
You get the 100vw minus the width of the scrollbar.
You can do this with height as well, if you want a square that's 50% of the viewport for example (minus 50% of the scollbar width)
.box {
width: calc(50vw - ((100vw - 100%)/2))
height: 0
padding-bottom: calc(50vw - ((100vw - 100%)/2))
}
I do this by adding a line of javascript to define a CSS variable once the document has loaded:
document.documentElement.style.setProperty('--scrollbar-width', (window.innerWidth - document.documentElement.clientWidth) + "px");
then in the CSS you can use var(--scrollbar-width) to make any adjustments you need for different browsers with/without scrollbars of different widths. You can do something similar for the horizontal scrollbar, if needed, replacing the innerWidth with innerHeight and clientWidth with clientHeight.
COPY & PASTE solution
Here is an easy drop-in solution based on user11990065's answer to set a css variable --scrollbar-width and keep it updated on resizes.
It also gets calculated on DOMContentLoaded and load events so that you don't have to worry about size changes during the initial rendering phase.
You can just copy and paste it to your code as it is vanilla JS (or wrap it in a 'script' tag and paste it directly into your HTML code:
function _calculateScrollbarWidth() {
document.documentElement.style.setProperty('--scrollbar-width', (window.innerWidth - document.documentElement.clientWidth) + "px");
}
// recalculate on resize
window.addEventListener('resize', _calculateScrollbarWidth, false);
// recalculate on dom load
document.addEventListener('DOMContentLoaded', _calculateScrollbarWidth, false);
// recalculate on load (assets loaded as well)
window.addEventListener('load', _calculateScrollbarWidth);
If you have dynamic height changes in your page that might show / hide the scrollbar, you might want to look into Detect Document Height Change with which you can trigger the recalculation also on height changes.
As the value is calculated with JS and set to a fixed value you can use it in calc operations in your CSS, like so:
.full-width {
width: calc(100vw - var(--scrollbar-width));
}
This will give .full-width exactly the available width.
According to the specs, the viewport relative length units do not take scrollbars into account (and in fact, assume that they don't exist).
So whatever your intended behavior is, you cannot take scrollbars into account when using these units.
body { overflow: overlay; }
If you don't want to overcomplicate things, this might be sufficient in certain situations. At least it fixed my issues well enough, since there was enough whitespace between the content and the viewport edges (Windows scrollbar would overlap your 20-ish most right pixels).
Webkit browsers exclude the scrollbars, other include them in the returned width.
This may of course lead to problems: for instance if you have dynamically generated content with ajax that add height dynamically, Safari might switch from a layout to another during page visualization...
Ok, it doesn't happen often, but it's something to be aware about.
On mobile, less problems, cause scrollbars are generally not showed.
That's said, if your problem is calculate exactly the viewport width without scrollbars in all browser, as far as i know, a good method is this:
width = $('body').innerWidth();
having previously set:
body {
margin:0;
}
100vw = width of the screen with scrollbar
100% = width of the screen without scrollbar
It is always preferable to use calc(100% - 50px) while measuring the screen width. Even on windows browsers where scrollbar is visible directly, return the screen width differently when compare with macOS browsers.
It's possible just very "ugly" looking.
First you need to have this script running to get the scrollbar width into a css variable:
document.documentElement.style.setProperty('--scrollbar-width', (window.innerWidth - document.documentElement.clientWidth) + "px");
Now for example if you want "real" 80vw do this:
calc(0.8 * (100vw - var(--scrollbar-width)));
"real" 40vw
calc(0.4 * (100vw - var(--scrollbar-width)));
As long as you're not expecting any actual horizontal scroll, you could use this:
body {
overflow-x: hidden;
}
Which will then just hide the tiny amount of horizontal scroll caused by the auto scrolling Y.
I came across this question while looking for an answer for my case.
I wanted to use WordPress's solution to center a div on the viewport with the viewport's width just like .alignfull would normally.
Situation:
<html>
<body>
<div class="main">
<div class="continer">
<div class="row">
<div class="col-12">
<article>
<div class="content">
<div class="alignfull-or-alignwide">
<p>The content.</p>
</div>
</div>
</article>
</div>
</div>
</div>
</div>
</body>
</html>
My solution:
html {
width: 100vw;
overflow-x: hidden;
}
.alignfull-or-wide {
margin-right: calc(50% - 50vw);
margin-left: calc(50% - 50vw);
width: 100vw;
max-width: 100vw; // change this for wide or w/e.
}
This solved my problem by making the root of the document as wide as the viewport. With this, you essentially ignore the width of any scrollbar.
By setting to 100vw we eliminate the width of the scrollbar on any platform.
By setting the overflow parameter, we prevent any content from being rendered outside of the viewport.
By setting margins, we center the left side of the div to it's relative positioned parent. This usually is the center of the viewport too.
Then, the negative margin pulls it to the left side of the viewport.
By doing the same on the right we create the illusion of the div being centered on the page.
Also something to watch out for: scrollbar-width on csswg.
The only way I found it to work without messing your code with "calc"
is to make the container element size to 100vw; Adding a wrapper around the container for overflow-x; This will make the container to be fullwidth like if the scrollbar was over the content.
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
html{ overflow-y: scroll; }
html, body{ padding:0; margin: 0;}
#wrapper{ overflow-x: hidden; }
.row{ width: 100vw; }
.row:after{ clear: both; content: ''; display: block; overflow: hidden; }
.row-left{ background: blue; float: left; height: 40vh; width: 50vw; }
.row-right{ background: red; float: right; height: 40vh; width: 50vw; }
</style>
</head>
<body>
<div id="wrapper">
<div class="row">
<div class="row-left"></div>
<div class="row-right"></div>
</div>
</div>
</body>
</html>
The vw unit doesn't take the overflow-y scrollbar into account when overflow-y is set to auto.
Change it to overflow-y: scroll; and the vw unit will be the viewport with the scrollbar. Then you can subtract the scrollbar size from the vw value using calc(). You can also define the scrollbar width, so it will be browser-independent.
Only downside to take into account. If the content fits into the screen, the scrollbar is shown anyway. Possible solution is to change from auto to scroll in javascript.
No, there's no way to calculate the vw without the scrollbars in CSS.
However, there's a way to solve the 100vw ruined by the scrollbar on Windows issue. You have to create a full-width element, in this case row--full-width, that beelds out of a Flex container. This solution works on both Mac and Windows:
HTML:
<section>
<div class="container">
<div class="row--full-width"></div>
<div class="row">
<div class="card">
</div>
<div class="card">
</div>
</div>
</div>
</section>
Example: https://jsfiddle.net/ecmv6ho1/show
Code: https://jsfiddle.net/ecmv6ho1/
As you can see in the example above, the row--full-width element bleeds out of the container, and it aligns with the header even when there's a scrollbar.
Tested on Edge 18 (Win), Edge 88 (Win/Mac), and Chrome 88 (Win/Mac).
The easiest way is set the html & body to 100vw:
html, body{ width:100vw; overflow-x: hidden; overflow-y: auto; margin: 0; }
The only problem is the right-most will be cut a little if scrollbar is shown.
If the case were something similar to a slider:
As posted in many answers, width 100% doesn't take into account the scrollbar, while 100vw does. In the case of having many elements that need to take the width of the window and that are nested inside a container already with 100% window width (or whose natural block width would be such), you can use:
Display flex for container
Flex: 0 0 100% for child elements
It's not my solution, but helps me create dropdown fullwidth menu with absolute in relative element in not fullwith span.
We should get scroll with in css var in :root and then use it.
:root{
--scrollbar-width: calc(100vw - 100%);
}
div { margin-right: var(--scrollbar-width); }
https://codepen.io/superkoders/pen/NwWyee
I have a div that may overflow as content is added or removed.
However the UI designer does not want a visible, but inactive scrollbar (as with overflow: scroll), and they don't want the content layout to change when one is added and remove (as with overflow: auto).
Is there a means to get this behavior, and considering the different scrollbars on different platforms and browsers.
https://jsfiddle.net/qy9a2r00/1/
No browser support this property yet (2021), but scrollbar-gutter is a suggested solution for this.
Update: 2022 - all modern browsers except Safari support the property.
The only way to do this is to make the width of the items in the container fixed. And you'll have to be conservative with the width of the scrollbar.
.container {
width: 200px;
height: 200px;
overflow: auto;
overflow-x: hidden;
border: 1px solid black;
}
.item {
width: 200px;
...
https://jsfiddle.net/fr1jnmn6/1/
overflow-y:overlay would be a partial solution to this as in, it solves the problem of not wanting the content layout to change when a scrollbar is added or removed. Extra padding or margin can be added so that scrollbar doesn't obfuscate the div behind
Here's the jsfiddle for the same https://jsfiddle.net/kitwradr/2qcsj6hw/
One cannot know how thick the scrollbar is, using only HTML & CSS and thus do not know the width of the (blue) placeholder.
You might solve such a task using scripting. Force a scrollbar in a hidden container and measure the inner and outer width. The difference being the scrollbar-width. Set this width (e.g. as CSS) to the placeholder element. And in the tricky part hide this element whenever a scrollbar is shown.
The usual solution to this problem is the one you do not want.
You can setup overflow: scroll to reserve space for scrollbar and add a class that makes scrollbar hidden
body {
overflow-y: scroll;
}
Hide the scrollbar by adding class to div (or to body) that will make your scrollbar transparent
.scroll-hidden::-webkit-scrollbar
{
background-color: transparent;
}
.scroll-hidden::-webkit-scrollbar-track
{
background-color: transparent;
}
To check if you have content overflow you can use this lines:
const { body } = document
const overflow = body.scrollHeight > body.clientHeight
If there are no overflow issue we will hide scrollbar and with reserve space
body.classList.add('scroll-hidden')
If content overflow we will show scrollbar
body.classList.remove('scroll-hidden')
Try the solution here https://jsfiddle.net/ycharniauski/y0pwftmq/
It's a bit hacky solution. Hope in future css will have some property to reserve space
You need to have a parent div with a fixed width (the final total width) and a child div with a width 16px smaller.
Then the scrollbar will have 16px free in the parent div.
The width should always be a number (can't be relative value). In the child div, you need to use a number as well. You can't do calc(100%-16px).
<div className="user-list">
<div className="user-list__content">
{content}
</div>
</div>
.user-list {
width: 500px; /* total width */
height: 1000x;
overflow-y: auto;
}
.user-list__content {
width: 484px; /* must be 16px smaller */
height: 100%;
}
This is an ancient question, but in case anyone comes looking.
Detect the scrollbar and show/hide your blue section based on the scrollbar being visible. If scrollbar is visible, HIDE your blue sections (apply a style). If not visible, show your blue padding section.
When the scrollbar becomes visible your padding hides, so the red and green sections will not change size or position.
This article below discusses detecting the scrollbar. You will want to set up a div somewhere to detect the current scrollbar width ahead of time in order to set your blue boxes to the same width.
How can I check if a scrollbar is visible?
Maybe append a div at the bottom will soft your problem ?
https://jsfiddle.net/moongod101/k7w574mw/1/
I'm trying to build a website that has lots of boxes that are of equal width and height. For example, I have a page that has 2 equal size boxes side by side.
The simple solution was to set the width and height to 50vw. This works great until there is a scroll bar. I've Googled around for hours and can't understand why on earth vw and vh would include the scrollbars as part of the viewport.
Here's a sample of my issue
HTML
<div class="container">
<div class="box red"></div>
<div class="box green"></div>
</div>
<div class="lotta-content"></div>
CSS
body {
margin: 0;
padding: 0;
}
.container {
width: 100vw;
}
.box {
float: left;
width: 50vw;
height: 50vw;
}
.red {
background-color: red;
}
.green {
background-color: green;
}
.lotta-content {
height: 10000px;
}
Notice the unwanted horizontal scrollbar
https://jsfiddle.net/3z887swo/
One possible solution would be to use percentages for the widths, but vw for the height, but it won't ever be a perfect box which isn't the worst thing in the world, but still not ideal. Here's a sample
https://jsfiddle.net/3z887swo/1/
Does anyone know why vw/vh include scrollbars as part of the viewport? Also, if someone has a better solution than my own, I'd love to hear it. I'm looking for a pure CSS solution. I rather not have javascript.
I have a different answer, and feel the need to share my frustration
BECAUSE STANDARD-MAKERS ARE STUPID
(committees, in general, always are)
One simple (simplicistic) workaround is keeping the scrollbar always around and be dealt with it
html,body {margin:0;padding:0}
html{overflow-y:scroll}
(use overflow-x for a layout that uses vh)
I believe they seriously screwed the pooch on this one.
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.
html { overflow-x: hidden; }
seems to work
This question is old, and answered well above, so I'm going to focus on obtaining scrollbar width to then be used to calc element widths, as that's why I landed here. Hopefully this will help other Googlers.
A sloppy CSS solution
I started writing the pure CSS solution based on the calculation below but once you start factoring in elements inside variable width containers, especially when they aren't 100% of the visible width, the calc functions start getting convoluted and unreadable.
For anybody interested, this calc on the root element (<html>) (assuming the doc is full width and no wider) will give you the scrollbar width or 0 when no scrollbar is displayed.
calc( 100vw - 100% );
A robust solution
Personally, I wouldn't battle CSS on this one. Use the right tool for the job:
(function get_scrollbar_width() {
// Get window width including scrollbar.
const withScrollBar = window.innerWidth;
// Get window width excluding scrollbar.
const noScrollBar = document.querySelector("html").getBoundingClientRect().width;
// Calc the scrollbar width.
scrollbarWidth = parseInt((withScrollBar - noScrollBar), 10) + 'px';
// Update the CSS custom property value.
let root = document.documentElement;
root.style.setProperty('--scrollbar', scrollbarWidth);
})();
:root {
--scrollbar: 0px;
}
body {
overflow: scroll;
}
.demobox {
display: grid;
grid: auto / var(--scrollbar) max-content;
width: calc(10em + var(--scrollbar) );
margin: 0 auto;
}
.demobox > div {
background: red;
}
.demobox > p {
padding: 1em;
text-align: center;
width: 10em;
}
<div class="demobox">
<div></div>
<p>
This red grid cell represents the scrollbar width as set
on the CSS custom property by the JavaScript function.
</p>
</div>
I have a solution here. It'll include the scrollbar width when you use 100vw, right? so if we can't make it right, then we can remove the scrollbar, make it invisible. like this: Hide scroll bar, but while still being able to scroll
I've been trying to layout this page, but for the life of me, can't seem to get it to work the way I want.
Window = black
Titlebar = red
Content div = blue
Vertical scrollbar = green
Horizontal scrollbar = yellow
Min titlebar/content div width of 1024px, growing to window size.
I may be completely overthinking it and the answer may be way simpler than I'm attempting.
Basically I want to have a fixed titlebar div at the top of the page that never scrolls vertically. If it does not fit in the window horizontally, I want the horizontal scrollbar to scroll both the titlebar and content. If the content div is taller than the window height, I want it to scroll, otherwise I want it to extend to the bottom of the page.
For the most part, I'm under next to no restrictions on how these divs may be set, so imagine there is a blank slate.
Needs to work on modern browsers only on recent OSes. Ideally only a CSS/HTML fix, but will consider some JS if absolutely required. Needs visible scrollbars (some versions I tried the scrollbars were off outside the window scope, ie, not just mousewheel scroll, but click and drag scroll).
I have to edit my answer, because after reading Lokesh Suthar's answer I finally understood your question! ;-)
There is no CSS solution!
You'll find the reason in the spec (http://www.w3.org/TR/CSS2/visuren.html#fixed-positioning):
Fixed positioning is a subcategory of absolute positioning. The only difference is that for a fixed positioned box, the containing block is established by the viewport. For continuous media, fixed boxes do not move when the document is scrolled.
So you have to go with a JS solution like the one Lokesh Suthar has linked to in his answer.
A personal note:
Normally web designer try to avoid horizontal scrollbars at all costs!
They are "bad" for usability and most users hate to scroll horizontally.
And instead of making a fixed positioned element wider than the viewport you should expand its height.
Remember: Using a JS solution on this will make content unreachable/ not visible if JS is disabled!
Pure CSS Solution.
Here's my updated answer. Please check.
Demo link below:
Fiddle
HTML
<div id="title-bar">Title Bar</div>
<div id="content">Contents</div>
CSS
html, body {
margin:0;
padding:0;
height:100%;
}
#title-bar, #content {
min-width:1024px;
width:100%;
}
#title-bar {
position:fixed;
top:0;
background:#CC0000;
height:50px;
color:#fff;
}
#content {
top:50px;
position:relative;
background:#9EC2E3;
height:calc(100% - 50px);
overflow:auto;
}
Just let me know if you have concerns.
I think this may work for you...
Working Example
JS:
$(window).scroll(function () { // on scroll
var win = $(window);
var title = $('.title');
var winWidth = $(window).innerWidth();
var titleWidth = title.width();
if (win.scrollLeft() >= titleWidth - winWidth) { // if scrolled to the right further than .title is wide minus the window's width
title.addClass('fixed'); // add the fixed class
title.offset({ //keep the title bar at the top
top: win.scrollTop(),
});
} else { // if not
title.removeClass('fixed'); // removed class fixed
title.offset({ // keep the title bar at the top anyway
top: win.scrollTop(),
});
}
});
CSS:
* {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
html, body {
width: 1024px;
height:100%
}
.title {
background:red;
position: absolute;
z-index:2;
min-width: 100%;
}
#content {
background: blue;
padding-top:50px;
min-width:1024px;
min-height:100%;
}
.fixed {
position: fixed;
right: 0;
}
API documentation:
.scroll()
.innerWidth()
.width()
.scrollLeft()
.offset()
.addClass()
.removeClass()
With CSS:
In short, it is not possible with position: fixed;.
As already mentioned by other answers, it is not possible to force a fixed div to scroll, because the div becomes positioned in relation to the viewport (thanks #Netsurfer for digging up the link), and there is no way for us to manipulate this.
Alternative 1: You could set overflow of the body to hidden (thereby hiding browser scrollbars) and add a new wrapper div that fills the entire viewport by using viewport units (vh and vw). You would then nest your titlebar and content divs within this wrapper and give it a horizontal scrollbar. Then you would absolutely position your titlebar in relation to a new titlebar wrapper div, while wrapping your content in a div with 100% (minus the titlebar) height and a vertical scrollbar.
See jsfiddle example.
This approach is rather ugly when you consider all the wrappers... also, when you apply a min-width of 1024 pixels to the content, the vertical scrollbar will move out of the viewport when viewed on smaller screens (as you mentioned in your post). You could position the scrollbar on the left side using direction: rtl;, but the scrollbar will still go out of view when scrolling to the right.
See jsfiddle example with scrollbar on left.
All in all it is not a great solution which would need to be heavily tested for cross-browser support any time anything is changed. Currently it works in Chrome 33 (which I am using) and I have also succesfully tested it in Firefox 27, Internet Explorer 11 and Opera 19. Safari 5.1 (windows) does not like it, but it should work on the newer Mac versions. For Safari 5.1 you can try changing to % heights and dropping the css calc() method, but you'll probably have problems scrolling the entire content.
Alternative 2: Wait. In the future you may be able to use position: sticky; to achieve exactly what you want (assuming this new property ever gains complete browser support). You can see it in action with chrome if you enable the "Enable experimental Web Platform features" option under "chrome://flags/".
See jsfiddle example.
With jQuery:
With jQuery this becomes a trivial task if you forget about position: fixed;, and does not require much code. All you would have to do is position the titlebar div absolutely and then tell it to move every time the window is scrolled:
$window.scroll(function() {
$(".title").css('top', $window.scrollTop() + "px");
});
Using .css() is slightly faster than using .offset() (see benchmark tests).
If JS is disabled the titlebar will simply scroll out of view.
See jsfiddle example.
Considering how easy this is with jQuery, I would suggest using that approach.
I think this should answer your query.
CLICK ME
Basically the fellow is trying moving the fixed nav with scroll events(playing with left property as he says)
I used position absolute to set height in percentage.
like for titlebar ,
position:fixed;
height:6%;
you can remove wrapper if you don't want to use,
Click for demo
Let me know more if it need some changes
You have to use a combination of CSS and JavaScript. As the others stated, a fixed element does not scroll and you cannot choose that it should scroll horizontally but not vertically. So there comes the JS.
This is the shortest form I could think of. This should work on mobile devices, too. It works with a inner div in the fixed element, which is positioned absolute and reacts to the windows scroll event.
Here is the codepen example: http://codepen.io/HerrSerker/pen/AJHyf
This just works with a fixed height header. If your header is not fixed in height, you have to add some JavaScript, that measures the height of the header and adds
HTML
<div id="maker"></div>
<header><div id="header_inner">Lorem ipsum dolor sit amet.</div></header>
<main><div id="#main_inner">Lorem ipsum dolor sit amet ...</div></main>
CSS
html,body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
body {
overflow: auto;
}
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
#maker {
width: 1024px;
height: 1px;
margin-top: -1px;
background: red;
}
header {
position: fixed;
min-width: 1024px;
background: black;
color:white;
width: 100%;
height: 50px;
}
#header_inner {
padding: 10px;
}
main {
padding: 0px;
padding-top: 50px;
min-height: 100%;
min-width: 1024px;
background: gold;
color: brown;
}
#main_inner {
padding: 20px;
}
JavaScript
(function() {
var headerInner = document.getElementById('header_inner');
headerInner.style.position = 'absolute';
var scrollReact = function() {
headerInner.style.left = '-'+self.pageXOffset+'px';
}
if ('addEventListener' in self) {
self.addEventListener('scroll', scrollReact);
} else if (typeof self.attachEvent == 'function') {
self.attachEvent('scroll', scrollReact );
}
}())
I have a website with center-aligned DIV. Now, some pages need scrolling, some don't. When I move from one type to another, the appearance of a scrollbar moves the page a few pixels to the side. Is there any way to avoid this without explicitly showing the scrollbars on each page?
overflow-y:scroll is correct, but you should use it with the html tag, not body or else you get a double scrollbar in IE 7
So the correct css would be:
html {
overflow-y: scroll;
}
Wrap the content of your scrollable element into a div and apply padding-left: calc(100vw - 100%);.
<body>
<div style="padding-left: calc(100vw - 100%);">
Some Content that is higher than the user's screen
</div>
</body>
The trick is that 100vw represents 100% of the viewport including the scrollbar. If you subtract 100%, which is the available space without the scrollbar, you end up with the width of the scrollbar or 0 if it is not present. Creating a padding of that width on the left will simulate a second scrollbar, shifting centered content back to the right.
Please note that this will only work if the scrollable element uses the page's entire width, but this should be no problem most of the time because there are only few other cases where you have centered scrollable content.
html {
overflow-x: hidden;
margin-right: calc(-1 * (100vw - 100%));
}
Example. Click "change min-height" button.
With calc(100vw - 100%) we can calculate the width of the scrollbar (and if it is not displayed, it will be 0). Idea: using negative margin-right, we can increase the width of <html> to this width. You will see a horizontal scroll bar — it should be hidden using overflow-x: hidden.
I think not. But styling body with overflow: scroll should do. You seem to know that, though.
With scroll always being shown, maybe be not good for layout.
Try to limit body width with css3
body {
width: calc(100vw - 34px);
}
vw is the width of the viewport (see this link for some explanation)
calc calculate in css3
34px stands for double scrollbar width (see this for fixed or this to calculate if you don't trust fixed sizes)
If changing size or after loading some data it is adding the scroll bar then you can try following, create class and apply this class.
.auto-scroll {
overflow-y: overlay;
overflow-x: overlay;
}
I don't know if this is an old post, but i had the same problem and if you want to scroll vertically only you should try overflow-y:scroll
body {
scrollbar-gutter: stable both-edges;
}
New css spec that will help with scrollbar repositioning is on its way:
https://developer.mozilla.org/en-US/docs/Web/CSS/scrollbar-gutter
Summary
I see three ways - each with their own quirks:
scrollbar-gutter as mentioned by Markus T.
overflow: overlay as mentioned by kunalkamble
Add spacing with calc(100vw - 100%) as mentioned Rapti
Here is a StackBlitz demo
Press the "Toggle height" to see the content shift.
scrollbar-gutter
This has limited support but with a #support media query we can use a combination of this and overflow-y: scroll:
html {
overflow-y: scroll;
}
#supports (scrollbar-gutter: stable) {
html {
overflow-y: auto;
scrollbar-gutter: stable;
}
}
In this way content will never shift.
The "problem" with this solution is that there is always a fixed space for the scrollbar.
overflow: overlay
Limited support and it obviously hides anything it overlays. Special care is needed to make sure nothing vital is hidden (also on zoom and text size changes).
Can be combined with scrollbar-gutter:
html {
overflow-y: scroll;
}
#supports (scrollbar-gutter: stable) {
html {
overflow-y: auto;
scrollbar-gutter: stable;
}
}
#supports (overflow-y: overlay) {
html {
overflow-y: overlay;
scrollbar-gutter: auto;
}
}
It is possible to do some negative margin and overflow-x: hidden but this has a risk of hiding vital content under certain situations. Small screen, custom font/zoom size, browser extensions, etc.
calc(100vw - 100%)
This can be done with RTL support like this:
html[dir='ltr'] main {
padding-left: calc(100vw - 100%);
}
html[dir='rtl'] main {
padding-right: calc(100vw - 100%);
}
Where <main> in this case would be the container for the centered content.
Content here will not shift as long as the centered container is smaller than <main>. But as soon as it is 100% of the container a padding will be introduced. See the StackBlitz demo and click "Toggle width".
The "problem" with this solution is that you need media queries to prevent padding on "small screens" and that even on small screens - when the scrollbar should be visible - some shifting will occur because there is no room for 100% content and a scrollbar.
Conclusion
Use scrollbar-gutter perhaps combined with overlay. If you absolutely don't want empty spacing, try the calc solution with media queries.
Simply setting the width of your container element like this will do the trick
width: 100vw;
This will make that element ignore the scrollbar and it works with background color or images.
#kashesandr's solution worked for me but to hide horizontal scrollbar I added one more style for body. here is complete solution:
CSS
<style>
/* prevent layout shifting and hide horizontal scroll */
html {
width: 100vw;
}
body {
overflow-x: hidden;
}
</style>
JS
$(function(){
/**
* For multiple modals.
* Enables scrolling of 1st modal when 2nd modal is closed.
*/
$('.modal').on('hidden.bs.modal', function (event) {
if ($('.modal:visible').length) {
$('body').addClass('modal-open');
}
});
});
JS Only Solution (when 2nd modal opened from 1st modal):
/**
* For multiple modals.
* Enables scrolling of 1st modal when 2nd modal is closed.
*/
$('.modal').on('hidden.bs.modal', function (event) {
if ($('.modal:visible').length) {
$('body').addClass('modal-open');
$('body').css('padding-right', 17);
}
});
I've solved the issue on one of my websites by explicitly setting the width of the body in javascript by the viewport size minus the width of the scrollbar. I use a jQuery based function documented here to determine the width of the scrollbar.
<body id="bodyid>
var bodyid = document.getElementById('bodyid');
bodyid.style.width = window.innerWidth - scrollbarWidth() + "px";
Extending off of Rapti's answer, this should work just as well, but it adds more margin to the right side of the body and hides it with negative html margin, instead of adding extra padding that could potentially affect the page's layout. This way, nothing is changed on the actual page (in most cases), and the code is still functional.
html {
margin-right: calc(100% - 100vw);
}
body {
margin-right: calc(100vw - 100%);
}
Expanding on the answer using this:
body {
width: calc(100vw - 17px);
}
One commentor suggested adding left-padding as well to maintain the centering:
body {
padding-left: 17px;
width: calc(100vw - 17px);
}
But then things don't look correct if your content is wider than the viewport. To fix that, you can use media queries, like this:
#media screen and (min-width: 1058px) {
body {
padding-left: 17px;
width: calc(100vw - 17px);
}
}
Where the 1058px = content width + 17 * 2
This lets a horizontal scrollbar handle the x overflow and keeps the centered content centered when the viewport is wide enough to contain your fixed-width content
If the width of the table won't change, you can set the width of the element (such as tbody) that contains the scrollbar > 100% (allowing extra space for the scrollbar) and set overflow-y to "overlay" (so that the scrollbar stays fixed, and won't shift the table left when it appears). Also set a fixed height for the element with the scrollbar, so the scrollbar will appear once the height is exceeded. Like so:
tbody {
height: 100px;
overflow-y: overlay;
width: 105%
}
Note: you will have to manually adjust the width % as the % of space the scrollbar takes up will be relative to your table width (ie: smaller width of table, more % required to fit the scrollbar, as it's size in pixels is constant)
A dynamic table example:
function addRow(tableID)
{
var table = document.getElementById(tableID);
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);
var colCount = table.rows[0].cells.length;
for(var i=0; i<colCount; i++)
{
var newRow = row.insertCell(i);
newRow.innerHTML = table.rows[0].cells[i].innerHTML;
newRow.childNodes[0].value = "";
}
}
function deleteRow(row)
{
var table = document.getElementById("data");
var rowCount = table.rows.length;
var rowIndex = row.parentNode.parentNode.rowIndex;
document.getElementById("data").deleteRow(rowIndex);
}
.scroll-table {
border-collapse: collapse;
}
.scroll-table tbody {
display:block;
overflow-y:overlay;
height:60px;
width: 105%
}
.scroll-table tbody td {
color: #333;
padding: 10px;
text-shadow: 1px 1px 1px #fff;
}
.scroll-table thead tr {
display:block;
}
.scroll-table td {
border-top: thin solid;
border-bottom: thin solid;
}
.scroll-table td:first-child {
border-left: thin solid;
}
.scroll-table td:last-child {
border-right: thin solid;
}
.scroll-table tr:first-child {
display: none;
}
.delete_button {
background-color: red;
color: white;
}
.container {
display: inline-block;
}
body {
text-align: center;
}
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="test_table.css">
</head>
<body>
<h1>Dynamic Table</h1>
<div class="container">
<table id="data" class="scroll-table">
<tbody>
<tr>
<td><input type="text" /></td>
<td><input type="text" /></td>
<td><input type="button" class="delete_button" value="X" onclick="deleteRow(this)"></td>
</tr>
</tbody>
</table>
<input type="button" value="Add" onclick="addRow('data')" />
</div>
<script src="test_table.js"></script>
</body>
</html>
I tried to fix likely the same issue which caused by twitter bootstrap .modal-open class applied to body. The solution html {overflow-y: scroll} doesn't help. One possible solution I found is to add {width: 100%; width: 100vw} to the html element.
I use to have that problem, but the simples way to fix it is this (this works for me):
on the CSS file type:
body{overflow-y:scroll;}
as that simple! :)
The solutions posted using calc(100vw - 100%) are on the right track, but there is a problem with this: You'll forever have a margin to the left the size of the scrollbar, even if you resize the window so that the content fills up the entire viewport.
If you try to get around this with a media query you'll have an awkward snapping moment because the margin won't progressively get smaller as you resize the window.
Here's a solution that gets around that and AFAIK has no drawbacks:
Instead of using margin: auto to center your content, use this:
body {
margin-left: calc(50vw - 500px);
}
Replace 500px with half the max-width of your content (so in this example the content max-width is 1000px). The content will now stay centered and the margin will progressively decrease all the way until the content fills the viewport.
In order to stop the margin from going negative when the viewport is smaller than the max-width just add a media query like so:
#media screen and (max-width:1000px) {
body {
margin-left: 0;
}
}
Et voilà!
After trying most of the above CSS or JS-based solutions that haven't worked in my case, just wanted to add up to it.
My solution worked for the case where the scrollbar had to disappear on an event (e.g. a button click, cause you've just opened a full-screen menu that should block the page from being scrollable).
This should work when the below styles are applied to the element that turns overflow-y to hidden (in my case it's the body tag):
body {
overflow-x: hidden;
width: 100vw;
margin-right: calc(100vw - 100%);
}
Explanation: The width of your body tag is 100vw (so it includes the scrollbar's width).
By setting the margin-right, the margin only gets applied if your vertical scrollbar is visible (so your page content isn't actually under the scrollbar), meaning the page content will not reposition once overflow-y has changed.
Note: this solution only works for the pages that are not horizontally-scrollable.
Tested on Chrome 89.0, Firefox 87.0, Safari 14.0.3
Update: unfortunately it only works with centered container that doesn't take 100% width - otherwise the scrollbar overlays the piece of content on the right.
My approach is to make the track transparent. The scroll bar thumb color is #C1C1C1 to match the default scrollbar thumb color. You can make it anything you prefer :)
Try this:
html {
overflow-y: scroll;
}
body::-webkit-scrollbar {
width: 0.7em;
background-color: transparent;
}
body::-webkit-scrollbar-thumb {
background: #C1C1C1;
height:30px;
}
body::-webkit-scrollbar-track-piece
{
display:none;
}
I know the question is very old, but there is a new better method.
scrollbar-gutter: stable;
I tried overflow scroll but it didn't work for my case. the scroll bar still adds some kind of (white) padding. what works is changing the width from 100vw to 100%, but for the height it is ok to use 100vh. so this:
const Wrapper = styled.div`
min-height: 100vh
`
const Parent = styled.div`
width: 100%
`
const Children = styled.div`
width: 100%
`
Edit
I've set the width twice because the parent component held a sidebar, and the children. Depending on your use case, you can set it once.
Since I haven't found my solution here I would like to add it:
I did not want a permanent scrollbar (accepted solution) and I also decided to not use negative margins. They didn't (instantly) work for me in chrome and I also did not want to have content possibly disappearing below the scrollbar.
So this is a padding solution.
My web page consists of three parts:
Header (content is left aligned)
MainContent (content is centered)
Footer (content is left and right aligned)
Since the header would look bad with a left padding and since the logo should stay in the corner of the page, I kept it unchanged since the appearing of a scrollbar does not affect it in most cases (except when window width is very small).
Since an even padding is acceptable for both the MainContent and the footer I used only for those both containers the following css:
.main-content, .footer {
/*
* Set the padding to the maximum scrollbar width minus the actual scrollbar width.
* Maximum scrollbar width is 17px according to: https://codepen.io/sambible/post/browser-scrollbar-widths
*/
padding-right: calc(17px - (100vw - 100%));
padding-left: 17px;
}
This will keep the MainContent in the exact center and also work for all scrollbar width up to 17px. One could add a media query removing these paddings for mobile devices that have an overlay scrollbar.
This solution is similar to only adding the left padding and setting the width to "width: calc(100vw - 17px);". I cannot say if it would behave equally in all cases though.
I used some jquery to solve this
$('html').css({
'overflow-y': 'hidden'
});
$(document).ready(function(){
$(window).load(function() {
$('html').css({
'overflow-y': ''
});
});
});
#media screen and (min-width: 1024px){
body {
min-height: 700px
}
}
Contrary to the accepted answer which suggests a permanent scroll bar on the browser window even if the content doesn't overflow the screen, I would prefer using:
html{
height:101%;
}
This is because the appearance of scroll bar makes more sense if the content actually overflows.
This makes more sense than this.