Sometimes it’s useful to adapt the controls available to users based on whether they’ve scrolled through key positions on a page.
Here’s an example: a user scrolls through a Terms & Conditions page. If they click “agree” without having scrolled down until the end, we could prompt them with a “please confirm you’ve read these terms” before continuing. Whereas if they have scrolled down the whole way, that could imply they have read the terms, so we don’t need the additional prompt.
Implementing something like this is relatively easy with the recent CSS scroll-state queries (browser support).
The following is an example of exactly as described above. If you click the “Sign Up” button without having scrolled down until the end, you’ll see an additional prompt reminding that you might not have read the terms yet and if you’d still like to sign up. And if the “Sign Up” is clicked after the text has been scrolled to the end, the sign-up acknowledgement pops up without any confirmation prompt first.
Here’s a live demo:
The Layout
We’ll start with this basic layout:
<article>
<!-- many paragraphs of ToS text goes here -->
<div class="control">
<button>Sign Up</button>
</div>
</article>
Code language: HTML, XML (xml)
article {
overflow: scroll;
container-type: scroll-state;
.control {
position: sticky;
bottom: -20px;
}
}
Code language: CSS (css)
The sign up button’s container (.control
) is a sticky element that sticks to the bottom of its scrollable container (<article>
). This is so the user always has access to the sign up button, in case they prefer to drop reading the terms and sign up right away.
The scrollable container (<article>
) has container-type: scroll-state.
This makes it possible to make changes to its descendants based on their scroll positions.
The Scroll-State Conditional Rule
This is where we code in how the button control’s action adapts to its scroll position inside the article
.
@container not scroll-state(scrollable: bottom) {
button {
appearance: button;
}
}
Code language: CSS (css)
When the container (<article>
in our example) can no longer be scrolled further down, i.e. the container has already been scrolled until its bottom edge, we make a subtle change to the button in CSS that won’t visually modify it. In the example above, the button’s appearance is set to button from its default auto, keeping the button’s look the same.
The Alerts
When the button is clicked, depending on the value of its appearance
property, show the relevant alert.
document.querySelector('button').onclick = (e) => {
if (getComputedStyle(e.target).appearance == "auto"
&& !confirm("Hope you've read the terms. Do you wish to complete the sign up?"))
return;
alert("Sign up complete");
};
Code language: JavaScript (javascript)
If the <article>
has not been scrolled down until the end, the button’s appearance
value remains its default auto (getComputedStyle(e.target).appearance == "auto"
). The click handler executes a confirm()
prompt reminding the user they might not have read the terms fully yet, and if they’d like to continue with the sign up. If the user clicks “OK”, the alert("Sign up complete")
message shows up next.
If the article has been scrolled down to the end, the button will have an appearance
value other than auto
, and so the click handler executes the alert()
only.
Learn about scroll-state queries (here and/or here) to know the different kinds of scrolling scenarios that you can work with. Based on scroll states and positions, you’ll be able to change the appearance, content, or even functionality (as seen in this article) of an element or module.