Control the Viewport Resize Behavior on mobile with interactive-widget
by Bramus published on
Viewports units on mobile have been a problem for a long time. Using 100vh
is most likely not exactly what you initially expected it to be. To fix this, the CSS Working Group came up with more units over time for you to use. The dynamic viewport units got introduced, which include svh
and lvh
which represent 1% of the small and large viewport height respectively.
While these units are fairly interoperable at the time of writing – there are still some interop issues, mainly related to webviews – there is one big gripe that a lot of people have with it: when the Virtual Keyboard gets shown, these units do not take the presence of that Virtual Keyboard into account. Depending on what you are building, you might want to have these units get resized when the Virtual Keyboard is shown.
The default viewport resize behavior
When the Virtual Keyboard gets shown on mobile, it gets laid over the content. As a result, the Visual Viewport gets resized but the Layout Viewport - the one that is used to position out position: fixed
elements – remains unchanged.
Because the Layout Viewport does not change, the Viewport Units also don’t change. The only thing that changes is the size of the Visual Viewport, wich represents only the visual part that you see on screen.
Note: Prior to Chrome 108, Chrome on Android used to resize the Layout Viewport when the Virtual Keyboard was shown. To align with MobileSafari, Chrome adjusted its behavior to resize only the Visual Viewport instead. Firefox did the same with the release of Firefox 132.
What sometimes also happens is that browsers shift the Layout Viewport upwards (or the Visual Viewport downwards depending on how you look at it) in order to keep the focused input at the center of the screen.
Intermezzo
If you want to know all the details about Viewports, check out this HTTP 203 episode:
The relevant part for you to know here is that the size of the Initial Containing Block (ICB) is based on the Layout Viewport – more specifically the Small Layout Viewport – and that the Viewport Units are based on the size of the ICB.
If you prefer reading, there are also a bunch of explainers for you to review.
The interactive-widget
keyword in the viewport meta tag
To control the viewport's size and shape there is the viewport meta tag. Most likely you have used the following before:
<meta name="viewport" content="width=device-width, initial-scale=1" />
In the content
there are two properties listed, each with their own value:
width
: Sizes the width of the ICB. The valuedevice-width
indicates that it should be size in relation to the device’s width.initial-scale
: Sets the zoom level when the page is first loaded. It is set to1
, which is also the default (in most cases).
Other keywords that you might have used before include height
, minimum-scale
, maximum-scale
, and user-scalable
.
A fairly new keyword that you can use in the viewport meta tag is interactive-widget
. It allows you to specify how the various viewports should behave when “interative widgets” such as the Virtual Keyboard get shown.
resizes-visual
: Resize only the Visual Viewport but not the Layout Viewport.resizes-content
: Resize both the Visual Viewport and Layout Viewport.overlays-content
: Do not resize any viewport. This is similar to using the Virtual Keyboard API withoverlaysContent
set totrue
.
By setting interactive-widget
to resizes-content
, you can have the Layout Viewport resize. As a result the ICB will also resize, and therefore the Viewport units will also yield different values.
interactive-widget
is supported in Chrome 108+ and Firefox 132+. If you would like to see this become available in WebKit/Safari, please go give https://github.com/WebKit/standards-positions/issues/65 a thumbs up.
Summary
Use the interactive-widget
keyword in the viewport meta tag to control the viewport resize behavior when the Virtual Keyboard gets shown. By default the Visual Viewport resizes. To also have the Layout Viewport resize, set the value of interactive-widget
to resizes-content
.
<meta name="viewport" content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content">
To not resize any of those viewports, set its value to overlays-content
.
The interactive-widget
keyword is supported in Chrome 108+ and Firefox 132+.
Further Reading
- The large, small, and dynamic viewport units
- Viewport vs Virtual Keyboard Resize Behavior
- Prepare for viewport resize behavior changes coming to Chrome on Android
- It’s Viewports all the way down | HTTP 203
About Bramus
Bramus is a web developer from Belgium. He’s part of the Chrome Developer Relations team at Google, focusing on CSS, Web UI, and DevTools. From the moment he discovered view-source
at the age of 14 (way back in 1997), he fell in love with the web and has been tinkering with it ever since.
Blog: bram.us
Bramus on Mastodon: @bramus@front-end.social
Bramus on X: @bramus