Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSS: scroll snap module #26735

Merged
merged 10 commits into from
May 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 24 additions & 16 deletions files/en-us/web/css/css_scroll_snap/basic_concepts/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,43 @@ page-type: guide

{{CSSRef}}

The [CSS Scroll Snap](/en-US/docs/Web/CSS/CSS_Scroll_Snap) feature provides a way to snap the scrolling to certain points as the user scrolls through a document. This can be helpful in creating a more app-like experience on mobile or even on the desktop for some types of applications.
The properties in the [CSS scroll snap](/en-US/docs/Web/CSS/CSS_Scroll_Snap) module enable you to define how scrolling snaps to specific points as a user scrolls through a document.

## Key properties for CSS Scroll Snap
The scroll snap feature lets you define the snap positions where a [scroll container](/en-US/docs/Glossary/Scroll_container)'s scrollport may end or "snap to" after a scrolling operation has completed.

The key properties for the scroll snap feature are:
## Key properties for CSS scroll snap

- {{CSSxRef("scroll-snap-type")}}: This property is used on the [scroll container](/en-US/docs/Glossary/Scroll_container) to specify the type, direction, and optionality of scrolling.
- {{CSSxRef("scroll-snap-align")}}: This property is used on child elements to specify the scroll snap position.
Before you can define scroll snapping, you need to enable scrolling on a scroll container. You can do this by ensuring that the scroll container has a defined size and that it has {{cssxref("overflow")}} enabled.

The example below demonstrates scroll snapping along the vertical axis, which is defined by `scroll-snap-type`. Additionally, `scroll-snap-align` is used on all the `<section>` element children dictating the point where the scrolling of each child should stop.
You can then define scroll snapping on the scroll container by using the following two key properties:

- {{cssxref("scroll-snap-type")}}: Using this property, you can define whether or not the scrollable viewport can be snapped to, whether snapping is required or optional, and the axis on which the snapping should occur.
estelle marked this conversation as resolved.
Show resolved Hide resolved
- {{cssxref("scroll-snap-align")}}: This property is set on every child of the scroll container and you can use it to define each child's snap position or lack thereof. (Using the {{cssxref("scroll-snap-stop")}} property, you can ensure that a child is snapped to during scrolling and not passed over. You can also set several {{cssxref("scroll-margin")}} properties on child elements that are snapped to during scrolling to create an outset from the defined box.)
Optional {{cssxref("scroll-padding")}} properties can be set on the scroll container to create a snapping offset.

The example below demonstrates scroll snapping along the vertical axis, which is defined by `scroll-snap-type`. Additionally, `scroll-snap-align` applies on all the children of the `<section>` element, dictating the point where the scrolling of each child should stop.

{{EmbedGHLiveSample("css-examples/scroll-snap/mandatory-y.html", '100%', 700)}}

## Using scroll-snap-type

The {{CSSxRef("scroll-snap-type")}} property needs to know the direction in which scroll snapping happens. This could be `x`, `y`, or the logical mappings `block` or `inline`. You can also use the keyword `both` to have scroll snapping work along both axes.
The {{CSSxRef("scroll-snap-type")}} property needs to know the direction in which scroll snapping happens. This can be `x`, `y`, or the logical mappings `block` or `inline`. You can also use the keyword `both` to have scroll snapping work along both axes.

You can also pass in the keywords `mandatory` or `proximity`. The `mandatory` keyword tells the browser whether the content _has_ to snap to a certain point, no matter where the scroll is. The `proximity` keyword means that the content may snap to the point, but does not have to.

Using `mandatory` creates a very consistent scrolling experience — you know that the browser will always snap to each defined point. This means that you can be confident that something you expect to be at the top of the screen will be when scrolling finishes. However, it can cause problems if the content is larger than you expect — users may find themselves in the frustrating position of never being able to scroll and view a certain point in the content. Therefore, use of `mandatory` should be carefully considered and only used in situations where you know how much content is on the screen at any time.
Using `mandatory` creates a very consistent scrolling experience — you know the browser will always snap to each defined point. This means that you can be confident that something you expect to be at the top of the screen will be there when scrolling finishes. However, it can cause problems if the content is larger than you expect — users may find themselves in the frustrating position of never being able to scroll and view a certain point in the content. Therefore, the use of `mandatory` should be carefully considered and only used in situations where you know how much content is on the screen or scrollable section at any time.

> **Note:** Never use `mandatory` if the content inside one of your child elements will overflow the parent container because the overflowing content will not be visible.
> **Note:** Never use `mandatory` if the content inside one of your child elements will overflow the parent container because user will not be able to scroll the overflowing content into view.

The `proximity` value will only snap to a position when it is close by, the exact distance being left to the browser to decide.
The `proximity` value only snaps child elements to a position when it is close by, with the browsers determining the exact distance.

In the example below, you can change the value between `mandatory` and `proximity` to see the effect this has on the scroll experience.

