Does Safari 15 finally fix viewport height?

Written by Luke Channings on June 11, 2021

The design for Safari 15 has been very controvercial, and has changed significantly since the beta that this article was based on Sadly, one of the casualties of the evolving design was the main thrust of this article: env(safe-area-inset-bottom) is no longer dynamically the height of the address bar in the final release.

TL;DR : No , but if you subtract env(safe-area-inset-bottom) from 100vh you'll get what you want .

Safari 15's UI is a radical departure from the previous version — and from web browsers in general — but does it fix the viewport height problem?

What is the viewport height problem again?

Mobile Safari has had problems related to 100vh not behaving like web developers expect 1 2 pretty much since the beginning. The main crux of the issue is that Mobile Safari's UI Chrome shrinks when you scroll, and expands again when you activate it. That means 100vh ("100% the height of the viewport") can't be a static number.

Let's start by understanding the definition of the vh unit 3 :

vh is defined as Equal to 1% of the height of the initial containing block . — Anthony Frehner

And here's the best explanation of the 100vh issues in Mobile Safari that I've seen so far,

The core issue is that mobile browsers (I’m looking at you, Chrome and Safari) have a “helpful” feature where the address bar is sometimes visible and sometimes hidden, changing the visible size of the viewport. Rather than adjusting the height of 100vh to be the visible portion of the screen as the viewport height changes, these browsers instead have 100vh set to the height of the browser with the address bar hidden. The result is that the bottom portion of the screen will be cut off when the address bar is visible, thus defeating the purpose of 100vh to begin with. — David Chanin , Avoid 100vh On Mobile Web

Let's put this new Safari to the test

I have a simple HTML page based on the example given in David's article. It has a header at the top and a button at the bottom, all wrapped in a 100vh container.

an image showing the aforementioned button hidden below the bottom UI controls in iOS 14's Mobile Safari

Safari's new floating address bar is displayed above our test button, which is more-or-less exactly the same behaviour as iOS 14.

So - Safari 15 does not change the behavour of 100vh 😢.

So what's the solution then?

It makes sense to me that the WebKit team wouldn't change the behaviour of the viewport unit, it's already well defined.

Do you remember when Apple introduced env() and safe-area-inset so that web developers could avoid their content being shown behind the notch 4 ?

Well in Safari 14, safe-area-inset-bottom is 0px whether the UI chrome is active or inactive, which is something that has annoyed me for a while.

safe-area-inset-bottom is 0px when the UI chrome is inactive in Safari 15 on iOS, and then the height of the collapsed chrome minus the height of the expanded chrome when the bar is expanded.

That means that to get a button to float at the bottom of the page, always above the UI Chrome, all you have to do is use calc(100vh - env(safe-area-inset-bottom)) .

Wrapping up

So not only does safe-area-inset-bottom work in Safari 15, it's animated !

I've been hoping that something to remedy the viewport height bug was coming since Jen Simmons (who joined the Safari / WebKit team in June 2020) was asking for feedback regarding viewport height issues.

Hey everyone who’s been frustrated that VH units in CSS don’t do what you need… can you describe your usecase? What layout are you creating? With which layout mechanism? What do you need? Screenshots & sample code appreciated. — Jen Simmons ( @jensimmons ) May 15, 2021
Have a feeling I’m going to be talking about Environment Variables a lot this week. They are really cool & supported! https://developer.mozilla.org/en-US/docs/Web/CSS/env() https://caniuse.com/css-env-function padding-bottom: calc(1rem + env(safe-area-inset-bottom)); -or- height: calc(100vh - env(safe-area-inset-bottom)); — Jen Simmons ( @jensimmons ) June 7, 2021
  • https://bugs.webkit.org/show_bug.cgi?id=141832 ↩
  • https://css-tricks.com/the-trick-to-viewport-units-on-mobile/ ↩
  • https://github.com/w3c/csswg-drafts/issues/4329 ↩
  • https://webkit.org/blog/7929/designing-websites-for-iphone-x/ ↩

DEV Community

DEV Community

Rachel

Posted on Nov 19, 2021 • Updated on Oct 30, 2022

A Javascript fix for the 100vh problem on mobile screens

I'm a software development student at Developers Institute NZ, and this is my first public post. 🎉

I figured this would be the perfect place to share a slightly obscure fix that has helped me recently. A few weeks ago, my boss at the lovely cafe I work at on the weekends asked me if I'd be willing to take on some extra hours at work to help with their new landing page. I agreed, however, the brief turned out to be a little trickier than I'd first anticipated! My boss (who is also a graphic designer) had created a gorgeous, eye-catching full-page design. However, it only really works if the entire page is displayed on load, with no scroll bars.

My first thought was to just make everything 100vh. However, of course it's never that simple - as I'm sure many people would have come across, 100vh is not always... 100vh. On some mobile browsers, most commonly Chrome and Safari on iOS, 100vh actually refers to outerHeight. This means the lower toolbar on the browser will not be taken into account, cutting off the last couple of rems of your design. While you can account for the difference using CSS, the view height will subsequently change as soon as the user starts scrolling down and the lower browser toolbar disappears.

