davidjerleke / embla-carousel

A lightweight carousel library with fluid motion and great swipe precision.
https://www.embla-carousel.com
MIT License
5.8k stars 175 forks source link

Ability to lock scroll if all slides in view #320

Closed Intaria closed 2 years ago

Intaria commented 2 years ago

Hello.

Is it possible to lock scroll or check if all slides shown completely?

I know that we could get container width with containerRect.width inside api "scroll" callback and compare it with the sum of all slides widths, but is there more cleanup way?

stepanjakl commented 2 years ago

+ 1 it would be nice to have

davidjerleke commented 2 years ago

Hi @Intaria & @stepanjakl,

I'm not quite sure what you mean by lock scroll. Do you want to disable dragging when all slides have been in view once? Or do you want to be able to determine when the carousel has scrolled to the end of its scrollable length?

Best, David

Intaria commented 2 years ago

Hi @davidjerleke Totally disable dragging and overstretching slides when all slides in view at once.

vodolazskikh commented 2 years ago

Hi! I have the same question:)

davidjerleke commented 2 years ago

@Intaria are you using vanilla JS or React?

A friendly reminder: Please use the feature request template because it asks you to provide this information when creating an issue. Manually asking these questions that you initially didn’t answer will increase the time it takes for you to get to help.

Best, David

Intaria commented 2 years ago

@davidjerleke react

davidjerleke commented 2 years ago

Hi @Intaria,

If I understand you correctly, you want to disable dragging as soon as the carousel is headed for the end of its scrollable length. Please let me know if this is not the case.

Here's a CodeSandbox demonstrating that. This is how the sandbox works:

Is this what you had in mind?

Best, David

davidjerleke commented 2 years ago

@Intaria have you had any chance to read my response?

stepanjakl commented 2 years ago

I'll chip in here. It would be nice to have an option (similar to draggable - something like noScrollWithAllSlidesInView - probably with more compact wording though) on the initialisation of the carousel. When all slides are in view at once, hence there is no need to use the scroll - then disable it. But this would be an option for the slider, not an extra function with overflow computation etc. That's at least what I would propose.

davidjerleke commented 2 years ago

Hi @stepanjakl,

Thank you for your response. You didn't answer if the solution I provided here was what you wanted to achieve?

I have to weigh feature request carefully because one of the biggest selling points of Embla is that it's very lightweight but still offers a lot of functionality. Its API is very extensible - Both using the public API and the possibility to use and create plugins is what makes it very extensible. This is the first time in a couple of years that someone asks about this feature. So I don't want to prioritize building it into the core and burden other users with an increased bundle size, unless it gets a whole lot of traction/attention. In contrast, an example of a feature request that got very much attention was the new breakpoints option that was released with v7 yesterday.

So for now I would say that the little function I shared in my solution is what I can offer. I hope this makes sense.

Best, David

stepanjakl commented 2 years ago

I understand. The required outcome can definitely be achieved by using Embla's API. The solution you provided is close to what's needed, except it should disable the scroll on initialization and/or possibly even when slide widths change. For instance, on the desktop you could have 2 slides with 50% width. They fit the container area without overflowing - scroll can be disabled. On the mobile, slide width changes to 100%, therefore one slide would overflow - scroll is enabled. I would say it's not a priority. I could also create a codepen solution for this later.

davidjerleke commented 2 years ago

Hello again @stepanjakl,

For instance, on the desktop you could have 2 slides with 50% width. They fit the container area without overflowing - scroll can be disabled. On the mobile, slide width changes to 100%, therefore one slide would overflow - scroll is enabled.

I think you can do it like this:

const toggleActiveWhenScrollable = () => {
  const isScrollable = embla.internalEngine().scrollSnaps.length > 1
  embla.reInit({ active: isScrollable })
}

const embla = EmblaCarousel(emblaNode, { loop: false })

embla.on('resize', toggleActiveWhenScrollable)
toggleActiveWhenScrollable()

Let me know if it helps.

Best, David

stepanjakl commented 2 years ago

Thank you David, that is a good solution.

davidjerleke commented 2 years ago

Closing this as resolved. Feel free to reopen this if the provided solutions wasn't what you were looking for. If that's the case, please provide clear instructions of what you want to achieve.

adonaicandido commented 8 months ago

Hello again @stepanjakl,

For instance, on the desktop you could have 2 slides with 50% width. They fit the container area without overflowing - scroll can be disabled. On the mobile, slide width changes to 100%, therefore one slide would overflow - scroll is enabled.

I think you can do it like this:

const toggleActiveWhenScrollable = () => {
  const isScrollable = embla.internalEngine().scrollSnaps.length > 1
  embla.reInit({ active: isScrollable })
}

const embla = EmblaCarousel(emblaNode, { loop: false })

embla.on('resize', toggleActiveWhenScrollable)
toggleActiveWhenScrollable()

Let me know if it helps.

Best, David

Could you provide a example for React please? I'm trying to adapt your example but no success so far.

bel7aG commented 3 months ago

is there a way to make embla don't block scroll on vertical slides (axis y) ?

on mobile when embla is full width scrolling will just keep sliding embla rather then scrolling the body

Ingramz commented 3 months ago

Heads up for anyone trying to use the example code posted here. resize event won't fire any longer after active is set to false.

https://github.com/davidjerleke/embla-carousel/blob/7cc1aee2506e7ec4ffeb4eaadb94b7259b286c1c/packages/embla-carousel/src/components/EmblaCarousel.ts#L110-L117

As a workaround I suggest implementing your own ResizeObserver and using that with the event handler.

Lshiroc commented 6 days ago

is there a way to make embla don't block scroll on vertical slides (axis y) ?

on mobile when embla is full width scrolling will just keep sliding embla rather then scrolling the body

You can achive this via breakpoints. If you know when will you show the all slides you can just set the screen size like this:

const [emblaRef] = useEmblaCarousel({
  breakpoints: {
    '(min-width: 1250px)': { active: false }
  }
});