Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Element.scrollIntoView ponyfills for things like "if-needed" and "smooth"

License

NotificationsYou must be signed in to change notification settings

scroll-into-view/scroll-into-view-if-needed

Repository files navigation

npm statnpm versiongzip sizesizesemantic-releaseBrowserStack Status

scroll-into-view-if-needed

This used to be aponyfill forElement.scrollIntoViewIfNeeded. Since then the CSS working group have decided to implement its features inElement.scrollIntoView as the optionscrollMode: "if-needed". Thus this library got rewritten to implement that spec instead of the soon to be deprecated one.

Install

npm i scroll-into-view-if-needed

You can also use it from a CDN:

const{default:scrollIntoView}=awaitimport('https://esm.sh/scroll-into-view-if-needed')

Usage

importscrollIntoViewfrom'scroll-into-view-if-needed'constnode=document.getElementById('hero')// similar behavior as Element.scrollIntoView({block: "nearest", inline: "nearest"})// only that it is a no-op if `node` is already visible// see: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView// same behavior as Element.scrollIntoViewIfNeeded()// see: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoViewIfNeededscrollIntoView(node,{scrollMode:'if-needed',block:'nearest',inline:'nearest',})// same behavior as Element.scrollIntoViewIfNeeded(true) without the "IfNeeded" behavior// see: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoViewIfNeededscrollIntoView(node,{block:'center',inline:'center'})// scrollMode is "always" by default// smooth scroll if the browser supports it and if the element isn't visiblescrollIntoView(node,{behavior:'smooth',scrollMode:'if-needed'})

Ponyfill smooth scrolling

What does ponyfilling smooth scrolling mean, and why is it implemented insmooth-scroll-into-view-if-needed instead?The answer is bundlesize. If this package adds smooth scrolling to browsers that's missing it then the overall bundlesize increases regardless of wether you use this feature or not.

Put it this way:

importscrollIntoViewfrom'scroll-into-view-if-needed'// Even if all you do is thisscrollIntoView(node,{scrollMode:'if-needed'})// You would end up with the same bundlesize as people who need// smooth scrolling to work in browsers that don't support it nativelyscrollIntoView(node,{behavior:'smooth',scrollMode:'if-needed'})

That's why only native smooth scrolling is supported out of the box. There are two common ways you can smooth scroll browsers that don't support it natively. Below is all three, which one is best for you depends on what is the most important to your use case:: load time, consistency or quality.

Load time

In many scenarios smooth scrolling can be used as a progressive enhancement. If the user is on a browser that don't implement smooth scrolling it'll simply scroll instantly and your bundlesize is only as large as it has to be.

importscrollIntoViewfrom'scroll-into-view-if-needed'scrollIntoView(node,{behavior:'smooth'})

Consistency

If a consistent smooth scrolling experience is a priority and you really don't want any surprises between different browsers and enviroments. In other words don't want to be affected by how a vendor might implement native smooth scrolling, thensmooth-scroll-into-view-if-needed is your best option. It ensures the same smooth scrolling experience for every browser.

importsmoothScrollIntoViewfrom'smooth-scroll-into-view-if-needed'smoothScrollIntoView(node,{behavior:'smooth'})

Quality

If you want to use native smooth scrolling when it's available, and fallback to the smooth scrolling ponyfill:

importscrollIntoViewfrom'scroll-into-view-if-needed'importsmoothScrollIntoViewfrom'smooth-scroll-into-view-if-needed'constscrollIntoViewSmoothly='scrollBehavior'indocument.documentElement.style    ?scrollIntoView    :smoothScrollIntoViewscrollIntoViewSmoothly(node,{behavior:'smooth'})

API

scrollIntoView(target, [options])

New API introduced inv1.3.0

options

Type:Object

behavior

Type:'auto' | 'smooth' | Function
Default:'auto'

Introduced inv2.1.0

'auto'

The auto option unlocks a few interesting opportunities.The browser will decide based on user preferences wether it should smooth scroll or not.On top of that you can control/override scrolling behavior through thescroll-behavior CSS property.

Some people getmotion sick from animations. You can use CSS to turn off smooth scrolling in those cases to avoid making them dizzy:

html,.scroll-container {overflow: scroll;}html,.scroll-container {scroll-behavior: smooth;}@media (prefers-reduced-motion) {html,  .scroll-container {scroll-behavior: auto;  }}

'smooth'

Usingbehavior: 'smooth' is the easiest way to smooth scroll an element as it does not require any CSS, just a browser that implements it.More information.

Function

When given a function then this library will only calculate what should be scrolled and leave it up to you to perform the actual scrolling.

The callback is given an array over actions. Each action contain a reference to an element that should be scrolled, with its top and left scrolling coordinates.What you return is passed through, allowing you to implement a Promise interface if you want to (checksmooth-scroll-into-view-if-needed to see an example of that).

