Skip to content
OVEX TECH
Education & E-Learning

Create Dynamic Scroll Animations with New CSS Features

Create Dynamic Scroll Animations with New CSS Features

Master New CSS Scroll Features to Eliminate JavaScript

CSS has introduced powerful new features that allow for complex scroll-based animations and interactive elements without relying on JavaScript. This article will guide you through implementing these features, including scroll-to-top buttons, sticky header effects, interactive tables of contents, and fully functional carousels, all using pure CSS.

Understanding Scroll State and Container Queries

The core of these new CSS capabilities lies in the scroll state, a new container type that enables container queries based on the scroll position within an element, rather than its dimensions. This allows elements to react dynamically to user scrolling.

1. Implementing a Scroll-to-Top Button

Create a button that appears only when the user can scroll and provides a quick way to return to the top of the page.

  1. Define the Scroll Container: Apply the container-type: scroll-state; property to the main scrollable element (e.g., html or a specific wrapper). Assign a name using container-name: page; for easy referencing.
    html {
      container-type: scroll-state;
      container-name: page;
    }
  2. Query Scroll State: Use a container query to check if the page is scrollable upwards. This condition is met when the user has scrolled down.
    @container page (scroll-state: upward) {
      /* Styles to apply when scrollable upwards */
    }

    Expert Note: The scroll-state: upward checks if there is content above the current viewport, meaning the user can scroll up. Other possible values include downward, leftward, rightward, and any-direction.

  3. Style the Button: Initially, hide the scroll-to-top button off-screen using CSS transforms (e.g., transform: translateX(80px);). Inside the container query, reset the transform to none or translateX(0) to make it visible.
    .scroll-top-button {
      transform: translateX(80px);
      transition: transform 0.3s ease-in-out;
    }
    
    @container page (scroll-state: upward) {
      .scroll-top-button {
        transform: none;
      }
    }
  4. Add Smooth Scrolling: Use a simple anchor tag (<a href="#top">Scroll to Top</a>) where the #top ID is applied to the top of your page (e.g., <body id="top">). This provides native smooth scrolling behavior.

2. Styling Sticky Headers Based on Scroll Position

Apply different styles to a sticky header depending on whether it’s actively stuck to the top of the viewport or still scrolling with the page.

  1. Apply Container Type to Sticky Element: Place container-type: scroll-state; and container-name: header; directly on the element that uses position: sticky;.
    .site-header {
      position: sticky;
      top: 0;
      container-type: scroll-state;
      container-name: header;
    }
  2. Query the ‘Stuck’ State: Use a container query to check if the sticky element is currently in its ‘stuck’ state.
    @container header (scroll-state: stuck) {
      /* Styles for when the header is stuck */
      .site-header {
        background-color: white;
        box-shadow: 0 2px 4px rgba(0,0,0,0.1);
      }
    }

    Tip: When an element has position: sticky and is currently adhering to its top, bottom, left, or right offset relative to the viewport, it is considered ‘stuck’.

  3. Define Unstuck Styles: Style the header for when it’s not stuck (i.e., when the container query doesn’t apply). This could involve different background colors or shadows.
    .site-header {
      /* Default styles when not stuck */
      background-color: transparent;
    }

3. Creating an Auto-Updating Table of Contents

Dynamically highlight the current section in a table of contents as the user scrolls through the page.

  1. Enable Scroll Target Group: Add scroll-behavior: smooth; to your main scroll container and apply scroll-target-group: auto; to the element containing your navigation links.
    body {
      scroll-behavior: smooth;
    }
    
    .table-of-contents {
      scroll-target-group: auto;
    }
  2. Link Navigation to Content IDs: Ensure each link in your table of contents has an href pointing to an ID of a corresponding section on the page (e.g., <a href="#section1">Section 1</a>). Each section should have a matching ID (e.g., <div id="section1">...</div>).
  3. Apply ‘Current Target’ Styling: Use the :target-current pseudo-class on your navigation links within the scroll target group to apply styles when that link’s corresponding section is currently in view.
    .table-of-contents a:target-current {
      color: blue;
      font-weight: bold;
    }

    Note: The browser automatically determines which section is currently in view and applies the :target-current state to the corresponding link.

4. Building a CSS-Only Carousel with Animations

Construct a fully functional carousel with navigation buttons, swipe gestures, and entry/exit animations, all without JavaScript.

4.1. Customizing Scroll Snap Points and Indicators

Use scroll-snap-type for smooth snapping and scroll-marker-group and scroll-marker for custom navigation indicators (like dots).

  1. Set Up Scroll Snapping: Apply scroll-snap-type: x mandatory; (or y for vertical) to the carousel container. Ensure child elements are styled to occupy the full width/height of the snap interval.
    .carousel {
      overflow-x: auto;
      scroll-snap-type: x mandatory;
      display: flex;
    }
    
    .carousel-slide {
      flex-shrink: 0;
      width: 100%;
      scroll-snap-align: start;
    }
  2. Define Scroll Marker Group: Add scroll-marker-group to a container that will hold your custom indicators.
    .carousel-indicators {
      scroll-marker-group: custom-markers;
    }
  3. Style Individual Scroll Markers: Use the scroll-marker pseudo-element on the elements you want to represent as indicators (e.g., slides). This automatically creates a marker for each element.
    .carousel-slide::scroll-marker {
      /* Styles for each dot indicator */
      width: 10px;
      height: 10px;
      background-color: grey;
      border-radius: 50%;
      margin: 0 5px;
    }
  4. Highlight Active Marker: Use :target-current on the scroll markers to indicate the active slide, similar to the table of contents.
    .carousel-slide:target-current::scroll-marker {
      background-color: blue;
    }
  5. Add Custom Scroll Buttons: Utilize the ::scroll-button pseudo-element on the carousel container. Specify the direction (e.g., left, right) and provide content.
    .carousel::scroll-button(left) {
      content: '';
      /* Styles for the right button */
    }

    Note: The browser automatically handles disabling these buttons when the end of the scrollable content is reached. The default scroll amount for these buttons is typically one full snap interval.

4.2. Implementing Fade and Scale Animations

Animate carousel slides in and out based on their visibility and snap state.

  1. Track Slide State: Apply container-type: scroll-state; and container-name: slide; to each carousel slide wrapper.
    .carousel-slide {
      /* ... other styles */
      container-type: scroll-state;
      container-name: slide;
    }
  2. Query Snap State: Use container queries to check if the slide is currently snapped in the horizontal (X) direction.
    @container slide (scroll-state: snapped(x)) {
      .carousel-slide {
        opacity: 1;
        transform: scale(1);
      }
    }
  3. Define Default (Off-Screen) Styles: Set default styles for slides that are not currently snapped, such as reduced opacity and scale. These styles apply when the container query condition is false.
    .carousel-slide {
      opacity: 0.5;
      transform: scale(0.75);
      transition: opacity 0.3s ease, transform 0.3s ease;
    }

    Tip: Hiding the scrollbar (e.g., using scrollbar-width: none;) can provide a cleaner carousel appearance.

Conclusion

These new CSS scroll features, including scroll-state, scroll-target-group, :target-current, ::scroll-marker, ::scroll-marker-group, and ::scroll-button, offer powerful ways to create dynamic, interactive, and animated user interfaces without needing JavaScript. Experiment with these properties to enhance your web designs.


Source: NEW CSS Scroll Features are Game Changers (YouTube)

Leave a Reply

Your email address will not be published. Required fields are marked *

Written by

John Digweed

1,380 articles

Life-long learner.