How to prevent vh-units from ignoring the scrollbar? - css

I am working on a page layout with a horizontal scrollbar.
I have some panels with fixed widths in a horizontal order, which should all have the viewport height. I decided to test the vh unit to do that.
.panel { height: 100vh; }
This is working fine, until I get a scrollbar.
The problem is, that vh ignores the height used by the scrollbar and therefore adds a vertical scrollbar.
I would like to subtract the height of the scrollbar from the measurements of vh; is there any way to do this?

You could use a parent element with overflow-y: hidden to ensure that you don't get a vertical scrollbar and then safely use 100vh inside it. This is assuming that you do actually need 100vh for some reason and don't just need to fill the vertical space.
HTML
<div id="main">
<div id="container"></div>
</div>
CSS
#main {
width:200vw;
height:100%;
background: red;
position: absolute;
overflow-y: hidden;
}
#container {
height: 100vh;
width:10px;
background: blue;
}

Related

button height in percent makes it flat [duplicate]

I am trying to set a <div> to a certain percentage height in CSS, but it just remains the same size as the content inside it. When I remove the HTML 5 <!DOCTYTPE html> however, it works, the <div> taking up the whole page as desired. I want the page to validate, so what should I do?
I have this CSS on the <div>, which has an ID of page:
#page {
padding: 10px;
background-color: white;
height: 90% !important;
}
I am trying to set a div to a certain percentage height in CSS
Percentage of what?
To set a percentage height, its parent element(*) must have an explicit height. This is fairly self-evident, in that if you leave height as auto, the block will take the height of its content... but if the content itself has a height expressed in terms of percentage of the parent you've made yourself a little Catch 22. The browser gives up and just uses the content height.
So the parent of the div must have an explicit height property. Whilst that height can also be a percentage if you want, that just moves the problem up to the next level.
If you want to make the div height a percentage of the viewport height, every ancestor of the div, including <html> and <body>, have to have height: 100%, so there is a chain of explicit percentage heights down to the div.
(*: or, if the div is positioned, the ‘containing block’, which is the nearest ancestor to also be positioned.)
Alternatively, all modern browsers and IE>=9 support new CSS units relative to viewport height (vh) and viewport width (vw):
div {
height:100vh;
}
See here for more info.
You need to set the height on the <html> and <body> elements as well; otherwise, they will only be large enough to fit the content. For example:
<!DOCTYPE html>
<title>Example of 100% width and height</title>
<style>
html, body { height: 100%; margin: 0; }
div { height: 100%; width: 100%; background: red; }
</style>
<div></div>
bobince's answer will let you know in which cases "height: XX%;" will or won't work.
If you want to create an element with a set ratio (height: % of it's own width), use the aspect-ratio property. Make sure height is not explicitly set on the element for it to work. https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio
.square {
width: 100%;
height: unset;
aspect-ratio: 1 / 1;
}
Historically, the best way to do this was to set the height using padding-bottom. Example for square:
<div class="square-container">
<div class="square-content">
<!-- put your content in here -->
</div>
</div>
.square-container { /* any display: block; element */
position: relative;
height: 0;
padding-bottom: 100%; /* of parent width */
}
.square-content {
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 100%;
}
The square container will just be made of padding, and the content will expand to fill the container. Long article from 2009 on this subject: http://alistapart.com/article/creating-intrinsic-ratios-for-video
In order to use percentage(%), you must define the % of its parent element. If you use body{height: 100%} it will not work because its parent have no percentage in height. In that case in order to work that body height you must add this in html{height:100%}
In other cases to get rid of that defining parent percentage you can use
body{height:100vh}
vh stands for viewport height
You can use 100vw / 100vh. CSS3 gives us viewport-relative units. 100vw means 100% of the viewport width. 100vh; 100% of the height.
<div style="display:flex; justify-content: space-between;background-color: lightyellow; width:100%; height:85vh">
<div style="width:70%; height: 100%; border: 2px dashed red"></div>
<div style="width:30%; height: 100%; border: 2px dashed red"></div>
</div>
Sometimes, you may want to conditionally set the height of a div, such as when the entire content is less than the height of the screen. Setting all parent elements to 100% will cut off content when it is longer than the screen size.
So, the way to get around this is to set the min-height:
Continue to let the parent elements automatically adjust their height
Then in your main div, subtract the pixel sizes of the header and footer div from 100vh (viewport units). In css, something like:
min-height: calc(100vh - 246px);
100vh is full length of the screen, minus the surrounding divs.
By setting min-height and not height, content longer than screen will continue to flow, instead of getting cut off.
With new CSS sizing properties you can get away with not setting exact height on parent. The new block-size and inline-size properties can be used like this:
<!DOCTYPE html>
<style>
#parent {
border: 1px dotted gray;
height: auto; /* auto values */
width: auto;
}
#wrapper {
background-color: violet;
writing-mode: vertical-lr;
block-size: 30%;
inline-size: 70%;
}
#child {
background-color: wheat;
writing-mode: horizontal-tb;
width: 30%; /* set to 100% if you don't want to expose wrapper */
height: 70%; /* none of the parent has exact height set */
}
</style>
<body>
<div id=parent>
<div id=wrapper>
<div id=child>Lorem ipsum dollar...</div>
Resize the browser window in full page mode. I think the values are relative to viewport height and width.
For more info refer: https://www.w3.org/TR/css-sizing-3/
Almost all browsers support it: https://caniuse.com/?search=inline-size