(An interesting fact I found while researching this is that this behaviour is completely intentional! Have a look at this blog from 2015 if you're interested.)

While this isn't really an issue for most websites, there are a few different threads on the topic floating around. Unfortunately, CSS fill-available wasn't working for me. The most interesting solution I found was this comment buried in a thread in Elementor's Github repo. It uses Javascript to get innerHeight and assign it to the min-height CSS property for the outer container of the design. In order to change the innerHeight when the user starts scrolling and the browser toolbars shrink, we use an event listener. This worked perfectly for the design of the cafe's landing page.

Here is the solution I used, adapted from that comment:

If you're using Wordpress (which I was), the easiest way to insert this is to wrap it in a script tag and add it into an HTML component underneath ALL other content, and then remove all padding from it so no white space is visible. Depending on your design, theme, and plugins, you may also need to add more lines to the function to include any containers for which you'd usually need to re-state the 100vh rule, for example perhaps .elementor-container and .elementor-widget-wrap if you're using Elementor.

While this is not the cheapest solution due to the event listener, it was exactly what I needed for this particular project. Hope someone else finds it useful or interesting! 👋

Top comments (2)

pic

Templates let you quickly answer FAQs or store snippets for re-use.

ilxanlar profile image

  • Joined Mar 4, 2022

You can also take a quick look at this article: Fix 100vh Issue on Mobile Devices

zaxwebs profile image

  • Joined Dec 25, 2020

Ah, yes, this will certaily help me in future. Thanks for the article, Rachel.

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink .

Hide child comments as well

For further actions, you may consider blocking this person and/or reporting abuse

iankcode profile image

Creating a custom logger in Node JS using Winston

Ian Kamau - Apr 11

facubotta profile image

Meta Data in React

Facundo Botta - Apr 10

mrinasugosh profile image

React vs Angular vs Vue - What's the right framework for your project?

Mrinalini Sugosh (Mrina) - Apr 18

waveplay-staff profile image

Getting credentials for your Discord Activity

WavePlay Staff - Apr 18

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

CSS fix for 100vh in mobile WebKit

Not long ago there was some buzz around how WebKit handles 100vh in CSS, essentially ignoring the bottom edge of the browser viewport. Some have suggested not using 100vh , others have come up with different alternatives to work around the problem. In fact, this issue goes further back a few years when Nicolas Hoizey filed a bug with WebKit on the subject (the short of it: WebKit says this is “intentional” 🧐 ).

The other day I was doing some work with a basic flexbox layout – header, main, sticky footer – the kind we’ve all seen and used many times before:

I began running some browser tests on my iPhone, and that’s when I noticed that my sticky footer wasn’t looking so sticky:

iPhone screen showing sticky footer below Safari browser's menu bar.

The footer was hiding below Safari’s menu bar. This is the 100vh bug (feature?) that Nicolas originally uncovered and reported. I did a little sleuthing – hoping that maybe by now a non-hacky fix had been found – and that’s when I stumbled upon my own solution (btw, it’s totally hacky):

🔥 TIL a #CSS trick to handle that annoying mobile viewport bug with `100vh` in WebKit (iOS Safari)! #WebDev #ProTip pic.twitter.com/lefD0Klqzd — Matt Smith (@AllThingsSmitty) April 25, 2020

Using -webkit-fill-available

The idea behind -webkit-fill-available – at least at one point – was to allow for an element to intrinsically fit into a particular layout, i.e., fill the available space for that property. At the moment intrinsic values like this aren’t fully supported by the CSSWG.

However, the above problem is specifically in WebKit, which does support -webkit-fill-available . So with that in mind, I added it to my ruleset with 100vh as the fallback for all other browsers.

And now the sticky footer is right where I want it to be in mobile Safari!

iPhone screen showing sticky footer at the bottom of the viewport above Safari browser's menu bar

Does this really work?

The jury seems to be out on this. I’ve had no problems with any of the tests I’ve run and I’m using this method in production right now. But I did receive a number of responses to my tweet pointing to other possible problems with using this (e.g., the effect on rotating devices, Chrome not completely ignoring the property, etc.).

Will -webkit-fill-available work in every scenario? Probably not, cuz let’s be honest: this is the web, and it can be damn hard to build. But, if you’re having a problem with 100vh in WebKit and you’re looking for a CSS alternative, you might want to try this.

See the Pen CSS Fix for 100vh Mobile ViewPort Bug by Matt Smith ( @AllThingsSmitty ) on CodePen .

100VH Viewport Safari Fix using Intrinsic Sizing

About the use of using -webkit-fill-available.

The idea behind -webkit-fill-available – at least at one point – was to allow for an element to intrinsically fit into a particular layout, i.e., fill the available space for that property.

At the moment intrinsic values like this aren’t fully supported by the CSSWG. However, the above problem is specifically in WebKit, which does support -webkit-fill-available.

The issue, and the fix

The orange div, set to height:100vh, goes under the webkit's browser bottom bar.

The black footer, supposedly stuck to the bottom of the viewport, being masked by the browser bottom bar.

Using -webkit-fill-available, the viewport height is calculated as expected.

body {  min-height: 100vh;  min-height: -webkit-fill-available ; }

I'm a footer, set to Position:Sticky to the bottom, and I should be seen entirely on webkit browsers on mobile.

  • Web Development

Fixing the iOS Toolbar Overlap Issue with CSS Viewport Units

One of the most exciting aspects of web development in recent years has been the continued growth and improvement of CSS. Flexbox and grid revolutionized how we build webpage layouts. Custom properties (aka, CSS variables) opened up new possibilities for theming. Newer selectors like :has() , :is() , and :where() have lead to more powerful and concise CSS. Container queries are now a reality and looking ahead, native CSS nesting is on its way ( decisions concerning its syntax notwithstanding).

But all of these new and upcoming features means that CSS is becoming increasingly complicated. Inevitably, then, some new features might fall through the cracks and get overlooked. (Which is why I’m of the opinion that “full-time CSS engineer” ought to be a thing, but that’s a topic for another post.) Speaking personally, I’m still pretty ignorant concerning the benefits of newer color formats like hwb() and lch() . Which brings me to viewport units.

Put simply, viewport units allow you to size a page’s elements relative to the size of the browser’s viewport , which contains everything that is currently visible on a webpage. (The viewport is basically the browser window minus any UI elements like the navigation and search bar.)

Consider this very simple example:

The vh stands for “viewport height,” so an element set to 100vh will be 100% of the viewport’s height. If that element’s height is set to 50vh , then it’ll be 50% of the viewport’s height, and so on. The 100vh is often used when you want an element to fill up the entire browser window. For instance, I use this technique on special features (like my recent David Zindell post ) to make their headers fill up the entire viewport with a splashy image. This gives them some extra visual oomph that sets them apart from my “normal” posts.

Not All Viewports Are the Same

This approach works well except for one pretty prominent scenario. If you’re viewing such a layout in Safari on an iOS device, that 100vh element fills up the viewport, but its bottom portion is then covered by a toolbar that includes the next/previous navigation and other controls. (See Figure A.)

Note: Although I’m focusing on iOS Safari, this issue also occurs in iOS Chrome. It doesn’t occur in other iOS browsers like Brave, DuckDuckGo, Firefox, and Opera. (More on that in a moment.) I haven’t tested this in any Android browsers.

In other words, Safari doesn’t seem to take its own UI into consideration when drawing its viewport. Thus, a 100vh element doesn’t behave the way it seems like it should, i.e., filling up the space between the URL bar and the bottom toolbar. (Remember that a browser viewport is the browser window minus any UI elements.)

There are, of course, reasons for why Apple opted for this approach. And reading the developer’s explanation  — the viewport’s height changes dynamically because any toolbars disappear or minimize when you scroll — they seem perfectly valid. But that doesn’t mean I liked how it looked. It was hard to believe that this was still an issue the Year of Our Lord 2023.

Various Google searches returned different solutions, including some JavaScript-based workarounds . Using JavaScript to fix visual layout issues, however, always feels hack-y to me. Call me old-fashioned, but I like to keep my CSS and JavaScript nice and separate, and reserved for those things that they do best (e.g., CSS for layout, JavaScript for interactivity).

That aforelinked article also pointed me to Matt Smith’s article about -webkit-fill-available , which seemed promising at first. Unfortunately, it wasn’t applicable to my situation. I didn’t want the post header to simply fill up the entire available space because I also needed to take into account the height of my site’s header, which contains the logo, nav, and search.

Here’s what my original CSS looked like:

The site header is 6 rems high, so I use the calc function to subtract that from the 100vh to dynamically calculate the post header’s new height. But, as pointed out before, iOS doesn’t respond to 100vh the way you might think it would. What I really needed was a new type of CSS unit — and fortunately, I found it.

New Viewport Units

Back in November, Google’s Web.dev blog covered three new viewport units: the “large,” “small,” and “dynamic” viewport units . These units were created specifically to work with viewports whose size might change due to dynamic toolbars —  which was the exact problem I was facing .

  • The “large” viewport units assume that any dynamic toolbars (e.g., Safari’s bottom bar) are retracted and hidden , and calculate the viewport’s size accordingly. (This is akin to Safari’s aforementioned default behavior.)
  • The “small” viewport units assume that any dynamic toolbars are expanded and visible , and calculates the viewport’s size accordingly.
  • The “dynamic” viewport units sit in-between the “large” and “small” units, and react automatically to the dynamic toolbar’s behavior.

At first glance, a “dynamic” viewport unit seemed like the solution. After all, who doesn’t like a web design that automatically responds, all on its own, to a given situation? With that thought in mind, I updated my CSS:

In addition to the original selector, I added a feature query via @supports that basically says if the browser recognizes and supports the height: 100dvh declaration, then run the following CSS. (This is an example of progressive enhancement , i.e., starting with the basics and then adding on more advanced code that modern browsers will recognize.) That CSS is virtually identical to my original CSS, except I’m now using 100dvh instead of 100vh . (The dvh stands for “dynamic viewport height.”)

The first time I loaded the page, the problem seemed to be solved: the post header now filled up the space between Safari’s toolbars without anything cut off or hidden. But then I scrolled a little bit.

When you scroll down in iOS, the browser’s toolbars disappear or reduce in size, thus increasing the height of the browser’s viewport. Conversely, scrolling back to the top causes the toolbars to reappear or return to their original size, thus decreasing the viewport’s height. This behavior caused some distracting (IMO) changes to the post header: the background image expanded while the text shifted down in response to the additional height.

Interestingly, this “dynamic” approach is the behavior employed by the iOS versions of Brave, DuckDuckGo, Firefox, and Opera. In other words, toolbar overlap appears to be a non-issue for them, at least as far as Opus is concerned.

So after giving it some more thought, I replaced 100dvh with 100svh  — i.e., the “small” viewport height — which assumes that any toolbars are always expanded.

Here’s my final code:

You can see the results — that is, the entire post header — in Figure B. Upon scrolling, the post header doesn’t take advantage of the increased viewport height, so it’s not a truly “full-height” element. However, it doesn’t have any weird shifting, either, but looks the same all the time. And I always prefer such stability in my web designs.

For what it’s worth, Firefox, Brave, et al . ignore the 100svh setting altogether, and instead, always stick with the “dynamic” handling of the viewport and post header heights. That’s a little frustrating, but since they represent a relatively minuscule amount of Opus ’ overall traffic, I’m not going to sweat it.

Final Thoughts

Along with the aforementioned color formats, viewport units are one of those aspects of CSS that has always felt rather abstract to me. (Then again, I still have trouble wrapping my mind around how srcset works, and that’s used all the time for responsive images.) The problems they seek to address have often seemed rather niche to me, compared to the issues that I’m trying to solve 95% of the time.

Of course, now I have to eat a little crow because I found myself in just such a “niche” situation. Which is to say, I’m glad that really smart people have spent time thinking through these situations, rarefied as they might seem, to find and propose potential solutions.

I’m also glad that browser makers are quick to implement them; browser support for these new viewport units is pretty good, with Opera being the only major holdout. (Which means that I’ll probably remove the @supports feature query in the not-too-distant future and use the 100svh as the default CSS.)

Finally, while Safari’s behavior was initially frustrating, I do believe they made the better choice concerning how to handle dynamic toolbars and viewport heights now that I’ve seen how Firefox et al . handle them. I’d rather have part of the design covered up by default (but fixable, if needed, with the right CSS) then see the page rearrange itself as you scroll. The latter behavior is unexpected and thus distracting, two things that can create a poorer user experience — which is something I try to avoid in every aspect of my designs.

  • Dec 20, 2023

New CSS Viewport Units Do Not Solve The Classic Scrollbar Problem

  • 23 min read
  • CSS , Tools , Techniques
  • Share on Twitter ,  LinkedIn

About The Author

Šime Vidas creates news content for web developers on Web Platform News . More about Šime ↬

Email Newsletter

Weekly tips on front-end & UX . Trusted by 200,000+ folks.

Browsers shipped a new set of CSS viewport units in 2022. These units make it easier to size elements in mobile browsers, where the browser’s retractable UI affects the height of the viewport as the user scrolls the page. Unfortunately, the new units do not make it easier to size elements in desktop browsers, where classic scrollbars affect the width and height of the viewport.

The following video shows a desktop browser with classic scrollbars. As we resize the viewport (dashed line) in different ways, the CSS length 100dvw matches the width of the viewport in all situations except when a vertical classic scrollbar is present on the page. In that case, 100dvw is larger than the viewport width. This is the classic scrollbar problem of CSS viewport units. When the page has a vertical classic scrollbar, the length 100dvw is larger than the viewport width. In fact, all viewport units have this problem.

Before discussing the solutions and workarounds to the classic scrollbar problem, we should familiarize ourselves with all the relevant concepts, which include the visual and layout viewport , the two types of zoom , the initial containing block , the original and new viewport units , and the two types of scrollbars .

The Visual And Layout Viewports

The viewport is the rectangular section of the web browser in which the web page is rendered. For example, when a web page loads in Safari on an iPhone SE, the viewport has a width of 375 CSS pixels 1 and a height of 548 CSS pixels. This size is called the “small viewport size” . If the user then scrolls the page, causing the browser’s UI to retract, the height of the viewport increases to 626 CSS pixels, an additional 78 pixels. This size is called the “large viewport size” .

1 The width and height of the viewport are measured in CSS pixels, not device pixels. On most modern displays, especially on mobile devices, one CSS pixel consists of two or more device pixels.

If the user rotates their device and the operating system switches to landscape mode, the size of the viewport changes (it becomes wider than it is tall), but there is again a small and large viewport size.

In desktop browsers, the size of the viewport can change as well (e.g., when the user resizes the browser window, opens the browser’s sidebar, or zooms the page), but there is no separate “small viewport size” and “large viewport size” like in mobile browsers.

So far, I’ve only talked about the “viewport,” but there are, in fact, two different viewports in web browsers: the visual viewport and the layout viewport . When the page initially loads in the browser, the visual viewport and the layout viewport have the exact same size and position. The two viewports diverge in the following two cases:

  • When the user zooms in on a part of the page via a pinch-to-zoom or double-tap gesture, the part of the page that is visible on the screen is the visual viewport. The size of the visual viewport (in CSS pixels) decreases because it shows a smaller part of the page. The size of the layout viewport has not changed.
  • When the browser’s virtual keyboard appears on mobile platforms, the smaller part of the page that is visible on the screen above the keyboard is once again the visual viewport. The height of the visual viewport decreases with the height of the virtual keyboard. The size of the layout viewport has again not changed.

It’s worth noting that as part of shipping the new viewport units in 2022, Chrome stopped resizing the layout viewport and initial containing block (ICB) when the virtual keyboard is shown. This behavior is considered the “the best default” , and it ensures that the new viewport units are consistent across browsers. This change also made the mobile web feel less janky because resizing the ICB is a costly operation. However, the virtual keyboard may still resize the layout viewport in some mobile browsers .

In these two cases, the visual viewport continues to be “the rectangular section of the web browser in which the web page is rendered,” while the layout viewport becomes a larger rectangle that is only partially visible on the screen and that completely encloses the visual viewport. In all other situations, both viewports have the same size and position.

One benefit of the two-viewport system is that when the user pinch-zooms and pans around the page, fixed-positioned elements don’t stick to the screen, which would almost always be a bad experience. That being said, there are valid use cases for positioning an element above the virtual keyboard (e.g., a floating action button). The CSS Working Group is currently discussing how to make this possible in CSS.

CSS viewport units are based on the layout viewport, and they are unaffected by changes to the size of the visual viewport. Therefore, I will focus on the layout viewport in this article. For more information about the visual viewport, see the widely supported Visual Viewport API .

The Two Types Of Zoom

The two types of zoom are defined in the CSSOM View module :

“There are two kinds of zoom: page zoom, which affects the size of the initial viewport, and the visual viewport scale factor, which acts like a magnifying glass and does not affect the initial viewport or actual viewport.”

Page zoom is available in desktop browsers, where it can be found in the browser’s menu under the names “Zoom in” and “Zoom out” or just “Zoom”. When the page is “zoomed in,” the size of the layout viewport shrinks, which causes the page to reflow . If the page uses CSS media queries to adapt to different viewport widths (i.e., responsive web design), those media query breakpoints will be triggered by page zoom.

Scale-factor zoom is available on all platforms. It is most commonly performed with a pinch-to-zoom gesture on the device’s touch screen (e.g., smartphone, tablet) or touchpad (e.g., laptop). As I mentioned in the previous section, the size of the layout viewport does not change when zooming into a part of the page, so the page does not reflow.

The Layout Viewport And The Initial Containing Block

The layout viewport is the “ containing block ” for fixed-positioned elements. In other words, fixed-positioned elements are positioned and sized relative to the layout viewport. For this reason, the layout viewport can be viewed as the “position fixed viewport,” which may even be a better name for it .

Here’s a tip for you : Instead of top: 0 , bottom: 0 , left: 0 , and right: 0 in the snippet above, we can write inset: 0 . The inset property is a shorthand property for the top , bottom , left , and right properties, and it has been supported in all major browsers since April 2021.

The initial containing block (ICB) is a rectangle that is positioned at the top of the web page. The ICB has a static size, which is the “small viewport size.” When a web page initially loads in the browser, the layout viewport and the ICB have the exact same size and position. The two rectangles diverge only when the user scrolls the page: The ICB scrolls out of view, while the layout viewport remains in view and, in the case of mobile browsers, grows to the “large viewport size.”

The ICB is the default containing block for absolutely positioned elements. In other words, absolutely positioned elements are, by default, positioned and sized relative to the ICB. Since the ICB is positioned at the top of the page and scrolls out of view, so do absolutely-positioned elements.

The ICB is also the containing block for the <html> element itself, which is the root element of the web page. Since the ICB and the layout viewport initially have the same size (the “small viewport size”), authors can make the <body> element as tall as the initial viewport by setting height to 100% on both the <html> and <body> element.

Some websites, such as Google Search, use this method to position the page footer at the bottom of the initial viewport . Setting height to 100% is necessary because, by default, the <html> and <body> elements are only as tall as the content on the page.

2 The layout viewport is not fully visible when the user zooms in on the part of the page and when the browser’s virtual keyboard is shown.

The New Viewport Units

The CSS viewport units are specified in the CSS Values and Units Module , which is currently at Level 4. The original six viewport units shipped in browsers a decade ago. The new units shipped in major browsers over the past year , starting with Safari 15.4 in May 2022 and ending with Samsung Internet 21 in May 2023.

Note : The new viewport units may not be correctly implemented in some mobile browsers .

A few clarifications:

  • The “inline size” and “block size” are either the width or the height, depending on the writing direction. For example, in writing systems with a left-to-right writing direction, the inline size is the width ( vi is equivalent to vw ), and the block size is the height ( vb is equivalent to vh ).
  • The ”smaller size” and “larger size” are either the width or the height, depending on which one is larger. For example, if the viewport is rather tall than it is wide (e.g., a smartphone in portrait mode), then the smaller size is the width ( vmin is equivalent to vw ), and the larger size is the height ( vmax is equivalent to vh ).
  • Each viewport unit is equal to one-hundredth of the corresponding viewport size. For example, 1vw is equal to one-hundredth of the viewport width, and 100vw is equal to the entire viewport width.

For each of the six original units, there are three new variants with the prefixes s , l , and d (small, large, and dynamic, respectively). This increases the total number of viewport units from 6 to 24.

  • The s -prefixed units represent the “small viewport size.” This means that 100svh is the height of the initial layout viewport when the browser’s UI is expanded.
  • The l -prefixed units represent the “large viewport size.” This means that 100lvh is the height of the layout viewport after the browser’s UI retracts. The height difference between the large and small viewport sizes is equivalent to the collapsible part of the browser’s UI:

100lvh - 100svh = how much the browser’s UI retracts

  • The old unprefixed units (i.e., vw , vh , and so on) are equivalent to the l -prefixed units in all browsers , which means that they also represent the “large viewport size.” For example, 100vh is equivalent to 100lvh .
  • The d -prefixed units represent the current size of the layout viewport, which can be either the “small viewport size” or the “large viewport size.” This means that 100dvh is the actual height of the layout viewport at any given point in time. This length changes whenever the browser’s UI retracts and expands.

Why Do We Have New CSS Units?

In previous years, the Android version of Chrome would resize the vh unit whenever the browser’s UI retracted and expanded as the user scrolled the page. In other words, vh behaved like dvh . But then, in February 2017, Chrome turned vh into a static length that is based on the “largest possible viewport” . In other words, vh started behaving like lvh . This change was made in part to match Safari’s behavior on iOS, which Apple implemented as a compromise :

“Dynamically updating the [ 100vh ] height was not working. We had a few choices: drop viewport units on iOS, match the document size like before iOS 8, use the small view size, or use the large view size. From the data we had, using the larger view size was the best compromise. Most websites using viewport units were looking great most of the time.”

With this change in place, the same problem that occurred in iOS Safari also started happening in Chrome. Namely, an element with height: 100vh , which is now the “large viewport size,” is taller than the initial viewport, which has the “small viewport size.” That means the bottom part of the element is not visible in the viewport when the web page initially loads. This prompted discussions about creating a solution that would allow authors to size elements based on the small viewport size. One of the suggestions was an environment variable , but the CSS Working Group ultimately decided to introduce a new set of viewport units.

The same height can be achieved by setting height to 100% on the .hero element and all its ancestors, including the <body> and <html> elements, but the svh unit gives authors more flexibility.

I wasn’t able to find any good use cases for the dvh unit. It seems to me that sizing elements with dvh is not a good idea because it would cause constant layout shifts as the user scrolled the page. I had considered dvh for the following cases:

  • For fixed-positioned elements , such as modal dialogs and sidebars, height: 100% behaves the same as height: 100dvh because the containing block for fixed-positioned elements is the layout viewport, which already has a height of 100dvh . In other words, height: 100% works because 100% of 100dvh is 100dvh . This means that the dvh unit is not necessary to make fixed-positioned elements full-height in the dynamic viewport of mobile browsers.
  • For vertical scroll snapping , setting the individual “pages” to height: 100dvh results in a glitchy experience in mobile browsers . That being said, it is entirely possible that mobile browsers could fix this issue and make scroll snapping with height: 100dvh a smooth experience.

There is no concept of a “small viewport size” and a “large viewport size” in desktop browsers. All viewport units, new and old, represent the current size of the layout viewport, which means that all width units are equivalent to each other (i.e., vw = svw = lvw = dvw ), and all height units are equivalent to each other (i.e., vh = svh = lvh = dvh ). For example, if you replaced 100vh with 100svh in your code, nothing would change in desktop browsers.

This behavior isn’t exclusive to desktop platforms. It also occurs on mobile platforms in some cases, such as when a web page is embedded in an <iframe> element and when an installed web app opens in standalone mode.

It is possible for the small and large viewport sizes to be equivalent even during regular web browsing in mobile browsers. I have found two such cases:

  • In Safari on iOS, if the user chooses the “Hide Toolbar” option from the page settings menu, the browser’s UI will retract and stay retracted while the user scrolls the page and navigates to other web pages.
  • In Firefox on Android, if the user disables the “Scroll to hide toolbar” option in Settings → Customize , the browser’s UI will completely stop retracting when the user scrolls web pages.

The Two Types Of Scrollbars

In a web browser, scrollbars can be either classic or overlay. On mobile platforms, scrollbars are exclusively overlay. On desktop platforms, the user can choose the scrollbar type in the operating system’s settings. The classic scrollbar option is usually labeled “Always show scrollbars.” On Windows, scrollbars are classic by default. On macOS, scrollbars are overlay by default (since 2011), but they automatically switch to classic if the user connects a mouse.

The main difference between these two types of scrollbars is that classic scrollbars are placed in a separate ”scrollbar gutter” that consumes space when present, which reduces the size of the layout viewport; meanwhile, overlay scrollbars , as the name suggests, are laid over the web page without affecting the size of the layout viewport.

When a (vertical) classic scrollbar appears on the page in a desktop browser with classic scrollbars, the width of the layout viewport shrinks by the size of the scrollbar gutter, which is usually 15 to 17 CSS pixels. This causes the page to reflow. The size and position of absolutely and fixed-positioned elements may also change. By default, the browser only shows a classic scrollbar when the page overflows, but the page can force the scrollbar (or empty scrollbar track) to be shown and hidden via the CSS overflow property.

To prevent the page from reflowing whenever a vertical classic scrollbar is shown or hidden, authors can set scrollbar-gutter: stable on the <html> element. This declaration tells the browser to always reserve space for the classic scrollbar . The declaration has no effect in browsers with overlay scrollbars. The scrollbar-gutter property is not supported in Safari at the time of writing this article.

A benefit of classic scrollbars is that they make it clear when an element on the page has a scrollable overflow. In comparison, overlay scrollbars are not shown unless the user actually attempts to scroll an element that is a scroll container with overflow. This can be a problem because the user may not even notice that an element contains more content than initially visible . Chrome for Android mitigates this problem by showing the overlay scrollbar until the user scrolls the element at least once.

Even if the Windows operating system switches to overlay scrollbars by default in the future, some users prefer classic scrollbars and will turn them on if possible. Therefore, developers should test in browsers with classic scrollbars and ensure that their websites remain usable.

Issues Related To Classic Scrollbars

When testing your website in a desktop browser with classic scrollbars, the two main issues to look out for are unexpected extra scrollbars caused by small amounts of overflow and empty scrollbar tracks that serve no real purpose. These are usually not major issues, but they make the website appear not quite right, which may confuse or even annoy some visitors.

Issue 1: Setting overflow To scroll Instead Of auto

Whether or not a scroll container has overflow depends on the content length, viewport width, and other factors. In situations when there is no overflow, it’s usually better to hide the scrollbar than to show an empty scrollbar track in browsers with classic scrollbars. Such an automatic scrollbar behavior can be enabled by setting overflow to auto on the scroll container.

When a website is developed on macOS, which uses overlay scrollbars by default, the developer may mistakenly set overflow to scroll instead of auto . Overlay scrollbars behave in the same manner whether overflow is set to auto or scroll . The scrollbar only appears when the user attempts to scroll an element that is a scroll container with overflow. Classic scrollbars behave differently. Notably, if overflow is set to scroll but the element does not overflow, then the browser will show empty scrollbar tracks. To avoid this problem, set overflow to auto instead of scroll .

Auto scrollbars trade the problem of empty scrollbar tracks with the problem of content reflow, but the latter problem can be avoided by setting scrollbar-gutter to stable on the scroll container, as I previously mentioned.

Issue 2: Assuming That The Full Width Of A Media Query Is Available

CSS media queries don’t take into account the fact that classic scrollbars reduce the width of the viewport. In other words, media queries assume scrollbars never exist. For example, if the width of the layout viewport is 983 pixels, and the page has a vertical classic scrollbar that is 17 pixels wide, the media query (min-width: 1000px) is true because it “pretends” that the scrollbar isn’t there. And indeed, if we were to hide the scrollbar, the viewport width would grow to 1,000 pixels (983 + 17 = 1000).

This behavior is by design. Media queries “assume scrollbars never exist” in order to prevent infinite loops . Web developers should not assume that the entire width of a media query is available on the web page. For example, avoid setting the width of the page to 1000px inside a @media (min-width: 1000px) rule. 3

3 Apple does not seem to agree with this reasoning. In Safari, media queries take scrollbars into account, which means that the appearance and disappearance of a classic scrollbar can trigger media query breakpoints, although the browser seems to guard against infinite loops . Nonetheless, Safari’s behavior is considered a bug .

Issue 3: Using 100vw to make an element full width

The length 100vw is equivalent to the width of the layout viewport, except in one case. If the page has a vertical classic scrollbar, 100vw is larger than the viewport width . Due to this anomaly, setting an element to width: 100vw causes the page to overflow horizontally by a small amount in browsers with classic scrollbars.

This is a known issue. The CSS Values and Units module includes the following note:

“Issue: Level 3 assumes scrollbars never existed because it was hard to implement, and only Firefox bothered to do so. This is making authors unhappy. Can we improve here?”

The note is referring to Firefox’s past behavior , where the browser would reduce the size of 100vw on pages that set overflow to scroll on the <html> element. Such pages had a stable scrollbar track, and in that case, 100vw matched the actual viewport width. This behavior was removed from Firefox in 2017, and it was dropped from the CSS specification shortly after. In a recent change of heart, the CSS Working Group decided to revert their earlier decision and reinstate the behavior :

“RESOLVED: If overflow: scroll is set on the root element (not propagated from <body> ), account for the default scrollbar width in the size of vw . Also, take scrollbar-gutter […] into account on the root.”

At the time of writing this article, this change has not yet made it into the CSS specification. It will take some time until all the major browsers ship the new behavior.

Solving The Classic Scrollbar Problem

As the title of this article states, the new viewport units did not solve the classic scrollbar problem. The new svw , dvw , and lvw units are equivalent to the original vw unit in browsers (i.e., 100svw = 100dvw = 100lvw = 100vw ). At first glance, this may seem like a missed opportunity to solve the classic scrollbar problem with the new viewport units. For example, the length 100dvw could have represented the actual viewport width as it dynamically changes in response to the appearance and disappearance of a vertical classic scrollbar. This would have allowed developers to make any element on the page as wide as the viewport more easily.

There are at least two reasons why the new viewport units did not solve the classic scrollbar problem:

  • The new viewport units were introduced to solve the problem of 100vh being taller than the initial viewport in mobile browsers. A small mobile viewport due to the browser’s expanded UI is different from a small desktop viewport due to the presence of classic scrollbars on the page, so the same s -prefixed viewport units cannot represent the small viewport in both cases. If they did, then, for example, using 100svh to solve a layout issue in mobile browsers would have potentially unwanted side effects in desktop browsers and vice-versa.
  • The position of the CSS Working Group is that viewport units should be “resolvable at a computed-value time” and that they should “not depend on layout” . Implementing units that depend on a layout is “relatively hard” for browsers.

The CSS Working Group recently decided to mitigate the classic scrollbar problem by making 100vw smaller in browsers with classic scrollbars when the scrollbar-gutter property is set to stable on the <html> element. The idea is that when the page has a stable scrollbar gutter, the space for the scrollbar is reserved in advance, so the appearance of the scrollbar does not decrease the viewport width. In other words, the viewport has a static width that isn’t affected by the scrollbar. In that case, the length 100vw can safely match the viewport width at all times, whether the scrollbar is present or not. Once this behavior makes it into browsers, developers will be able to use scrollbar-gutter: stable to prevent width: 100vw from horizontally overflowing the page.

Avoiding The Classic Scrollbar Problem

Since at least 2018 , developers have been using CSS custom properties that are dynamically updated via JavaScript to get the actual size of the viewport in CSS. In the following example, the custom property --vw is a dynamic version of the vw unit that is correctly updated when the viewport width changes due to the appearance or disappearance of a vertical classic scrollbar. The CSS variable falls back to 1vw when JavaScript fails to execute or doesn’t load at all.

In the JavaScript code, document.documentElement.clientWidth returns the width of the ICB, which is also the width of the layout viewport. Since the global resize event does not fire when a classic scrollbar changes the viewport width, I’m instead using a resize observer on the <html> element.

With the introduction of CSS container queries to browsers over the past year, another solution that doesn’t require JavaScript became available. By turning the <body> element into an inline-size query container, the length 100cqw — which is the width of <body> in this case — can be used instead of 100vw to get the desired result. Unlike 100vw , 100cqw becomes smaller when a vertical classic scrollbar appears on the page.

Container queries have been supported in all desktop browsers since February 2023. If the page has additional nested query containers, the <body> element’s width ( 100cqw ) can be stored in a registered custom property to make it available inside those query containers. Registered custom properties are not supported in Firefox at the time of writing this article.

If you’d like to learn more about the concepts discussed in this article, I recommend the viewport investigation project , which was a collaboration between browser vendors to “research and improve the state of interoperability of existing viewport measurement features.” The new viewport units were, in fact, one of the focus areas of Interop 2022 .

Smashing Newsletter

Tips on front-end & UX, delivered weekly in your inbox. Just the things you can actually use.

Front-End & UX Workshops, Online

With practical takeaways, live sessions, video recordings and a friendly Q&A.

TypeScript in 50 Lessons

Everything TypeScript, with code walkthroughs and examples. And other printed books.

Search code, repositories, users, issues, pull requests...

Provide feedback.

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly.

To see all available qualifiers, see our documentation .

  • Notifications

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do I deal with iOS Safari's 100vh bug? (It's happening in iOS Chrome as well now!) #14590