{{EmbedGHLiveSample("css-examples/scroll-snap/mandatory-proximity.html", '100%', 700)}}

In the above example, both {{cssxref("height", "height: 300px;")}} and {{cssxref("overflow-y", "overflow-y: scroll;")}} are set on the scroll container. If the contents don't overflow their container, there is nothing to scroll.
In the above example, both {{cssxref("height", "height: 300px;")}} and {{cssxref("overflow-y", "overflow-y: scroll;")}} are set on the scroll container.

If the content doesn't overflow its container, there is nothing to scroll.

## Using scroll-snap-align

Expand All @@ -47,30 +54,31 @@ If `scroll-snap-type` is `mandatory` and `scroll-snap-align` on a child is eithe

## Using scroll-padding

If you do not want the content to snap right to the edge of the scroll container, you can use the {{CSSxRef("scroll-padding")}} property or its equivalent longhand values to add some padding.
When using `start` or `end`, if you do not want the content to snap right to the edge of the scroll container, or if you want the snap position to be slightly offset from center when using `center`, use the {{CSSxRef("scroll-padding")}} property or its equivalent longhand values to add some padding.

In the example below, `scroll-padding` is set to `40px`. When the content snaps to the start of the second and third sections, scrolling stops 40 pixels away from the start of the section. Try changing the `scroll-padding` value to see how this changes the distance.

{{EmbedGHLiveSample("css-examples/scroll-snap/scroll-padding.html", '100%', 700)}}

