Tag: Scroll

Memorize Scroll Position Across Page Loads

Hakim El Hattab tweeted a really nice little UX enhancement for a static site that includes a scrollable sidebar of navigation.

The trick is to throw the scroll position into localStorage right before the page is exited, and when loaded, grab that value and scroll to it. I’ll retype it from the tweet…

let sidebar = document.querySelector(".sidebar");  let top = localStorage.getItem("sidebar-scroll"); if (top !== null) {   sidebar.scrollTop = parseInt(top, 10); }  window.addEventListener("beforeunload", () => {   localStorage.setItem("sidebar-scroll", sidebar.scrollTop); });

What is surprising is that you don’t get a flash-of-wrong-scroll-position. I wonder why? Maybe it has to do with fancy paint holding stuff browsers are doing now? Not sure.

The post Memorize Scroll Position Across Page Loads appeared first on CSS-Tricks.

CSS-Tricks

, , , , ,

An Overview of Scroll Technologies

Scroll-related animations have been used on the web for years. In recent years, they’ve started to become more common, perhaps in part due to devices being higher-performing and thus able to handle more animation. 

There are a number of scroll related technologies out there, so this article’s aim is to provide an overview of them and tools to help choose the one that’s right for you. I’d argue that these technologies can be broken down into two broad categories: ones for specific scroll-related behaviors and ones for more generic scroll-related behaviors.

Technologies for specific scroll-related behaviors

There are a few simple native CSS scroll effects that are supported by modern browsers. In some limited use cases they can be sufficient for your scroll animation needs.

position: sticky;

If all you need is for an element to stay in the same place on scroll for a portion of the page, using position: sticky is a good option. It’s straightforward and built into modern browsers. That said, a polyfill is required for IE support and some mobile browsers. For a solid overview, check out this article by Preethi.

CSS parallax

This isn’t a technology as much as a technique, but it’s pretty handy for simple parallax effects where you want different pieces of the page to move at different speeds on scroll. There’s a good write up of the technique on Alligator.io and a bunch of examples on CodePen, like this Firewatch header. The biggest downside for me is that it’s difficult to understand what values to use to set the perspective and transforms in order to get the parallax effect exactly right.

CSS scroll snap points

Scroll snap points allow the browser to snap to particular scroll positions that you set after a user is done with their normal scrolling. This can be helpful for keeping certain elements in view. However, the API is still in flux so be careful to use the most up to date API and be careful about relying on it in production. This CSS-Tricks article by Max Kohler is a good place to learn about it right now.

Smooth scrolling

Smooth scrolling is supported natively when jumping from section to section within a page using window.scrollTo() in JavaScript or even the scroll-behavior property in CSS. Generic smooth scrolling that smooths out mouse wheel actions is not supported natively in all browsers at this time. There are various JavaScript libraries that attempt to add smooth scroll support for the mousewheel action, but I’ve yet to find one that is bug-free and plays nicely with all other scroll technologies. Plus, smooth scrolling isn’t always good in the first place.

Technologies for generic scroll behaviors

Currently, there is no way to create or fire generic animations based on the scroll position using just CSS (though there is a proposal that could support some form of generic scroll based animations in CSS in the distant future) or to scrub through part of an animation. As such, if you want to animate elements on scroll, you’ll need to use at least some JavaScript to create the effect you want. There are two broad methods of using JavaScript to fire animations on scroll: using intersection observers and using the scroll event.

IntersectionObserver

Intersection observers are great if all you need for your animation is information related to whether or not and how much of an element is visible in the viewport. This makes them a good option for reveal animations. Even then, some things are difficult (though not impossible) using intersection observers, such as firing different animations depending on the direction an element enters the viewport. Intersection observers also aren’t very helpful if you want to do any scroll animations when an element is in between and not overlapping with the start and end points. 

Using the scroll event

Using the scroll event will give you the most freedom in controlling animations on scroll. It allows you to affect an element on scroll no matter where it is in terms of the viewport and set up starting and ending points exactly as you need for your project. 

With that being said, it can also be intense on performance if it isn’t throttled correctly and doesn’t have a convenient API to create particular behaviors. This is why it’s oftentimes helpful to use a good scrolling library that can handle the throttling for you and give you a more handy API to work with. Some can even handle a lot of the resizing issues for you!

Tools to create generic scroll behaviors

There are a few holistic scrolling libraries that attempt to give you full control over animations on scroll without you having to perform all of the calculations yourself. 

ScrollMagic