@rchrdnsh

rchrdnsh commented Jun 6, 2019 • edited

@gatsbot

DSchau commented Jun 6, 2019

Sorry, something went wrong.

@DSchau

rchrdnsh commented Jun 6, 2019

  • 👍 1 reaction
  • 👍 2 reactions

@rchrdnsh

ptb commented Jun 5, 2020

@Vini98br

Vini98br commented Aug 18, 2020

@a-barbieri

a-barbieri commented Jul 21, 2021 • edited

No branches or pull requests

@ptb

Some Things You Oughta Know When Working with Viewport Units

Avatar of Chris Coyier

David Chanin has a quickie article summarizing a problem with setting an element’s height to 100vh in mobile browsers and then also positioning something on the bottom of that .

Summarized in this graphic:

safari 100vh problem

The trouble is that Chrome isn’t taking the address bar (browser chrome) into account when it’s revealed which cuts off the element short, forcing the bottom of the element past the bottom of the actual viewport.

You’d expect that button in the graphic to be visible (assuming this element is at the top of the page and you haven’t scrolled) since it’s along the bottom edge of a 100vh element. But it’s actually hidden behind the browser chrome in mobile browsers, including iOS Safari or Android Chrome.

I use this a lot:

It’s just a quick way to make sure the body is full height without involving any other elements. I’m usually doing that on pretty low-stakes demo type stuff, but I’m told even that is a little problematic because you might experience jumpiness as browser chrome appears and disappears, or things may not be quite as centered as you’d expect.