100vw causing horizontal overflow, but only if more than one?

Say you have this:
html, body {margin: 0; padding: 0}
.box {width: 100vw; height: 100vh}
<div class="box">Screen 1</div>
You'll get something that fills the screen, no scrollbars. But add another:
<div class="box">Screen 1</div>
<div class="box">Screen 2</div>
You get not only vertical scrollbars (expected), but a slight horizontal scroll.
I realize you could omit the width, or set it to width: 100%, but I'm curious why this is happening. Isn't 100vw supposed to be "100% of the viewport width"?
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
scrollbars will be included in the vw so the horizontal scroll will be added to allow you to see under the vertical scroll.
When you only have 1 box, it is 100% wide x 100% tall. Once you add 2, its 100% wide x 200% tall, therefore triggering the vertical scrollbar. As the vertical scrollbar is triggered, that then triggers the horizontal scrollbar.
You could add overflow-x:hidden to body
html, body {margin: 0; padding: 0; overflow-x:hidden;}
.box {width: 100vw; height: 100vh; background-color:#ff0000}
.box2 {width: 100vw; height: 100vh; background-color:#ffff00}
http://jsfiddle.net/NBzVV/
I had a similar problem and came up with the following solution using JS and CSS variables.
JS:
function setVw() {
let vw = document.documentElement.clientWidth / 100;
document.documentElement.style.setProperty('--vw', `${vw}px`);
}
setVw();
window.addEventListener('resize', setVw);
CSS:
width: calc(var(--vw, 1vw) * 100);
1vw is a fallback value.
If you're working in a framework (ASP.NET for example) where there's possibly a parent element wrapping around the html, then setting the html's max-width to 100% will solve the problem without using the "band-aid" solution overflow-x: hidden.
html {
max-width: 100%;
}
The reason why 100vw is causing a horizontal scrollbar is well explained in other responses: 100vw counts the width of the vertical scrollbar to the html itself. I think this is a little absurd, but it is what it is, you know :)
Update: As of Chrome version 66, I cannot reproduce the behaviour reported by question anymore. No workaround appears to be needed.
Original Answer
This is actually a bug as reported in this answer and the comments above.
While the workaround in the accepted answer (adding .box {max-width: 100%;}) generally works, I find it noteworthy that it does not currently work for display:table (tested in Chrome). In that case, the only workaround I found is to use width:100% instead.
Broken Fiddle with display:table
Working Fiddle with display:table and width:100%
to get rid of the scrollbar width included in vw i had to do this:
html, body {
overflow-x: hidden;
height: 100vh;
}
*,
html,
body {
margin: 0;
padding: 0;
overflow: hidden;/*add This*/
}
/*and enjoy ^_^ */
You can try:
*{ box-sizing: border-box}
the reason why the content is flowing out of screen is maybe you have extra padding or border on the div and it cause the content out of the broswer

set div width as a percentage of height

I am trying to set the width of the .full_height_div element using pure css, based on its height. It has to be width-relative-to-height, and not height-relative-to-width. The reason for this is that the parent container (.set_rectangle_height) is already a div with height relative to the page width. Obviously, as the page is resized the divs on the page will resize, so i cannot set a fixed width in px for the .full_height_div child.
So .rectangle and .set_rectangle_height make up the parent container which has a width as a percentage of the page and a height relative to this width. See here for an explanation for this method.
But the problem is that then I want to place a div inside the parent with height: 100% and width relative to this height. The aim is then that I will be able to alter the browser window size and everything will keep its aspect ratio.
here is my failed attempt:
.rectangle
{
position: relative;
width: 30%;/*the outermost div is always a % of the page
width, even while resizing*/
display:inline-block;
background-color: green;
}
.set_rectangle_height
{
padding-bottom: 30%;/*this sets the height of the outermost div
to a ratio of 1:3*/
position: relative;
float: left;
width: 100%;
height: 100%;
}
.full_height_div/*this is the div that i want to have a width relative
to its height*/
{
height: 100%;
width: 20px;/*i will delete this once .square_set_width is working*/
position: absolute;
background-color: red;
}
.square_set_width
{
display: inline-block;
padding-left: 100%; /*i want to use something like this line to set
the width of this div to be equal to .full_height_div's height - ie a 1:1 aspect
ratio, but padding-left does not work :( */
position: relative;
height: 100%;
background-color: blue;
}
<div class='rectangle'>
<div class='set_rectangle_height'>
<div class='full_height_div'>
<div class='square_set_width'></div>
</div>
</div>
</div>
So, this is what the above incorrect markup looks like:
And this is what i want it to look like:
I know I could find the blue square percentage height in javascript, then set the width to be equal to this height, but it would be really handy if there is a pure css fix for what I am trying to do. I will be using this structure a lot and I don't really want to go writing code to resize all the divs on my page.
you have to use javascript for that. If I understood you, you want a perfect blue square. Use
var height = $('.square_set_width').height();
$('.square_set_width').css('width',height);
here is a jsfiddle: http://jsfiddle.net/a8kxu/
Edit: instead of doing padding-bottom: 30% do height: 70% instead. Here is another fiddle: http://jsfiddle.net/a8kxu/1/
Edit #2: Sorry, but you cant use css to do this. Its not powerful enough
If i understand you correctly
you can do
#divID {
width: 75%;
margin-left: auto; // this is used to center the container
margin-right: auto;// this as well
}

