1 | [![CircleCI Status](https://img.shields.io/circleci/project/github/stipsan/compute-scroll-into-view.svg?style=flat-square)](https://circleci.com/gh/stipsan/compute-scroll-into-view)
|
2 | [![npm stat](https://img.shields.io/npm/dm/compute-scroll-into-view.svg?style=flat-square)](https://npm-stat.com/charts.html?package=compute-scroll-into-view)
|
3 | [![npm version](https://img.shields.io/npm/v/compute-scroll-into-view.svg?style=flat-square)](https://www.npmjs.com/package/compute-scroll-into-view)
|
4 | [![gzip size][gzip-badge]][unpkg-dist]
|
5 | [![size][size-badge]][unpkg-dist]
|
6 | [![module formats: umd, cjs, and es][module-formats-badge]][unpkg-dist]
|
7 | [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=flat-square)](https://github.com/semantic-release/semantic-release)
|
8 |
|
9 | ![compute-scroll-into-view](https://user-images.githubusercontent.com/81981/43024153-a2cc212c-8c6d-11e8-913b-b4d62efcf105.png)
|
10 |
|
11 | Lower level API that is used by the [ponyfill](https://ponyfill.com) [scroll-into-view-if-needed](https://github.com/stipsan/scroll-into-view-if-needed) to compute where (if needed) elements should scroll based on [options defined in the spec](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView) and the [`scrollMode: "if-needed"` draft spec proposal](https://github.com/w3c/csswg-drafts/pull/1805).
|
12 | Use this if you want the smallest possible bundlesize and is ok with implementing the actual scrolling yourself.
|
13 |
|
14 | Scrolling SVG elements are supported, as well as Shadow DOM elements. The [VisualViewport](https://developer.mozilla.org/en-US/docs/Web/API/VisualViewport) API is also supported, ensuring scrolling works properly on modern devices. Quirksmode is also supported as long as you polyfill [`document.scrollingElement`](https://developer.mozilla.org/en-US/docs/Web/API/document/scrollingElement).
|
15 |
|
16 | ## Install
|
17 |
|
18 | ```bash
|
19 | yarn add compute-scroll-into-view
|
20 | ```
|
21 |
|
22 | The UMD build is also available on [unpkg](https://unpkg.com/compute-scroll-into-view/umd/):
|
23 |
|
24 | ```html
|
25 | <script src="https://unpkg.com/compute-scroll-into-view/umd/compute-scroll-into-view.min.js"></script>
|
26 | ```
|
27 |
|
28 | You can find the library on `window.computeScrollIntoView`.
|
29 |
|
30 | ## Usage
|
31 |
|
32 | ```js
|
33 | // es6 import
|
34 | import computeScrollIntoView from 'compute-scroll-into-view'
|
35 | // or es5
|
36 | const computeScrollIntoView = require('compute-scroll-into-view')
|
37 |
|
38 | const node = document.getElementById('hero')
|
39 |
|
40 | // same behavior as Element.scrollIntoView({block: "nearest", inline: "nearest"})
|
41 | // see: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
|
42 | const actions = computeScrollIntoView(node, {
|
43 | scrollMode: 'if-needed',
|
44 | block: 'nearest',
|
45 | inline: 'nearest',
|
46 | })
|
47 |
|
48 | // same behavior as Element.scrollIntoViewIfNeeded(true)
|
49 | // see: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoViewIfNeeded
|
50 | const actions = computeScrollIntoView(node, {
|
51 | scrollMode: 'if-needed',
|
52 | block: 'center',
|
53 | inline: 'center',
|
54 | })
|
55 |
|
56 | // Then perform the scrolling, use scroll-into-view-if-needed if you don't want to implement this part
|
57 | actions.forEach(({ el, top, left }) => {
|
58 | el.scrollTop = top
|
59 | el.scrollLeft = left
|
60 | })
|
61 | ```
|
62 |
|
63 | ## API
|
64 |
|
65 | ### computeScrollIntoView(target, options)
|
66 |
|
67 | ### options
|
68 |
|
69 | Type: `Object`
|
70 |
|
71 | #### [block](https://scroll-into-view-if-needed.netlify.com/#scroll-alignment)
|
72 |
|
73 | Type: `'start' | 'center' | 'end' | 'nearest'`<br> Default: `'center'`
|
74 |
|
75 | Control the logical scroll position on the y-axis. The spec states that the `block` direction is related to the [writing-mode](https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode), but this is not implemented yet in this library.
|
76 | This means that `block: 'start'` aligns to the top edge and `block: 'end'` to the bottom.
|
77 |
|
78 | #### [inline](https://scroll-into-view-if-needed.netlify.com/#scroll-alignment)
|
79 |
|
80 | Type: `'start' | 'center' | 'end' | 'nearest'`<br> Default: `'nearest'`
|
81 |
|
82 | Like `block` this is affected by the [writing-mode](https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode). In left-to-right pages `inline: 'start'` will align to the left edge. In right-to-left it should be flipped. This will be supported in a future release.
|
83 |
|
84 | #### [scrollMode](https://scroll-into-view-if-needed.netlify.com/#scrolling-if-needed)
|
85 |
|
86 | Type: `'always' | 'if-needed'`<br> Default: `'always'`
|
87 |
|
88 | This is a proposed addition to the spec that you can track here: https://github.com/w3c/csswg-drafts/pull/1805
|
89 |
|
90 | This library will be updated to reflect any changes to the spec and will provide a migration path.
|
91 | To be backwards compatible with `Element.scrollIntoViewIfNeeded` if something is not 100% visible it will count as "needs scrolling". If you need a different visibility ratio your best option would be to implement an [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API).
|
92 |
|
93 | #### [boundary](https://scroll-into-view-if-needed.netlify.com/#limit-propagation)
|
94 |
|
95 | Type: `Element | Function`
|
96 |
|
97 | By default there is no boundary. All the parent elements of your target is checked until it reaches the viewport ([`document.scrollingElement`](https://developer.mozilla.org/en-US/docs/Web/API/document/scrollingElement)) when calculating layout and what to scroll.
|
98 | By passing a boundary you can short-circuit this loop depending on your needs:
|
99 |
|
100 | - Prevent the browser window from scrolling.
|
101 | - Scroll elements into view in a list, without scrolling container elements.
|
102 |
|
103 | You can also pass a function to do more dynamic checks to override the scroll scoping:
|
104 |
|
105 | ```js
|
106 | const actions = computeScrollIntoView(target, {
|
107 | boundary: parent => {
|
108 | // By default `overflow: hidden` elements are allowed, only `overflow: visible | clip` is skipped as
|
109 | // this is required by the CSSOM spec
|
110 | if (getComputedStyle(parent)['overflow'] === 'hidden') {
|
111 | return false
|
112 | }
|
113 |
|
114 | return true
|
115 | },
|
116 | })
|
117 | ```
|
118 |
|
119 | #### skipOverflowHiddenElements
|
120 |
|
121 | Type: `Boolean`<br> Default: `false`
|
122 |
|
123 | By default the [spec](https://drafts.csswg.org/cssom-view/#scrolling-box) states that `overflow: hidden` elements should be scrollable because it has [been used to allow programatic scrolling](https://drafts.csswg.org/css-overflow-3/#valdef-overflow-hidden). This behavior can sometimes lead to [scrolling issues](https://github.com/stipsan/scroll-into-view-if-needed/pull/225#issue-186419520) when you have a node that is a child of an `overflow: hidden` node.
|
124 |
|
125 | This package follows the convention [adopted by Firefox](https://hg.mozilla.org/integration/fx-team/rev/c48c3ec05012#l7.18) of setting a boolean option to _not_ scroll all nodes with `overflow: hidden` set.
|
126 |
|
127 | # TypeScript support
|
128 |
|
129 | This library ships with library definitions for TypeScript.
|
130 |
|
131 | [gzip-badge]: http://img.badgesize.io/https://unpkg.com/compute-scroll-into-view/umd/compute-scroll-into-view.min.js?compression=gzip&label=gzip%20size&style=flat-square
|
132 | [size-badge]: http://img.badgesize.io/https://unpkg.com/compute-scroll-into-view/umd/compute-scroll-into-view.min.js?label=size&style=flat-square
|
133 | [unpkg-dist]: https://unpkg.com/compute-scroll-into-view/umd/
|
134 | [module-formats-badge]: https://img.shields.io/badge/module%20formats-umd%2C%20cjs%2C%20es-green.svg?style=flat-square
|