You’d think you could do body { height: 100% } , but there’s a gotcha there as well. The body is a child of <html> which is only as tall as the content it contains, just like any other element.

If you need the body to be full height, you have to deal with the HTML element as well:

…which isn’t that big of a deal and has reliable cross-browser consistency.

It’s the positioning things along the bottom edge that is tricky. It is problematic because of position: absolute; within the “full height” (often taller-than-visible) container.

If you are trying to place something like a fixed navigation bar at the bottom of the screen, you’d probably do that with position: fixed; bottom: 0; and that seems to work fine . The browser chrome pushes it up and down as you’d expect ( video ).

Horizontal viewport units are just as weird and problematic due to another bit of browser UI: scrollbars . If a browser window has a visible scrollbar, that scrollbar will usually eat into the visual space although a value of 100vw is calculated as if the scrollbar wasn’t there. In other words, 100vw will cause horizontal scrolling in a way you probably wouldn’t expect.

See the Pen CSS Vars for viewport width minus scrollbar by Shaw ( @shshaw ) on CodePen .

Our last CSS wishlist roundup mentioned better viewport unit handling a number of times, so developers are clearly pretty interested in having better solutions for these things. I’m not sure what that would mean for web compatibility though, because changing the way they work might break all the workarounds we’ve used that are surely still out in the wild.

