📝 CSS-Tricks 232: Scroll Story

View this newsletter on the web.

[Robin]: Over the past week I’ve been working on fun side project that I’m calling a Scroll Story—an elaborate blog post where I rant about a thing. The most exciting part about this little website is that it uses scroll-snap from section to section. Here, a screenshot of one of the sections or “slides”:

The idea is to tell a comic book story with the text/illustration pairing whilst each of these “slides” snap into place. To build this thing, first we need a wrapper for all of the slides which looks something like this:

<div class="slide-container"> <div class="slide">...</div> <div class="slide">...</div> <div class="slide">...</div> </div>

And our .slide-container has the styles to make each slide click into place on scroll:

.slide-container { scroll-snap-type: y mandatory; overflow-y: scroll; height: 100vh; }

And each slide needs to have a height, too:

.slide { height: 100vh; }

100vh tells the browser that we always want the slide to be 100% of the browser’s height—that way each slide takes up the whole screen.

Now, the nifty thing about Firefox is that you can then use the up/down directional keys to jump to each section and it clacks just as you’d expect. And I really wish other browsers implemented this because it’s amazing that you can get the browser to do that with just CSS.

But! The problem here is that mobile browsers disagree about viewport units which is extremely annoying and odd to me. Heck, even Firefox on iOS—which still uses Webkit under the hood—appears to calculate viewport units differently from Safari on iOS.

Thankfully, Louis Hoebregts wrote about this very problem not so long ago:

Viewport units have always been controversial and some of that is because of how mobile browsers have made things more complicated by having their own opinions about how to implement them.

Case in point: should the scrollbar be taken into account for the vw unit? What about a site’s navigation or page controls — should those count in the calculation? Then there are physical attributes of the devices themselves (hello, notch!) that can’t be overlooked.

This was the very problem I was experiencing. To fix the way that browsers calculate vh or vw units correctly we need to use a tiny bit of JavaScript and combine that with CSS custom properties, as Louis writes here:

In JavaScript, you can always get the value of the current viewport by using the global variable window.innerHeight. This value takes the browser’s interface into account and is updated when its visibility changes. The trick is to store the viewport value in a CSS variable and apply that to the element instead of the vh unit.

So from what I understand, whenever we use vh units we need to use this which is sort of annoying and makes my eye twitch. But in terms of work, it’s not too much bother at all. First, we need to write the following JavaScript:

// Get the viewport height and multiple it by 1% to get a value for a vh unit let vh = window.innerHeight * 0.01; // Then we set the value in the --vh custom property to the root of the document document.documentElement.style.setProperty('--vh', `${vh}px`);

So if the browser height is 600px then we’ll now have a value of 6 to work with. We can then pass this variable into our CSS:

.slide { height: 100vh; /* Fallback */ height: calc(var(--vh, 1vh) * 100); }

6 * 100 = 600 which happens to be the height of our browser window.

As I said, it’s a bit annoying to me that browsers don’t all agree with how to calculate vh or vw units but it’s not too difficult to get this working. And to get this nifty effect it’s certainly worth the tiny bit of effort to ensure that browsers aren’t being weird.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s