Chalarangelo/30-seconds-of-code

View on GitHub
content/snippets/css/s/scroll-snap.md

Summary

Maintainability
Test Coverage
---
title: Horizontal or vertical scroll snap in CSS
shortTitle: Horizontal or vertical scroll snap
type: story
language: css
tags: [interactivity]
cover: purple-sunset-waves
excerpt: Create a horizontally or vertically scrollable container that will snap on elements when scrolling.
listed: true
dateModified: 2024-08-25
---

Scroll snapping in CSS has been around for a while and it's a great way to create modern interactive experiences. It consists of a handful of properties that allow you to create a scrollable container that will snap on elements when scrolling, either horizontally or vertically.

## Scrollable containers that snap

To create a scrollable container that snaps on elements when scrolling, you can use the `scroll-snap-type` property to control the **snap axis**. This property can be set to `x` for horizontal scrolling or `y` for vertical scrolling. You can also set it to `both` to enable both horizontal and vertical scrolling.

> [!TIP]
>
> If you're working with the new [**Logical Properties**](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties) you can use `block` for vertical and `inline` for horizontal. In this article, however, we'll focus on the more traditional `x` and `y` values.

```css
/* Horizontal scroll snap */
.scroll-snap {
  scroll-snap-type: x mandatory;
}

/* Vertical scroll snap */
.scroll-snap {
  scroll-snap-type: y mandatory;
}
```

Apart from the snap axis, you can also specify the **snap strictness** with `scroll-snap-type`. The `mandatory` value will snap the container to the nearest snap point, while `proximity` will snap the container to the nearest snap point if it's close enough (default).

### Snap alignment

You can also control the **alignment of the snap points** using the `scroll-snap-align` property. This property can be set to `start`, `end`, `center`, or `none`.

```css
/* Snap to the start of the element */
.scroll-snap > .element {
  scroll-snap-align: start;
}

/* Snap to the center of the element */
.scroll-snap > .element {
  scroll-snap-align: center;
}

/* Snap to the end of the element */
.scroll-snap > .element {
  scroll-snap-align: end;
}
```

### Scrolling over the edge

To prevent the default browser **behavior when reaching the end of the scrollable container**, you can use the `overscroll-behavior` property. This property can be set to `auto`, `contain`, or `none`.

The `contain` value is usually preferred as it allows the scroll snap to work as expected when scrolling over the edge of the container.

> [!TIP]
>
> Depending on your use case, you can use `overscroll-behavior-x` and `overscroll-behavior-y` to control the behavior on the horizontal and vertical axes respectively, or even `overscroll-behavior-inline` and `overscroll-behavior-block` if you're using Logical Properties.

```css
/* Horizontal scroll snap */
.scroll-snap {
  scroll-snap-type: x mandatory;
  overscroll-behavior-x: contain;
}

/* Vertical scroll snap */
.scroll-snap {
  scroll-snap-type: y mandatory;
  overscroll-behavior-y: contain;
}
```

## Horizontal scroll snap

Putting everything together, we can create a horizontally scrollable container that will snap on elements when scrolling. At its core the HTML and CSS is quite simple. All you need to do is set the `scroll-snap-type` to `x mandatory` and the `overscroll-behavior-x` to `contain`. You can decide on the value of your `scroll-snap-align` based on your design.

https://codepen.io/chalarangelo/pen/VwoYQYj

```html
<div class="horizontal-snap">
  <!-- Add your content here, use .element for snap points -->
</div>
```

```css
.horizontal-snap {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
}

.horizontal-snap > .element {
  scroll-snap-align: center; /* or start, end */
}
```

## Vertical scroll snap

Similarly, a vertically scrollable container that snaps on elements when scrolling can be created by setting the `scroll-snap-type` to `y mandatory` and the `overscroll-behavior-y` to `contain`. You can again decide the value of `scroll-snap-align` based on your design.

https://codepen.io/chalarangelo/pen/mdNyXVm

```html
<div class="vertical-snap">
  <!-- Add your content here, use .element for snap points -->
</div>
```

```css
.vertical-snap {
  overflow-y: auto;
  overscroll-behavior-y: contain;
  scroll-snap-type: y mandatory;
}

.vertical-snap > .element {
  scroll-snap-align: center; /* or start, end */
}
```