In the above example i’d like to add calc() minus the height of the address bar :D

height: calc(100vh – 80px) /* 80px or play with it until it fits ;) */

I use the same and on production sites works great!

I recently used something like this:

to address the same issue with iOS Safari (I believe). The second line is property CSS stuff. Ah. And I just see there are is also a -moz-available now.

fill-available has changed to stretch based on recent spec changes. So proper use would be:

witch after using autoprefixer could give us (not sure witch prefixes are correct):

Also there’s a React package that solves this problem https://www.npmjs.com/package/react-div-100vh

Chrome isn’t taking the address bar (browser chrome) into account

Chrome used to take the address bar into account, but this caused another problem: as the address bar slid out of view, all your elements which use vh units auto-resized to match the new viewport size, which caused the page (scroll position) to jump. So at some point in 2016 Chrome implemented the same behaviour as IOS Safari.

What if you set html/body height to 100% but make body display flex with a column direction? it would allow you to have a footer with fixed height and main using up all available space.

safari 100vh problem

Overlapping bottom navigation bar despite 100vh in iOS Safari

»100vh« may not behave as expected for some mobile browsers and the bottom of your content will be partially hidden behind the browser’s bottom bar (i.e. below the »fold«).

First of all, let’s have a look at the issue by checking out the following example. It’s a simple page with 2 absolutely positioned boxes in the top left corner ( .top ) and the right bottom corner ( .bottom ). These boxes are wrapped within an element ( .container ) with a width of 100vw and a height of 100vh . You may have something similar in your project, such as a fullscreen modal/lightbox with a header/footer.