This is potentially useful if you have a [fixed](/en-US/docs/Web/CSS/position#fixed_positioning) element, for example a navigation bar, which could end up overlapping scrolled content. By using `scroll-padding`, you can reserve a space for the fixed element, as shown in the example below, where the `<h1>` element remains on screen as the content scrolls beneath it. Without padding, the heading would overlap some of the content when snapping happens.
This is potentially useful if you have a [fixed](/en-US/docs/Web/CSS/position#fixed_positioning) element such as a navigation bar, which could end up overlapping scrolled content. By using `scroll-padding`, you can reserve space for the fixed element, as shown in the example below, where the `<h1>` element remains on screen as the content scrolls beneath it. Without padding, the heading would overlap some of the content when snapping happens.

{{EmbedGHLiveSample("css-examples/scroll-snap/scroll-padding-sticky.html", '100%', 700)}}

## Using scroll-margin

The {{CSSxRef("scroll-margin")}} property or the longhand scroll margin values can be set on child elements, essentially defining an outset from the defined box. This allows for different amounts of space for different child elements and can be used in conjunction with `scroll-padding` on the parent. Try this in the example below.
The {{CSSxRef("scroll-margin")}} property or the longhand scroll margin values can be set on child elements, defining an outset from the defined box. This allows for different amounts of space for different child elements and can be used in conjunction with `scroll-padding` on the parent. Try this in the example below.

{{EmbedGHLiveSample("css-examples/scroll-snap/scroll-margin.html", '100%', 700)}}

## Using scroll-snap-stop

The {{CSSxRef("scroll-snap-stop")}} property tells the browser whether it should snap to each defined snap point — meaning that in our examples above we would stop at the start of each section or be able to skip past sections.
Using the {{CSSxRef("scroll-snap-stop")}} property, you can specify whether the scrolling must snap to the defined snap points. In the above examples, this would mean that the scrolling would stop at the start of each section or be able to skip past sections.

It could be helpful in ensuring users see each section of the scroller and don't accidentally zip past them. However, it could be problematic in making the scrolling experience slower if the user is looking for a particular section.
With this property definition, you can ensure that users see each section of the scroller and don't accidentally scroll past them. However, this setting can also negatively affect user experience by preventing the user from quickly scrolling to their desired content.

## See also

- [CSS scroll snap module](/en-US/docs/Web/CSS/CSS_Scroll_Snap/)
- [Well-controlled scrolling with CSS Scroll Snap](https://web.dev/css-scroll-snap/)
- [Practical CSS scroll snapping/](https://css-tricks.com/practical-css-scroll-snapping/)
- [CSS Scroll Snap](https://12daysofweb.dev/2022/css-scroll-snap/)
Expand Down
47 changes: 33 additions & 14 deletions files/en-us/web/css/css_scroll_snap/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,23 @@ spec-urls: https://drafts.csswg.org/css-scroll-snap/

{{CSSRef}}

**CSS Scroll Snap** is a module of CSS that contains features to control panning and scrolling behavior with snap positions.
The **CSS scroll snap** module provides properties that let you control the panning and scrolling behavior by defining snap positions. Content can be snapped into position as the user scrolls overflowing content within a {{Glossary("scroll container")}}, providing paging and scroll positioning.

## Key concepts
This module includes the scroll container scroll-padding properties to adjust the optimal viewing region of paging during scroll-into-view operations. It also includes scroll-margin and scroll-alignment, set on the scroll container's children, to adjust the children's visual area when that child is scrolled into view, as well as a property to force scrolling to stop on individual children.

CSS scroll snap enables snapping content as the user scrolls overflowing content within a {{Glossary("scroll container")}}. Scroll snap introduces scroll snap positions, which enforce the scroll positions that a scroll container's {{Glossary("scrollport")}} may end at after a scrolling operation has completed.
## Scroll snap in action

To enable scroll snapping, the scrolling behavior is defined on the scroll container. The container's {{cssxref("scroll-snap-type")}} property defines whether the scrollable viewport can be snapped to, the axis upon which the snapping occurs, and whether snapping is required or optional. To enable scrolling, the container should have a defined size and {{cssxref("overflow")}} must be enabled. There are optional {{cssxref("scroll-padding")}} properties that can be set on the scroll container to create a snapping offset.
To view scroll snapping in the box below, scroll up-and-down and left-and-right through the grid of 45 numbered boxes in the scrollable viewport.

The {{cssxref("scroll-snap-align")}} property is set on every child of the scroll container, defining each child's snap position or lack thereof. The {{cssxref("scroll-snap-stop")}} property enables requiring that child is snapped to during scrolling and not passed over. There are several {{cssxref("scroll-margin")}} properties that can be set on the snapped-to child elements to create an outset from the defined box.
{{EmbedGHLiveSample("css-examples/modules/scroll_snap.html", '100%', 250)}}

With scroll snap, one of the numbered boxes that you scroll to will snap into place. The initial CSS makes the numbered box snap into the center of the viewport. Use the sliders to change the block and inline snap positions.

Using snap properties, you can allow or block the scrolling past an element, a numbered box in this case. Select the "Prevent scrolling past boxes" checkbox to force all scrolling actions to be limited to scrolling to an adjacent box.

To compare scroll snapping to regular scrolling, check the "disable snapping" checkbox and try scrolling again.

To see the code for this example, [view the source on Github](https://github.com/mdn/css-examples/blob/main/modules/scroll_snap.html).

## Reference

Expand Down Expand Up @@ -50,22 +58,33 @@ The {{cssxref("scroll-snap-align")}} property is set on every child of the scrol
- {{cssxref("scroll-margin-block-end")}}
- {{cssxref("scroll-snap-stop")}}

### Glossary terms
## Guides

- {{Glossary("scroll container")}}
- {{Glossary("scrollport")}}
- [Basic concepts of CSS scroll snap](/en-US/docs/Web/CSS/CSS_Scroll_Snap/Basic_concepts)
- : An overview and examples of CSS scroll snap features.

## Guides
## Related concepts

- [Basic concepts of CSS Scroll Snap](/en-US/docs/Web/CSS/CSS_Scroll_Snap/Basic_concepts)
- {{cssxref(":target")}} pseudo-class
- {{cssxref("overflow")}} CSS property
- Element {{domxref("Element.scroll", "scroll()")}} method
- Element {{domxref("Element.scrollBy", "scrollBy()")}} method
- Element {{domxref("Element.scrollIntoView", "scrollIntoView()")}} method
- Element {{domxref("Element.scrollTo", "scrollTo()")}} method
- Document {{domxref("Document.scroll_event", "scroll")}} event
- [`scrollbar`](/en-US/docs/Web/Accessibility/ARIA/Roles/scrollbar_role) ARIA role
- {{Glossary("Scroll container")}} glossary term
estelle marked this conversation as resolved.
Show resolved Hide resolved

## Specifications

{{Specifications}}

## See also

- [Well-controlled scrolling with CSS Scroll Snap](https://web.dev/css-scroll-snap/)
- [Practical CSS scroll snapping/](https://css-tricks.com/practical-css-scroll-snapping/)
- [CSS Scroll Snap](https://12daysofweb.dev/2022/css-scroll-snap/)
- [Scroll snap examples on Codepen](https://codepen.io/collection/KpqBGW)
- [CSS overflow](/en-US/docs/Web/CSS/CSS_Overflow) module
- [CSS scrollbars style](/en-US/docs/Web/CSS/CSS_Scrollbars) module
- [Keyboard-only scrolling areas](https://adrianroselli.com/2022/06/keyboard-only-scrolling-areas.html) on adrianroselli.com (November 28, 2022)
- [Scroll snap examples](https://codepen.io/collection/KpqBGW) on Codepen (September 7, 2022)
- [Well-controlled scrolling with CSS scroll snap](https://web.dev/css-scroll-snap/) on web.dev (August 13, 2021)
- [Practical CSS scroll snapping/](https://css-tricks.com/practical-css-scroll-snapping/) on CSS-Tricks (June 18, 2020)
- [CSS scroll snap](https://12daysofweb.dev/2022/css-scroll-snap/) on 12 Days of Web (December 7, 2019)