I am trying to understand if (and how) you can use the em measurement for CSS properties that set the width and height of elements for an elastic design layout (width, height, min-width, min-height, max-width and max-height). The problem relates to the layout position of the main wrapper. I don't understand when, and how you should use the em measurement for width and height properties when designing my layout (not for sizing). If I, for example, want the width of the main wrapper to be 90 % of the body-element, how can I achieve that using em instead of %?
I have searched Stack Overflow for similar questions, but the answers include things like responsive design, JavaScript and JQuery. I can only use HTML5 and CSS3. I have also tried to set the width and height using different values for em, but then main wrapper does not stay centered or exceeds the screen size.
Here is a code snippet of what I have tried. The full code is available on JSFiddle
<div id="page">
<header>
<nav></nav>
</header>
<div id="content">
<article></article>
<article></article>
</div>
<aside></aside>
<footer></footer>
</div>
#page {
position: relative;
width: 90em;
height: 90em;
top: 1em;
right: 1em;
bottom: 1em;
left: 1em;
}
The code above makes the main wrapper exceed the screen size, both vertically and horizontally. I want the results to equal that of using 90 % instead of 90em for width and height.
em measurements are based on font-size
What you will need to use is either % or vw (viewport units)
I would recommend using % as vw/vh can have some strange bugs on mobile safari:
100% is not always the same as 100vh when there is an address bar showing.
100% will shrink the content to fit when an address bar shows
100vh won't so your content might appear under the address bar
How do I set the height of a div container for example that should be 60% of the screen height?
Setting the 60% as the height in css works fine if the browser window is not resized. But if I shrink the browser window, the div shrinks accordingly.
https://zurb.com provides a nice example. The "Mission Accomplished", grey part is always the same height, no matter how the browser window is being resized. How can this be ensured?
I don't want to use px to ensure HiDpi support.
Thanks,
That's a simple fixed-height element; it has nothing to do with screen size.
You should just use px and not worry about anything; px means logical pixels and will work with arbitrary DPIs.
While the page in question simply used a fixed height (px) for the element in question, meaning that it will always have the same height (and won't be 60% of the height regardless of viewport height). In order to have an element be relative to the viewport, you're looking for viewport-sized typography.
To adjust based on height, you're looking for the CSS unit vh, which tells the element in question to scale based on the viewport height. You can also use vw to scale based on the viewport width.
Keep in mind that <body> has a default of margin: 8px, so if you want to avoid scrollbars when using viewport-sized typography, you'll also need to override this back to 0.
body {
margin: 0;
}
div {
height: 60vh;
width: 100vw;
background: red;
}
<div></div>
For more in-depth information on CSS units, I'd recommend checking out this guide.
Hope this helps! :)
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 header DIV which is 1400px wide and contains a background image which must always stay centered.
I have a site that needs to be 960px wide.
When I resize the browser (shrink it), I don't want any horizontal scrollbars until we hit 960px, but the larger width on the header/background is causing this.
Is it possible to stop all horizontal scrollbars on resize until 960px AND keep the background image in the header div centered??
Any help appreciated! Some code I set up here here for a quick test...
http://jsfiddle.net/gVuvk
The background image has a width of 1400px. I need the scrollbars to start at 960px - NOT 1400px. Is this possible?
change #header width from fixed pixels to 100%
Demo: http://jsfiddle.net/wNSTD/3/
Try fiddling with min-width, if that does not work, use margins, css auto-margins can be useful here. So, make the structure like this:
<style>
.center_image
{
margin: auto auto; // or you can modify the x or y seperately
background-image:url("somesite.jpg");
}
</style>
<div class="outer">
<div class="center_image">
Set the width of header to 100% and center the background image.
background: url(http://fade.com.au/test/bg-image.jpg) no-repeat center center;
width: 100%;
Demo: http://jsfiddle.net/post_erasmus/Hn6Zb/1/
I want a top margin for my webpage of say 100px when the window is maximised, but if the user resizes the window to shrink it I want this margin to shrink. The margin should have a minimum size of say 10px and should shrink in proportion to the window height.
An example if what I am trying to emulate is http://www.bing.com/
How would I go about implementing this in CSS? I'm stuggling with min-height, min-width, height and width at the moment.
Thanks.
Without seeing some code, it's difficult to give a great suggestion. But, you can style the html and body to be 100% height which should actually conform to the height of the viewable portion of the browser:
html, body{ margin:0; padding:0; height:100%; }
From there, you can add a div directly into the body and give that a height that is a percentage:
#push{ height: 15%; }
Your body html would look something like:
<body>
<div id="push"></div>
<div>
asdf asdf
</div>
</body>
When the body height changes, so will the push height. You may need to tweak that number to get it to your liking. You can also give the push a min-height, but that is not supported in IE6. Also, that 100% html / body could give you trouble later depending on how you're doing your footer and things, so beware and good luck.