This should span accross the full viewport, right? Well, in the left screenshot below, you can see that in iOS Safari the bottom navigation bar actually overlaps your content, i.e. your content is below the »fold«—although you may have expected that it’s not part of the viewport.

In the right screenshot, you can see how one would expect the layout to be. The container spans between the top address bar and the bottom navigation bar.

This is a well-known issue and unfortunately intentional, as it prevents other problems, as Benjamin Poulain explained in his reply to a WebKit bug ticket regarding this issue.

This is completely intentional. It took quite a bit of work on our part to achieve this effect.
The base problem is this: the visible area changes dynamically as you scroll. If we update the CSS viewport height accordingly, we need to update the layout during the scroll. Not only that looks like shit, but doing that at 60 FPS is practically impossible in most pages (60 FPS is the baseline framerate on iOS).
It is hard to show you the "looks like shit" part, but imagine as you scroll, the contents moves and what you want on screen is continuously shifting.
Dynamically updating the height was not working, we had a few choices: drop viewport units on iOS, match the document size like before iOS 8, use the small view size, use the large view size.
From the data we had, using the larger view size was the best compromise. Most website using viewport units were looking great most of the time.

So, it’s not a bug—and no fix is planned for this.

Luckily, this doesn't have to be the most depresssing answer ever. How do we go on from this? There’s a couple of solutions.

