Giter Club home page Giter Club logo

scroll-into-view-if-needed's Introduction

npm stat npm version gzip size size semantic-release BrowserStack Status

scroll-into-view-if-needed

This used to be a ponyfill for Element.scrollIntoViewIfNeeded. Since then the CSS working group have decided to implement its features in Element.scrollIntoView as the option scrollMode: "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 } = await import(
  'https://esm.sh/scroll-into-view-if-needed'
)

Usage

import scrollIntoView from 'scroll-into-view-if-needed'

const node = 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/scrollIntoViewIfNeeded
scrollIntoView(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/scrollIntoViewIfNeeded
scrollIntoView(node, { block: 'center', inline: 'center' })
// scrollMode is "always" by default

// smooth scroll if the browser supports it and if the element isn't visible
scrollIntoView(node, { behavior: 'smooth', scrollMode: 'if-needed' })

Ponyfill smooth scrolling

What does ponyfilling smooth scrolling mean, and why is it implemented in smooth-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:

import scrollIntoView from 'scroll-into-view-if-needed'
// Even if all you do is this
scrollIntoView(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 natively
scrollIntoView(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.

import scrollIntoView from '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, then smooth-scroll-into-view-if-needed is your best option. It ensures the same smooth scrolling experience for every browser.

import smoothScrollIntoView from '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:

import scrollIntoView from 'scroll-into-view-if-needed'
import smoothScrollIntoView from 'smooth-scroll-into-view-if-needed'

const scrollIntoViewSmoothly =
  'scrollBehavior' in document.documentElement.style
    ? scrollIntoView
    : smoothScrollIntoView

scrollIntoViewSmoothly(node, { behavior: 'smooth' })

API

scrollIntoView(target, [options])

New API introduced in v1.3.0

options

Type: Object

behavior

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

Introduced in v2.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 the scroll-behavior CSS property.

Some people get motion 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'

Using behavior: '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 (check smooth-scroll-into-view-if-needed to see an example of that).

import scrollIntoView from 'scroll-into-view-if-needed'
const node = document.getElementById('hero')

scrollIntoView(node, {
  // Your scroll actions will always be an array, even if there is nothing to scroll
  behavior: (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 want
      el.scrollTop = top
      el.scrollLeft = left

      // If you need the relative scroll coordinates, for things like window.scrollBy style logic or whatever, just do the math
      const offsetTop = el.scrollTop - top
      const offsetLeft = 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 an example 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 in v2.1.0

More info.

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

Introduced in v2.1.0

More info.

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

Introduced in v2.1.0

More info.

Type: Element | Function

Function introduced in v2.1.0, Element introduced in v1.1.0

More info.

skipOverflowHiddenElements

Type: Boolean
Default: false

Introduced in v2.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 misspelled behavior: 'smoooth' to the return type of a custom behavior:

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

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

const customBehavior = actions => {
    return new Promise(
      ...
    )
  }

const scrolling = 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):

import scrollIntoView, { type Options } from 'scroll-into-view-if-needed'

interface CustomOptions extends Options {
  useBoundary?: boolean
}

function scrollToTarget(selector, options: Options = {}) {
  const { useBoundary = false, ...scrollOptions } = options
  return scrollIntoView(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 is not enabled by default:

v1

import scrollIntoViewIfNeeded from 'scroll-into-view-if-needed'

// Only scrolls into view if needed, and to the nearest edge
scrollIntoViewIfNeeded(target)

v2

import scrollIntoView from 'scroll-into-view-if-needed'

// Must provide these options to behave the same way as v1 default
scrollIntoView(target, { block: 'nearest', scrollMode: 'if-needed' })

centerIfNeeded

The old Element.scrollIntoView api only had two settings, align to top or bottom. Element.scrollIntoViewIfNeeded had two more, align to the center or nearest edge. The Element.scrollIntoView spec now supports these two modes as block: 'center' and block: '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

import scrollIntoViewIfNeeded from 'scroll-into-view-if-needed'

// v1.3.x and later
scrollIntoViewIfNeeded(target, { centerIfNeeded: true })
scrollIntoViewIfNeeded(target, { centerIfNeeded: false })
// v1.2.x and earlier
scrollIntoViewIfNeeded(target, true)
scrollIntoViewIfNeeded(target, false)

v2

import scrollIntoView from 'scroll-into-view-if-needed'

scrollIntoView(target, { block: 'center' })
scrollIntoView(target, { block: 'nearest' })

duration

More information.

v1

import scrollIntoViewIfNeeded from 'scroll-into-view-if-needed'

scrollIntoViewIfNeeded(target, { duration: 300 })

v2

import scrollIntoView from 'scroll-into-view-if-needed'
// or
import scrollIntoView from 'smooth-scroll-into-view-if-needed'

scrollIntoView(target, { behavior: 'smooth' })

easing

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

handleScroll

This is replaced with behavior: 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 in v2.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 to BrowserStack for sponsoring cross browser and device testing πŸ˜„

scroll-into-view-if-needed's People

Contributors

ambar avatar arturbien avatar borm avatar dependabot[bot] avatar forabi avatar github-actions[bot] avatar greenkeeperio-bot avatar hemnstill avatar icd2k3 avatar imgbot[bot] avatar iwangulenko avatar jclijmans avatar jkillian avatar khell avatar li-jia-nan avatar long76 avatar madkap avatar pelotom avatar philipp-spiess avatar prettierci[bot] avatar renovate[bot] avatar rostimelk avatar semantic-release-bot avatar sindresorhus avatar stipsan avatar stramel avatar tonybdesign avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

scroll-into-view-if-needed's Issues

Cannot read property 'clientHeight' of undefined

2.2.8 is the last version that works for me (tried both Chrome and Safari). 2.2.9 and all later versions fail with:

scroll-into-view.min.js:1 Uncaught TypeError: Cannot read property 'clientHeight' of undefined
    at n (scroll-into-view.min.js:1)
    at r (scroll-into-view.min.js:1)
    at scroll-into-view.min.js:1

Here is the failing invocation (elem is neither undefined nor null):

scrollIntoView(elem, {
        behavior: 'instant',
        scrollMode: 'if-needed',
        block: 'nearest',
        inline: 'nearest',
      });

Body behind the modal scrolls

I have modal inside which I have a list of passengers who have scroll into view when clicked on a particular passenger. This works perfectly fine, but the body behind the modal also scrolls when this happens even thous I have frozen scroll using "overflow: hidden" CSS property. How to avoid body scroll.

Add support for upcoming promise behavior

Smooth scrolling will return promises in the future: w3c/csswg-drafts#1562

Suggested implementation here is:
If the browser is returning a promise, pass it through and let the browser decide how it's resolved.
If the browser isn't returning a promise, but the behavior is set to "smooth", use Promise.reject as there is no way of knowing when scrolling is complete anyway so userland code needs to handle both cases.

Scrolling on element happens only the first time

I have a slider of elements and a large view below the slider that is mounted when an element is clicked.
I have used scrollIntoViewIfNeeded when the large view component gets mounted.
It scrolls nicely the first time, but when i close the view and then open it again. It does not scroll.

Angular production support

When importing your lib to an angular project (I tried it with 6.1.9 with a simple empty project created with ng new) and running ng serve it works fine.

When I run ng serve --prod though, calling scrollIntoView just does nothing. There are no errors on compilation or at runtime, but apparently minification/uglification destroys something essential.

compute.js

Hi,
you left console.log in compute.js -> line 67 -> "console.log('test')"

typescript typings are wrong

Typescript, unlike babel, differentiates between default and "whole" exports, this is.
import * as X from 'X'; = require('X')
import X from 'X'; = require('X').default;

whereas in babel
import X from 'X'; = require('X').default || require('X');

the thing is that the TS typings say that the function is actually on require('X').default, but it is actually in require('X') due to this last line in the generated index.js:

module.exports = exports['default'];

something to do most probably with how rollup does it.
could the typings be fixed? or if not at least then make it actually export the function on default :)

animation not working

Using
scrollIntoViewIfNeeded(node, {duration: 500});

It is getting scrolled to that particular div but but animation is not working.
pls look into this.

Incorrect scroll behaviour on a page

Version: 2.2.14.
See the gif:

1234

I don't observe the bug on the react-responsive-ui demo page but in a real-world app I can see the bug.
Don't know what could cause such behaviour.
I guess there could be many variables affecting that.

I downgraded to various versions and found out that 2.1.0 doesn't have the bug and >= 2.1.1 has the bug, so I guess it was some change from 2.1.0 to 2.1.1.
I'm staying on version 2.1.0 because of that.

NPM distribution is unusual

Just tried out this package for this first time, and I'm a big fan! The native browser scrollIntoView was causing issues for me and this package is working perfectly.

However, I did notice the NPM distribution for this package is somewhat strange. The distributed files, specifically dist/bundle.js seem to contain all the dependent packages bundled together. This isn't the NPM way - ideally your distributed module should just require the other modules it wants to use. My friendly suggestion here is to use babel to compile your src/index.js file and distribute that in your final package as either index.js or dist/index.js and appropriately link to it in your package.json. You can still distribute the full rolled-up dist/bundle.js if you want, but it shouldn't be the main file.

Also, I noticed that the export in the distributed version is not a default export. So you have to do import * as scrollIntoView from "scroll-into-view-if-needed" instead of the examples given in the README.

Finally, I'd recommend adding the MIT license or another similar license to this package! Don't want to scare people away from using it πŸ˜„

Todo for v2

Moving it out of #155 so this can be done in multiple PRs.

Guiding principles behind the rebuild

  • Ponyfill principles, never alter globals that one day could break the web (cough cough mootools cough cough)..
  • Minimal in design and API surface.
  • Follow the Element.scrollIntoView(ScrollIntoViewOptions) spec and related draft specs instead of reinventing the wheel.
  • Comprehensive testing suite to ensure the spec is implemented correctly, and that common use cases are accounted for.
  • Modular design, favor composition over configuration.
  • Adapts to your priorities. If speed and bundlesize is more important than every visitor seeing a nice smooth scroll then the default version is enough. If a consistent user experience for all your users is more important, opt in to the smooth-behavior ponyfill.
  • Sensible defaults, zero-config (as long it doesn't break spec compliance).
  • Lifecycle hooks instead of a million options.

Entirely new API, implementing Element.scrollIntoView(ScrollIntoViewOptions) and {scrollMode: 'if-needed' | 'always'}.

  • new docs page.
  • upgrade cypress to be all TS.
  • upgrade next.js to follow TS best practice.
  • upgrade next.js to export test pages when cypress is running it.
  • update readme.
  • rewrite old tests to new changes.
  • migration guide with a list over breaking changes.
  • new rollup build that generates react-router like suite of bundles so this package is easier to consume for most people.
  • {scrollMode: 'if-needed'}, this feature is what spawned the creation of this package, but it needs to be rewritten to simply check if something isn't visible before it should optimistically attempt scrolling it into view (reference implementations: 1)
  • {scrollMode: 'always'}, and suddenly this package became a lot more useful.
  • {block: 'start'}
  • {block: 'center'}
  • {block: 'end'}
  • {block: 'nearest'}
  • {inline: 'start'}
  • {inline: 'center'}
  • {inline: 'end'}
  • {inline: 'nearest'}
  • scroll it yourself {behavior: (scrollInstructions: [Element, scrollTop, scrollLeft])}. Maybe you want to be creative, or a different transition, easing, do it in a sequence or throttle it. Whatever floats your boat.
  • {behavior: 'smooth'} (ensure ponyfilled animation matches what firefox and chrome is doing, it must not feel slow or odd).
  • {boundary: Element}, limit propagation of scrolling as it traverses innermost to outermost scrolling boxes by passing in an element reference.
  • {boundary: (el: Element) => boolean}, provide a way to do custom checks. This solves the problem with cross-realm elements (scrolling up iframes and frames) where referencial checks won't work. It also provides an escape hatch for userland business logic like "skip all elements that are overflow: hidden".

Testing strategy

Helpful reference material

https://github.com/chromium/chromium/blob/f18e79d901f56154f80eea1e2218544285e62623/chrome/browser/resources/chromeos/login/screen_supervised_user_creation.js#L392-L433

https://github.com/chromium/chromium/blob/7bacbbc6c0e5e337f642811374d9023f52795bd3/chrome/browser/resources/chromeos/chromevox/common/selection_util.js#L226-L249

http://www.performantdesign.com/2009/08/26/scrollintoview-but-only-if-out-of-view/

https://github.com/chromium/chromium/blob/f18e79d901f56154f80eea1e2218544285e62623/third_party/WebKit/LayoutTests/fast/scroll-behavior/bordered-container-child-scroll.html

https://github.com/iamdustan/smoothscroll/blob/master/src/smoothscroll.js

https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/dom/element.cc?sq=package:chromium&dr=CSs&l=500

Using FireFox' implementation as reference

The way FireFox handles smooth scrolling, and the scrollIntoView features in general is the best one today. So I am using their C++ implementation to guide me on the JS implementation: https://github.com/mozilla/gecko/blob/03abe3240ab1ad8c2e7f78ebb16a6bd3c17febb1/layout/base/PresShell.cpp#L3626-L3743

Rationale from dropping Element.scrollIntoViewIfNeeded

The fine folks over at chromium are already discussing removing this non-standard api: https://bugs.chromium.org/p/chromium/issues/detail?id=699843&q=scrollintoView&colspec=ID%20Pri%20M%20Stars%20ReleaseBlock%20Component%20Status%20Owner%20Summary%20OS%20Modified

It's time to move on πŸ˜ƒ

Bug - full-height elements can't scroll into view

I ran into a situation in my code where I wanted to change something so that a full-height element (same height as scroll container) would scroll into view. To my surprise, nothing happened. I thought it must be my code, so I made a Codepen, with the same behavior (nothing happens): https://codepen.io/matthewdean/pen/KxaJga

To verify that it wasn't something wrong with scrolling setup, I made a 99% height tile version, which works: https://codepen.io/matthewdean/pen/qMRgVL

Then I thought, "Well maybe this is just a bug where elements larger than the scrollable area don't scroll into view," at which point I discovered something totally bonkers. A Codepen with tiles that are 101% also work. https://codepen.io/matthewdean/pen/QVdYQp

So this bug appears to be that only tiles the same exact height as the scrollable area cannot scroll into view

The automated release is failing 🚨

🚨 The automated release from the master branch failed. 🚨

I recommend you give this issue a high priority, so other packages depending on you could benefit from your bug fixes and new features.

You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. I’m sure you can resolve this πŸ’ͺ.

Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.

Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the master branch. You can also manually restart the failed CI job that runs semantic-release.

If you are not sure how to resolve this, here is some links that can help you:

If those don’t help, or if this issue is reporting something you think isn’t right, you can always ask the humans behind semantic-release.


The push permission to the Git repository is required.

semantic-release cannot push the version tag to the branch master on remote Git repository with URL http://[secure]@github.com/stipsan/scroll-into-view-if-needed.git.

Please refer to the authentication configuration documentation to configure the Git credentials on your CI environment and make sure the repositoryUrl is configured with a valid Git URL.


Good luck with your project ✨

Your semantic-release bot πŸ“¦πŸš€

how to know when scrolling is complete?

Hi, is there any way to know whether the scroll into view action has completed (promise resolution? a recommended timer approach?)?

the closest to this issue I found is #387 . Thanks!

Can i set a offset?

I have some thing floating on the screen like header. I want to set a offset to scroll more and show the content behind the floating header out.

Scrolls both window and container

Hi πŸ‘‹ Thanks for making this library!

I'm using it to scroll a list that has overflow-y: scroll. However, when scrolling to an element on the bottom of this list the window is scrolled to the bottom as well. Is there a way to avoid this or is it a bug?

[BUG] Safari on macOS Monterey 12.3.1

Hey there, thanks for your job!

I would like to report that default function does not work on Safari macOS Monterey 12.3.1. The native function scrollIntoViewIfNeeded does work.

Is there any fix we can do?

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.


Using a curated preset maintained by


Sanity: The Composable Content Cloud

Pending Approval

These branches will be created by Renovate only once you click their checkbox below.

  • chore(deps): update dependency @sanity/pkg-utils to v5
  • chore(deps): update dependency @sanity/pkg-utils to v6
  • chore(deps): update dependency @sanity/semantic-release-preset to v5
  • chore(deps): lock file maintenance
  • πŸ” Create all pending approval PRs at once πŸ”

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.github/workflows/ci.yml
  • actions/checkout v4
  • actions/setup-node v4
  • actions/checkout v4
  • actions/setup-node v4
  • actions/checkout v4
  • actions/setup-node v4
.github/workflows/prettier.yml
  • actions/checkout v4
  • actions/setup-node v4
  • actions/cache v4
  • EndBug/add-and-commit v9@61a88be553afe4206585b31aa72387c64295d08b
npm
package.json
  • compute-scroll-into-view ^3.0.2
  • @sanity/pkg-utils ^3.2.2
  • @sanity/semantic-release-preset ^4.0.0
  • cross-env ^7.0.3
  • prettier ^3.0.3
  • prettier-plugin-packagejson ^2.4.3
  • rimraf ^4.1.2
  • typescript ^5.0.0

  • Check this box to trigger a request for Renovate to run again on this repository

How can I combine behavior function and behavior smooth

Hi, there.

Because there is a banner above the scroll container, I need to set a target offset. I tried the behavior function implementation, but also wanted to use behavior smooth. How can we combine the two? Do you have any idea?

behavior: actions => {
      const [{el, top}] = actions;
      el.scrollTop = top - targetOffset
      return scrollMotion ? 'smooth' : 'auto'; // works or not?
}

Add option to force centering

Description of options.centerIfNeeded says:

Center the target if possible, and if it's not already visible. If it's not centered but still visible it will not scroll

Description of options.forceCenter would be:

Brute force version of options.centerIfNeeded. This will adjust the scroll to center the target even if it's visible already

Scrolling up doesn't work with scrollMode: if-needed

πŸ‘‹ hey there,

After some investigation of an issue posted in react-scroll-into-view-if-needed here. It looks as though there is a bug with the following behavior:

  • scrolling up to a target block with scrollMode: 'if-needed'.

I setup this codesandbox to demonstrate: https://codesandbox.io/s/l4w26w2jz7
(note: it is in React, but I'd be happy to setup an html/css only one soon if it helps)

In this example, with scrollMode set to 'always', scroll to the bottom of the page and click this button at the bottom:
button

Notice that it scrolls up to the target as expected

Now, switch to 'if-needed' and notice the button does not scroll up to the target.

I'm happy to dig deeper in the near future and submit a PR if I can find the problem, but in the meantime just wanted to document it here for visibility.

Thanks for your work on this package!

Why accept arg #2 (centerIfNeeded) and options.centerIfNeeded?

This is mostly curiosity: why even include the 2nd parameter if the options parameter can do so?

The following cases (I presume) are analogous:

scrollIntoViewIfNeeded(myEl, true);
scrollIntoViewIfNeeded(myEl, null, {centerIfNeeded: true});

If they aren't analogous:

  1. Why not?
  2. Why is it not documented?

I feel as though the signature could be simplified to just be:

export default function(
  node: Element,
  options?: ScrollIntoViewIfNeededOptions,
  finalElement?: Element
): void;

I understand that parameter 2 is for convenience (at least I assume so), in which case, I recommend removing it from the ScrollIntoViewIfNeededOptions interface to avoid confusion.

Otherwise good work on a useful module. It's nice to have this around instead of pretending that browsers support the native implementation ;)

Expose amator's `done` option?

I need to do something after the animation is done but don't see a way of doing it with the current options, outside of doing something like setTimeout using the duration time.
I noticed aminate function accepts a done option that isn't being used by this package.

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: undefined. Note: this is a nested preset so please contact the preset author if you are unable to fix it yourself.

Content partially hidden behind scrollbars

When I set block/inline to end or nearest, in a container with scrollbars, part of the target element on the bottom and right remains hidden behind the scrollbars.

This is visible on https://scroll-into-view-if-needed.netlify.com/, the "scroll alignment" example. With block and inline both set to nearest, scrolling to 9 results in the green box being only partially visible, while scrolling to 1 results in that green box being fully visible. If I set the container to overflow: visible in devtools, scrolling to 9 results in the green box being fully visible, like for 1.

I get this behaviour on both Firefox 52.5 and Chromium 64.0.

Scroll element inside a iframe stop working when update to version 2.2.19

I have a React component render list chidrent inside a iframe (fixed height and scrollable). When i click on a child element i want to scroll it to center viewport. I use scroll-into-view-if-needed and it worked. but after update to version 2.2.19 it stop work without any error message. It work again when downgrade to version 2.2.15

`scrollIntoView` Promise doesn't resolve on some elements

I discovered an apparent bug, where I have something like this:

scrollIntoView([HTMLElement], {
  scrollMode: 'if-needed',
  block: 'nearest',
  boundary: document
}).then(() => { console.log('done') })

It appears that if the element doesn't need to be scrolled into view (or some other reason?), then the Promise will never resolve. Even if I change .then() to .finally(), nothing happens. No console.log is output. Meaning I can't chain scrollIntoViews.

I didn't have this problem until the element I needed to check if it needed to be scrolled into view was sometimes the same height as the document.

Set block: nearest with offset?

I need to be able to scroll into view with block: 'nearest' but with an offset. So this means I can have it scroll to the bottom of a div, but provide some buffer space below so the div isn't on the exact bottom of the screen. The center option is too drastic for my use, I just need a buffer of 30 pixels or so but still want it at the bottom of the screen.

I'm hoping there is a way to do this, but if not then this would be a feature request :)

Setup automatic changelog generation

Changelog haven't been updated since v2, and I'd rather not continue to update it manually.

It should be generated the same way release notes are generated during publish.

Unneeded scrolling of ancestors

https://recordit.co/z3vQ93V1YP

Scrolling the parent also scrolls another ancestor higher up the DOM tree.

I understand this is the "standard" behavior even for the browser-implemented scrollIntoView. Is there any way to prevent this? It would be useful if the method did what its name suggest ("ifNeeded").

What happened to duration?

Hi, I just upgraded to v2, which looks great, except the duration option seems to have gone away... is it no longer possible to specify a duration for the smooth scroll animation?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.