cssnext.jsmobilematerial-uiviewport

The svh/lvh units are not working as expected on Chrome for iPhone


I have a hero section that needs to take the full height of the viewport. When I tried using the new svh/lvh units, the sizing seems to work correctly on desktop and Safari for mobile. However, I'm not able to achieve the expected behaviour on Chrome for mobile (tested on iPhone). The hero section is displayed correctly at first but it resizes (thus moving other elements on the page) when I scroll down and the navigation bar appears at the bottom.

This is the container for the hero section:

<Box
      // ref={observe}
      sx={{
        width: "100vw",
        height: "100vh",
        width: "100svw",
        height: "100svh",
        position: "relative",
      }}
    >

Using height: fill-available; works on Chrome mobile but breaks everywhere else.

I removed the fallbacks 100vh and 100vw to make sure that the mobile browser was using the correct svh units and it was.

Any ideas what is going on?


Solution

  • I agree with you, the svh behavior in Safari is desired, as this should result in the smallest viewport height (svh actually stands for "small viewport height").

    I simply needed to statically render the height of a hero div to the smallest dimensions of the viewport (with the address bar open, etc), and not have it shift in height and ruin the experience when the browser's UI goes away while scrolling.

    I got around this issue in javascript on the initial render of the page, by using window.visualViewport. You'll need to put this in a place where you'd know both the element and visualViewport are available--possibly delayed in setTimeout, but this would depend on how you're rendering the elements.

    if (window.visualViewport) {
       const elements = document.getElementsByClassName("your-small-view-height-div");
       for (let i = 0; i < elements.length; i++) {
          elements[i].setAttribute("style", `min-height: ${window.visualViewport.height}px`);
       }
    } else {
       // add class to body and style with svh as a fallback somewhere with css
       document.body.classList.add("use-svh");
    } 
    

    You're basically caching the value once here, which is what I needed for the mobile view. Now, this probably wouldn't be useful for the desktop representation. But after a few days of trying various approaches, this is what worked for me.