Depending on your use case, it may be enough to simply use 100% instead of 100vh , especially for fixed/sticky elements (as 100% will be relative to the »real« viewport).

However, if your element is nested somewhere in the DOM, this may not work out (as 100% will be relative to the parent elements which are only as tall as the content they contain). And that may have been the motivation why you wanted to use 100vh in the first place.

stretch / -webkit-fill-available

Intrinsic and extrinsic sizing is a new CSS functionality that extends the sizing properties with keywords that represent content-based »intrinsic« sizes and context-based »extrinsic« sizes. This allows CSS to more easily describe boxes that fit their content or fit into a particular layout context.

One of these keywords is stretch which formerly was known as fill , fill-available , and its prefixed spin-offs -moz-available and -webkit-fill-available . We can make use of this functionality and because CSS skips over style declarations it doesn’t understand, we can implement fallbacks for all of these possible implementations.

(Hint: Autoprefixer will compile stretch to -webkit-fill-available and -moz-available automatically.)

JavaScript is always the »last stronghold« for stuff that’s not possible with pure CSS. Using CSS variables, you can pass the value of window.innerHeight into your CSS and update this variable every time the viewport is resized.

In your CSS, you can consume this variable as follows.

If you can’t use CSS variables in your project (e.g. due to browser support concerns), you can also update the height of your affected elements directly from within your script.

Unfortunately, there isn’t a one-size-fits-all solution for this issue. You should try the aforementioned solutions top down and be very conscientious with your cross-browser/cross-device testing.

  • Discuss on Twitter
  • Edit on GitHub

IMAGES

  1. 100vh problem with iOS Safari

    safari 100vh problem

  2. 100vh issue in Safari (Fix for Viewport Height on Mobile devices)

    safari 100vh problem

  3. ios(safari)浏览器,使用100vh遇到的问题和修改方法。

    safari 100vh problem

  4. Corriger le problème de hauteur 100% (100vh) sur mobile

    safari 100vh problem

  5. Dialog: background doesn't fit 100vh when safari's address bar is

    safari 100vh problem

  6. 100vh in Safari on iOS

    safari 100vh problem

VIDEO

  1. Fixing 100vh in Webflow

  2. ಆನೆ ಆನೆ

  3. Не используй 100vh! Не попадись на эту багу ;)

  4. How To Fix Safari Could Not Install A Profile Due To An Unknown Error 2024|iphone|Iped

  5. Rules of conduct at Dubai Safari Park

  6. Safari kabhi mat lena? Safari vs Scorpio konsi better hai👆🏻

