Happy holiday folks! All the best from us at Digitpaint

Day 8

Viewport inception with the visual viewport API

Have you ever wanted to create a truly fixed positioned element on your website? Or had to deal with appearing on screen keyboards? The Visual Viewport API helps you deal with these situation.

Let's start of with a little demo before we dig deeper. As the different viewports matter most on mobile/touch devices it won't come as a surprise that the demo works best on such a device.

The emoji you can't get rid of

Try zooming, panning, etc. The snowflake will always stay on screen!

Debug info

offsetLeft

offsetTop

pageLeft

pageTop

width

height

scale

What's happening?

Your browser has more than one viewport, it has two. The Layout viewport and Visual viewport. The Layout viewport is the viewport on which a page's elements areplaced. This is what you see when you're all zoomed out. The Visual viewport is the user's visible area of the page. When the user pinch-zooms in on the page, the visual viewport shrinks, but the layout viewport stays the same. UI elements like the on-screen keyboard can also shrink the visual viewport without affecting the layout viewport.

So what does the visual viewport API do?

The API enables you to observe the zoom and scroll events of the visual viewport and it allows you to get data about how it's placed relative to the layout viewport. We acces these values through window.visualViewport. This object exposes a few values to us: width, height, scale, offsetLeft, offsetTop, pageLeft and pageTop. By using these we can place the emoji in such a way that it will always stay visible at the same size, regardless of zoom and scroll.

Observing changes

The window.visualViewport also exposes two events: scroll and resize. These allow us to observe changes to the visual viewport. In the example above we use them to reposition the emoji. But you can do other things with these events, such as overriding the user's actions when on the event. You could, for instance disable the user's zoom-actions completely.

There is a little gotcha when listening to these events. They will only fire if the visual viewport actually changed. This is not so much an issue with the resize event but the scroll event will trip you up. It will not fire when the visual viewport does not move relative to the layout viewport. To fix this we also attach the event listener to the window scroll event to listen to all scroll events.

There are some other issues still which Jake Archibald describes in detail in his article "Introducing visualViewport"

Browser compatibility

Right now it only works in Blink based browsers (Chrome & Opera).

  • Chrome
  • Chrome for Android
  • Opera
  • Opera mobile

Resources

Demo source code

Do you want to see what makes these demos possible? Have a look at their source code:

Back to home