How to set a div to auto adjust it's height with available browser height

I have a div ( position :fixed ) with varying height depending on the content in it. To have an auto scroll for that i have added overflow-y:auto and assigned a fixed height.
Is there a way to auto set the height of the div so that when the browser space gets changed, the height of the div changes accordingly, and if there is not enough space the scroll bar appears and when there is enough available space the scroll bar disappears.
use position:absolute instead of position: fixed and use the top left, right and bottom co-ordinates and set the scroll to auto;
example HTML:
<div id="resize">
<p>content</p><p>content</p><p>content</p><p>content</p>
</div>
CSS:
#resize {
background: #f00;
color: white;
position: absolute;
top: 100px;
left: 200px;
right: 200px;
bottom: 100px;
overflow: auto;
}
p {line-height: 3; margin: 0;}
Working Example : Here
Use two DIVs, one nested inside of the other.
The outer DIV should be set to position:fixed;max-height:100%;overflow-y:auto
The inner DIV will contain your contents. So far as I can tell, it won't require any specific styles.
What should happen (and what's happening when I test this fix in my browser) is that the outer DIV should shrink-wrap to fit the inner DIV -- but it will not exceed the height of the window. If the inner DIV exceeds the height of the window, it will also exceed the height of the outer DIV, producing a scrollbar.
EDIT: Sample markup:
<div id="outer">
<div class="inner">
Content goes here.
</div>
</div>
And the CSS:
#outer{
position:fixed;
max-height:100%;
overflow-y:auto;
bottom:0; /* sample value */
left:0; /* sample value */
}
#outer div.inner{
/* Whatever style you want the positioned box
to have. Border, padding, background, etc. */
}
You can listen to the resize event on the window and update the width accordingly.
$(window).resize(function() {
});
http://api.jquery.com/resize/
Alternatively, depending on the layout of your page, you might be able to just use height: 100% (or another % that works for you).

create a 1200px div with no page overflow

I have a div on page with a fixed width of 1200px. It's this way because I inserted inside a collection of thumbnails to creates a mosaic. I don't want the mosaic to change if the page is resized.
The problem is that I don't want to have horizontal scrollbars on the page. The div is placed just for visual purposes.
How can I avoid the horizontal navigator scrollbars that is automatically created when browser size is smaller than the div size?
Update: The div can't be positioned fixed.
in css:
html,body {
overflow : hidden;
}
or if you want vertical scrollbars, overflow-x: hidden
or a cleaner way:
<div class="wrapper">
<div class="mosaic"></div>
</div>
and put width:100%;overflow:hidden on the wrapper.
You should be able to do this simply by setting your div to fixed positioning.
.hugediv {
background: blue;
width: 1200px;
height: 200px;
position: fixed;
z-index: 1;
}

Resources