COMMENTS

  1. Safari's 100vh Problem

    1. change the height every time the bar hides and shows. or. 2. make the viewport height constant, and have the button bar cover part of the viewport. They opted for a constant height to avoid ...

  2. CSS3 100vh not constant in mobile browser

    This is a well know issue (at least in safari mobile), which is intentional, as it prevents other problems. Benjamin Poulain replied to a webkit bug: ... 100% will adjust it self to the screen size but for some reason 100vh have a problem on adjusting when the screen changes so using the bottom 0 will be affected thus if you use 100vh or 100%.

  3. 100vh problem with iOS Safari

    The problem you have been receiving after adding the height: 100vh to mobile resolutions. It happens due to the calculation method which Safari and Chrome are using. Mobile devices calc browser viewport as ( top bar + document + bottom bar) = 100vh. I had a hard time with 100vh when the page have to have a section filled the whole screen.

  4. Does Safari 15 finally fix viewport height? · Luke Channings

    Mobile Safari has had problems related to 100vh not behaving like web developers expect 1 2 pretty much since the beginning. The main crux of the issue is that Mobile Safari's UI Chrome shrinks when you scroll, and expands again when you activate it. That means 100vh ("100% the height of the viewport") can't be a static number.

  5. 100vh issue in Safari (Fix for Viewport Height on Mobile devices)

    In this video from Webwise, you will learn how to solve the 100vh issue in Safari, where blocks can extend beyond the viewport height. The video will take yo...

  6. A Javascript fix for the 100vh problem on mobile screens

    On some mobile browsers, most commonly Chrome and Safari on iOS, 100vh actually refers to outerHeight. This means the lower toolbar on the browser will not be taken into account, cutting off the last couple of rems of your design. While you can account for the difference using CSS, the view height will subsequently change as soon as the user ...

  7. CSS fix for 100vh in mobile WebKit

    On the right, the -webkit-fill-available property is being used rather than viewport units to fix the problem. And a solution of sorts: body { min-height: 100vh; min-height: -webkit-fill-available; } html { height: -webkit-fill-available; } The above was updated to make sure the html element was being used, as we were told Chrome is updating ...

  8. A workaround for the '100vh' issue in mobile browsers

    In mobile browsers, the real height of the viewport is dynamic, as browser "chrome" (panels) slide away on scrolling. The browser developers faced two choices: either to reflow the page as the pixel value of a vh changes, or ignore the fact that the browser panel covers part of the screen.. The browser panels are supposed to slide away smoothly, and because the layout reflow during scrolling ...

  9. CSS fix for 100vh in mobile WebKit

    Not long ago there was some buzz around how WebKit handles 100vh in CSS, essentially ignoring the bottom edge of the browser viewport. Some have suggested not using 100vh, others have come up with different alternatives to work around the problem. In fact, this issue goes further back a few years when Nicolas Hoizey filed a bug with WebKit on the subject (the short of it: WebKit says this is ...

  10. 100VH Viewport Safari Fix

    The issue, and the fix. The orange div, set to height:100vh, goes under the webkit's browser bottom bar. The black footer, supposedly stuck to the bottom of the viewport, being masked by the browser bottom bar. Using -webkit-fill-available, the viewport height is calculated as expected. Check the code contained in the HTML Embed Component below.

  11. Fixing the iOS Toolbar Overlap Issue with CSS Viewport Units

    That CSS is virtually identical to my original CSS, except I'm now using 100dvh instead of 100vh. (The dvh stands for "dynamic viewport height.") The first time I loaded the page, the problem seemed to be solved: the post header now filled up the space between Safari's toolbars without anything cut off or hidden. But then I scrolled a ...

  12. New CSS Viewport Units Do Not Solve The Classic Scrollbar Problem

    With this change in place, the same problem that occurred in iOS Safari also started happening in Chrome. Namely, an element with height: 100vh, which is now the "large viewport size," is taller than the initial viewport, which has the "small viewport size." That means the bottom part of the element is not visible in the viewport when ...

  13. CSS 100vh is too tall on mobile due to browser UI

    A simple solution worth mentioning... Continue to set the height of your element to 100vh, then just declare that element's max-height in js. $('.top-hero-container').css('max-height', (window.innerHeight + "px")); Now on page load, your element will be no larger than that declared max-height, so will display fine on mobile.

  14. How do I deal with iOS Safari's 100vh bug? (It's happening in iOS

    Here is a gatsby app in safari, chrome and then firefox...notice the difference??? You will notice that Safari and Chrome both crop the layout at the bottom, but Firefox does not. The css of 100vh on the Layout component is respected in Firefox, but not in Safari or Chrome. At first i tried to use this component to solve the issue:

  15. Some Things You Oughta Know When Working with Viewport Units

    David Chanin has a quickie article summarizing a problem with setting an element's height to 100vh in mobile browsers and then also positioning something on the bottom of that.. Summarized in this graphic: The trouble is that Chrome isn't taking the address bar (browser chrome) into account when it's revealed which cuts off the element short, forcing the bottom of the element past the ...

  16. Overlapping bottom navigation bar despite 100vh in iOS Safari

    Well, in the left screenshot below, you can see that in iOS Safari the bottom navigation bar actually overlaps your content, i.e. your content is below the »fold«—although you may have expected that it's not part of the viewport. In the right screenshot, you can see how one would expect the layout to be. The container spans between the ...

  17. How to fix safari 100vh height? : r/webdev

    How to fix safari 100vh height? Question. Hi, I tried to look at multiple solution + the code. min-height: -webkit-fill-available; However, it's not working and it has a weird white space at the bottom like if my 100vh was transformed into 95vh.

  18. How to access the real 100vh on iOS in CSS

    Now you can simply use the CSS: height: var(--real100vh); wherever you want 100vh to actually be the real 100vh on mobile, and this will simply work! It looks better if you also add a transition: height 0.4s ease-in-out; on the same element, so it doesn't snap when you scroll down on mobile. The advantage of using a CSS var to do this is that ...

  19. Easy css trick to fix 100vh Safari iOS bottom bar issue : r/webdev

    I'm not a fan of using 100vh. vh and vw units are designed to size other elements on the page based on current viewport height and width (such as making your font size or line-height dynamic), they do not take into account of scrollbars or Safari bottom bar because it would mean those sizes change every time the Safari bottom bar comes into view or when the page has scrollbars - imagine font ...

  20. Does 100vh not work in safari in windows?

    The front page of a website I have been building to learn some web development works well in all browsers I have tested it on (windows) except safari. I have a html step such that i have sections styled to be 100vw and 100vh. On safari they appear to have a height of 0;

  21. 100vh height when address bar is shown

    I came across this problem a few times and was wondering if there was a solution to this problem. My problem occurs on the Chrome mobile app. There, you can scroll down a bit and the address bar disappears. So far, so good, let's make an example: The container's height is set to 100vh. As you can see, the bottom part gets cut off.