ScrollMagic provides a relatively simple API to create various effects on scroll and can be hooked into different animation libraries like GSAP and Velocity.js. However, it has become less maintained over the past few years, which lead to the creation of ScrollScene.

ScrollScene

ScrollScene is essentially a wrapper to try and make ScrollMagic and/or the intersection observer more usable. It uses a custom, more maintained version of ScrollMagic and adds additional features like video playback, scene init breakpoints, and scene duration breakpoints. It also makes use of GSAP

ScrollTrigger

ScrollTrigger is an official GreenSock plugin for GSAP. It a long list of features as the most easy to use API of any scroll library (at least to me). Using it, you can have complete control to define where your scroll animations start and end, animate anything (WebGL, canvas, SVG, DOM, whatever) on scroll, pin elements in place while the animation is running, and more. Plus it has the support of GreenSock and the GreenSock forums

Notable mention: Locomotive Scroll

While it doesn’t attempt to be as comprehensive of a scrolling library as the other libraries mentioned above, Locomotive Scroll is focused on providing custom smooth scrolling. You can also animate certain properties of DOM objects by adding data attributes or hook into the onscroll event to animate other types of objects. 

In summary

For some particular scroll animation effects, like sticky positioning and parallax, CSS technologies may be sufficient, at least when using a polyfill for browsers that don’t support those properties.

I generally recommend using GSAP’s ScrollTrigger because it can do everything that CSS properties can do, plus much more. ScrollTrigger will handle the browser support and calculations so that you can focus on animating!

Here’s a table covering which tools you can use to create particular effects:

position: sticky CSS parallax CSS scroll snap points Smooth Scrolling Intersection observers ScrollMagic ScrollScene Locomotive Scroll ScrollTrigger
Pinning ⚪️
Parallax effects
Scrubbing through animation with easing ⚪️ ⚪️ ⚪️ ⚪️ ⚪️
Snaps scroll position ⚪️ ⚪️ ⚪️ ⚪️
Dynamic Batching / Staggering
Supports horizontal scroll effects

Here’s a table comparing various other aspects of scroll technology:

position: sticky CSS parallax CSS scroll snap points Smooth scrolling Intersection observers ScrollMagic ScrollScene Locomotive Scroll ScrollTrigger
Usable in production (good browser support) ⚪️ ⚪️ ⚪️ ⚪️ ⚪️
Complete freedom in animation ⚪️
Maintained n/a n/a n/a n/a n/a
Works with DOM, Canvas, WebGl, SVG ⚪️
Works easily with resizing ⚪️
Restricts animation to relevant section ⚪️ ⚪️
Directionally aware ⚪️ ⚪️
Native technology
✅ = Yes
⚪️ = Partial support
❌ = No

The post An Overview of Scroll Technologies appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

How I Put the Scroll Percentage in the Browser Title Bar

Some nice trickery from Knut Melvær.

Ultimately the trick boils down to figuring out how far you’ve scrolled on the page and changing the title to show it, like:

document.title = `$  {percent}% $  {post.title}`

Knut’s trick assumes React and installing an additional library. I’m sure that library does all kinds of smart stuff, but if you’re looking to do this “vanilla” style, I’d probably rock something like this…

const percentLabel = document.querySelector("#percent"); const originalTitle = document.title;  window.addEventListener("scroll", () => {   let scrollTop = window.scrollY;   let docHeight = document.body.offsetHeight;   let winHeight = window.innerHeight;   let scrollPercent = scrollTop / (docHeight - winHeight);   let scrollPercentRounded = Math.round(scrollPercent * 100);   percentLabel.innerHTML = scrollPercentRounded;   document.title = `($  {scrollPercentRounded}%) $  {originalTitle}`; });

Here’s a project, and here’s the deployed site so you can see it in action.

Direct Link to ArticlePermalink

The post How I Put the Scroll Percentage in the Browser Title Bar appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]

How to use CSS Scroll Snap

Nada Rifki demonstrates the scroll-snap-type and scroll-snap-alignCSS properties. I like that the demo shows that the items in the scrolling container can be different sizes. It is the edges of those children that matter, not some fixed snapping distance.

I like Max Kohler’s coverage as well, which includes a demo where the snapping can happen in multiple directions.

This is one of those things where, if you didn’t know about it, it’s worth a solid golf clap for CSS.

Direct Link to ArticlePermalink

The post How to use CSS Scroll Snap appeared first on CSS-Tricks.

CSS-Tricks

,
[Top]

Indicating Scroll Position on a Page With CSS