importscrollIntoViewfrom'scroll-into-view-if-needed'constnode=document.getElementById('hero')scrollIntoView(node,{// Your scroll actions will always be an array, even if there is nothing to scrollbehavior:(actions)=>// list is sorted from innermost (closest parent to your target) to outermost (often the document.body or viewport)actions.forEach(({ el, top, left})=>{// implement the scroll anyway you wantel.scrollTop=topel.scrollLeft=left// If you need the relative scroll coordinates, for things like window.scrollBy style logic or whatever, just do the mathconstoffsetTop=el.scrollTop-topconstoffsetLeft=el.scrollLeft-left}),// all the other options (scrollMode, block, inline) still work, so you don't need to reimplement them (unless you really really want to)})

Check the demo to see anexample with popmotion and a spring transition.

If you only need the custom behavior you might be better off by using the compute library directly:https://github.com/scroll-into-view/compute-scroll-into-view

Type:'start' | 'center' | 'end' | 'nearest'
Default:'center'

Introduced inv2.1.0

More info.

Type:'start' | 'center' | 'end' | 'nearest'
Default:'nearest'

Introduced inv2.1.0

More info.

Type:'always' | 'if-needed'
Default:'always'

Introduced inv2.1.0

More info.

Type:Element | Function

Function introduced inv2.1.0,Element introduced inv1.1.0

More info.

skipOverflowHiddenElements

Type:Boolean
Default:false

Introduced inv2.2.0

More info.

TypeScript support

When the library itself is built on TypeScript there's no excuse for not publishing great library definitions!

This goes beyond just checking if you misspelledbehavior: 'smoooth' to the return type of a custom behavior:

constscrolling=scrollIntoView(document.body,{behavior:actions=>{returnnewPromise(      ...)},})// TypeScript understands that scrolling is a Promise, you can safely await on itscrolling.then(()=>console.log('done scrolling'))

You can optionally use a generic to ensure thatoptions.behavior is the expected type.It can be useful if the custom behavior is implemented in another module:

constcustomBehavior=actions=>{returnnewPromise(      ...)}constscrolling=scrollIntoView<Promise<any>>(document.body,{behavior:customBehavior})// throws if customBehavior does not return a promise

The options are available for you if you are wrapping this libary in another abstraction (like a React component):

importscrollIntoView,{typeOptions}from'scroll-into-view-if-needed'interfaceCustomOptionsextendsOptions{useBoundary?:boolean}functionscrollToTarget(selector,options:Options={}){const{ useBoundary=false, ...scrollOptions}=optionsreturnscrollIntoView(document.querySelector(selector),scrollOptions)}

Breaking API changes from v1

Since v1 ponyfilled Element.scrollIntoViewIfNeeded, while v2 ponyfills Element.scrollIntoView, there are breaking changes from the differences in their APIs.

The biggest difference is that the new behavior follows the spec, so the "if-needed" behavior isnot enabled by default:

v1

importscrollIntoViewIfNeededfrom'scroll-into-view-if-needed'// Only scrolls into view if needed, and to the nearest edgescrollIntoViewIfNeeded(target)

v2

importscrollIntoViewfrom'scroll-into-view-if-needed'// Must provide these options to behave the same way as v1 defaultscrollIntoView(target,{block:'nearest',scrollMode:'if-needed'})

centerIfNeeded

The oldElement.scrollIntoView api only had two settings, align to top or bottom.Element.scrollIntoViewIfNeeded had two more, align to the center or nearest edge.TheElement.scrollIntoView spec now supports these two modes asblock: 'center' andblock: 'nearest'.Breaking changes sucks, but on the plus side your code is now more portable and will make this library easier to delete from your codebase on the glorious day browser support is good enough.

v1

importscrollIntoViewIfNeededfrom'scroll-into-view-if-needed'// v1.3.x and laterscrollIntoViewIfNeeded(target,{centerIfNeeded:true})scrollIntoViewIfNeeded(target,{centerIfNeeded:false})// v1.2.x and earlierscrollIntoViewIfNeeded(target,true)scrollIntoViewIfNeeded(target,false)

v2

importscrollIntoViewfrom'scroll-into-view-if-needed'scrollIntoView(target,{block:'center'})scrollIntoView(target,{block:'nearest'})

duration

More information.

v1

importscrollIntoViewIfNeededfrom'scroll-into-view-if-needed'scrollIntoViewIfNeeded(target,{duration:300})

v2

importscrollIntoViewfrom'scroll-into-view-if-needed'// orimportscrollIntoViewfrom'smooth-scroll-into-view-if-needed'scrollIntoView(target,{behavior:'smooth'})

easing

This feature is removed, but you can achieve the same thing by implementingbehavior: Function.

handleScroll

This is replaced withbehavior: Function with one key difference. Instead of firing once per element that should be scrolled, the new API only fire once and instead give you an array so you can much easier batch and scroll multiple elements at the same time. Or sync scrolling with another element if that's the kind of stuff you're into, I don't judge.

-import scrollIntoViewIfNeeded from 'scroll-into-view-if-needed'+import scrollIntoView from 'scroll-into-view-if-needed'-scrollIntoViewIfNeeded(node, {handleScroll: (el, {scrollTop, scrollLeft}) => {-  el.scrollTop = scrollTop-  el.scrollLeft = scrollLeft-}})+scrollIntoView(node, {behavior: actions.forEach(({el, top, left}) => {+  el.scrollTop = top+  el.scrollLeft = left+})})

offset

This was always a buggy feature and warned against using in v1 as it might get dropped.It's much safer to use CSS wrapper elements for this kind of thing.

scrollIntoViewIfNeeded(target, [centerIfNeeded], [animateOptions], [finalElement], [offsetOptions])

This API signature were warned to be dropped inv2.0.0, and it was.

Related packages

Who's using this

  • zeit.co/docs – Documentation of ZEIT Now and other services.
  • Selenium IDE – An integrated development environment for Selenium scripts.
  • Box UI Elements – Box UI Elements are pre-built UI components that allow developers to add elements of the main Box web application into their own applications.
  • react-responsive-ui – Responsive React UI components.
  • Mineral UI –A design system and React component library for the web that lets you quickly build high-quality, accessible apps.
  • Covalent – Teradata UI Platform built on Angular Material.
  • docs.expo.io – Documentation for Expo, its SDK, client and services.
  • Add yourself to the list 😉

Sponsors

Thanks toBrowserStack for sponsoring cross browser and device testing 😄


[8]ページ先頭

©2009-2025 Movatter.jp