Scrolling is something we all know and do on the web to the extent that it’s an expectation or perhaps even a habit, like brushing our teeth. That’s probably why we don’t put too much thought into designing the scrolling experience — it’s a well-known basic function. In fact, the popular “there is no fold” saying comes from the idea that people know how to scroll and there is no arbitrary line that people don’t go under.

Scroll-based features tend to involve some bespoke concoction of CSS and JavaScript. That’s because there simply aren’t that many native features available to do it. But what if we could accomplish something that only uses CSS? 

Take this ingenious horizontal scrollbar with CSS, for instance. I want to do something similar, but to indicate scrolled sections rather than capture continuous scrolling. In other words, rather than increasing the length of the indicator during scroll, I only want to increase the length when a certain section of the page has been reached.

Like this:

Here’s my plan: Each section carries an indicator that’s undetectable until it reaches the top of the screen. That’s where it becomes visible by changing color and sticks to the top of the viewport.

The exact opposite should happen in reverse: the indicator will follow along when scrolling back up the screen, camouflaging itself back to being undetected to the naked eye.

There are two key parts to this. The first is for the indicator to change color when it’s near the top of the screen. The second is for the indicator to stay put at the top of the screen and come down only when its section is scrolled down to.

The second one is easy to do: we use position: sticky; on our elements. When a page is scrolled, a sticky element sticks to a given position on the screen within its parent container.

That brings us to changing colors. Since the background of an HTML document is white by default, I’m keeping white as the base color for the demo. This means the indicator should look white when it’s over the base color and turn to some other color when it’s over the indicator bar at the top of the screen.

The dashed indicator is currently invisible, but becomes visible when it sticks to the top and blends with the background color of the indicator container.

This is where CSS blend modes come into play. They give us so many options to create a variety of color amalgams. I’m going to go with the overlay value. This one is quite dynamic in nature. I won’t explain the blend in depth (because the CSS-Tricks Alamanac already does a good job of that) but taking this demo into account, I’ll say this: when the background color is white the resulting foreground color is white; and when the background is some other color, the resulting color is darker or lighter, depending on the color it’s mixed with.

The indicator stops in the demo are black. But, because of the blend, we see them as white because they are on a white background. And when they are over the indicator container element, which is a lovely shade of violet, we see a dark violet indicator stop, because we’re mixing the indicator stop’s black with the indicator container’s violet.

Starting with the HTML:

<div id="passageWrapper">   <strong>Sections Scrolled ↴</strong>   <!-- Indicator container -->   <div id="passage"></div> </div> 
 <!-- Indicator stop --> <div class=passageStops></div> 
 <!-- First Section --> <div class="sections">   <!-- Content --> </div> 
 <!-- Another indicator stop --> <div class="passageStops"></div> 
 <!-- Second Section --> <div class="sections">   <!-- Content --> </div> 
 <!-- Another indicator stop --> <div class="passageStops"></div> 
 <!-- Third Section --> <div class="sections">   <!-- Content --> </div>

Pretty straightforward, right? There’s a sticky container at the very top that holds the indicators when they reach the top.  From there, we have three sections of content, each one topped with an indicator that will stick to the top with the indicator and blend with it.

Here’s the CSS:

.passageStops {   background-color: black; /* Each indicator stop is black */   mix-blend-mode: overlay; /* This makes it appear white on a white background */   width: 33.3%; /* Three sections total, so each section is one-third */   top: calc(1em + 3px); } 
 #passage,  .passageStops{   height: 10px; } 
 #passageWrapper, .passageStops {   position: sticky; /* The container and stops should stick to the top */   z-index: 1; /* Make sure the indicator and stops stay at the forefront */ } 
 #passage {   background: violet; /* Will blend with black to make a darker violet indicator */   margin: 0 0 20px 0; } 
 #passageWrapper{   background-color: white; /* Make sure we're working with white to hide indicator stops */   height: 40px;   top: 0px; } 
 /* Each stop will shift one-third the width of the indicator container to cover the whole thing when the last section is reached. */ .passageStops:nth-child(4){ margin-left: 33.3%; } .passageStops:nth-child(6){ margin-left: 66.6%; } 
 /* More styling, blah blah. */

The indicators (.passageStops) are black. But the overlay blend mode makes them appear white when it blends with the white background under it. Since there are three sections, each indicator is of one-third width.

The indicators have position: sticky; with a top distance value. This means the indicators will stick once they reach the calculated position from the top of the screen. When that happens, the black indicators that appeared white blend with the violet indicator container, which makes them appear to be a dark violet, representing the new scroll position on the page.

The reverse is also true. When an indicator loses its sticky position, it will move from the violet background of the indicator bar to the white background of the page, hiding it once again… like it was never there!

Here’s the demo again:

That’s it. You can perhaps further experiment with this by having a non-white background with another blend mode, or a gradient for the indicator bar or stops.

The post Indicating Scroll Position on a Page With CSS appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]

Animate Text on Scroll

We covered the idea of animating curved text not long ago when a fun New York Times article came out. All I did was peek into how they did it and extract the relevant parts to a more isolated demo.

That demo is here:

See the Pen
Selfie Crawl
by Chris Coyier (@chriscoyier)
on CodePen.

@keyframers covered it much nicer than I did and made this video. (Seriously, it’s so clear and concise — it’s a great watch.)

I particularly like how quick’n’easy creating, exporting, optimizing, and integrating the actual SVG codes in their demonstration.

Their final demo:

See the Pen
SVG textPath Animation on Scroll Tutorial | Keyssentials: Web Animation Tips by @keyframers
by @keyframers (@keyframers)
on CodePen.

The post Animate Text on Scroll appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

Weekly Platform News: CSS Scroll Snap, Opera GX, PWA Install Icon

Šime posts regular content for web developers on webplatform.news.

In this week’s roundup, Chrome is adding an install option for Progressive Web Apps, Opera GX comes to Windows, the ECMAScript proposals get an update, and CSS Scroll Snap is coming to a Firefox browser near you.

An install icon is coming to Chrome on desktop

Pete LePage: The next version of Chrome will automatically show an install icon in the address bar on desktop if the site meets Chrome’s PWA “installability” criteria. You can listen for the appinstalled event to detect if the user installed your PWA.

Opera GX is available on Windows

Maciej Kocemba: The preview version of Opera GX for Windows is now available. This is a special version of Opera that lets users limit how much CPU and RAM is available to the browser.

Updated ECMAScript proposals

Azu The JavaScript optional chaining operator (obj?.prop) and null-ish coalescing operator (x ?? y) proposals have been moved to Stage 2 of the TC39 process. (See Web Platform News issue 902 for more information about the TC39 process.)

// BEFORE let text = response.settings && response.settings.headerText; if (text == null) text = "Hello, world!";  // AFTER let text = response.settings?.headerText ?? "Hello, world!";

CSS Scroll Snap is coming to Firefox

Šime Vidas: CSS Scroll Snap is supported in Chrome, Safari, and the next version of Firefox. Scroll snapping works well on touch screen devices but there are some usability issues on desktop platforms.

The post Weekly Platform News: CSS Scroll Snap, Opera GX, PWA Install Icon appeared first on CSS-Tricks.

CSS-Tricks

, , , , , , ,
[Top]

Styling Based on Scroll Position

Rik Schennink documents a system for being able to write CSS selectors that style a page when it has scrolled to a certain point. If you’re like me, you’re already on the lookout for document.addEventListener('scroll' ... and being terrified about performance. Rik gets to that right away by both debouncing the function as well as marking the event as passive.

The end result is a data-scroll attribute on the <html> element that can be used in the CSS. Meaning if you’re scrolled to 640px down the page, you have <html data-scroll="640"> and could write a selector like:

html:not([data-scroll='0']) {   body {     padding-top: 3em;   }   header {     position: fixed;   } }

See the Pen
Writing Dumb JS 🧟‍♂️ and Smart CSS 👩‍🔬
by Rik Schennink (@rikschennink)
on CodePen.

Unfortunately, we don’t have greater than (>) less than (<) selectors in CSS for things like numbered attributes, so the CSS styling potential is fairly limited here. You might ultimately need to update the JavaScript function such that it applies other classes or data attributes based on your math. But you’ll already be set up for good performance here.

“Apply styles when the user has scrolled away from the top” is a legit use case. It makes me think of a once function (like we have in jQuery) where any scroll event would only be triggered once and then not again. They scrolled! So, by definition, they aren’t at the top anymore! But that doesn’t deal with when they scroll back to the top.

I find it generally more useful to use IntersectionObserver for styling things based on scroll position. With it, you can do things like, “has this element been scrolled into view or beyond,” which is generically useful and can be used for scrolled-away-from-top stuff too.

Here’s an example that adds or removes a class if a user has scrolled past a hidden pixel positioned at 500px down the page.

See the Pen
Fixed Header with IntersectionObserver
by Chris Coyier (@chriscoyier)
on CodePen.

That’s performant as well, avoiding any scroll event handlers at all.

And speaking of IntersectionObserver, check out “Trust is Good, Observation is Better—Intersection Observer v2”.

The post Styling Based on Scroll Position appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]