Closed dmorda closed 4 months ago
Hi Damon (@dmorda), Merry Christmas, and thank you for opening this issue ๐ .
About:
A way to have a scroll option for single/multiple slides
Would you mind explaining what you mean a bit more in detail or provide an example? Because I need more information to answer this question, but I'm going to take a guess and ask if you've checked out the slidesToScroll
option? Here's a CodeSandbox that demonstrates how you can achieve this.
The answer to your question about the fade option is no, it has not been requested yet. I'm not sure what you mean by fade option because it can be done in many different ways so would you mind explaining a bit further? I'm guessing here too but maybe you can achieve this by hooking onto the classname toggling for selected slides? Please have a look at the documentation here.
Thank you in advance!
Best, David
Thanks for the quick response and a Merry Christmas to you as well. What I'm trying to achieve is a Fade effect , as an example view this page and search for the word "Fade". That will provide an example of what I'm trying to accomplish.
Let me know if that helps!
Hi again Damon (@dmorda), Thank you for the clarification, it helps ๐.
The vision for Embla is carousels that move in a fluid and natural manner. The assumption here is that the carousel should be scrollable, and that doesn't play well with fade sliders that don't feel natural when dragging/swiping. This is why a fade option is not a part of the Embla vision and won't be incorporated into the Embla core.
But with that said, I've setup a CodeSandbox example for you, where I've created the fade effect just by tweaking some CSS.
I hope that you'll find it useful!
Best, David
That small tweak now lets me re-use Embla for both the fade version of a carousel and the normal sliding version. Thanks so much, happy holidays!
Hi Damon (@dmorda),
Iโm glad to hear that ๐. Thank you and happy holidays to you too!
Kindly, David
Hey @davidjerleke, sorry for digging up an old issue but I found your sandbox for a fade slider (thanks!). While playing around with it, I noticed that every slide is seen as "in view" by the slider and subsequently gets the selectedClass
when the window is resized, meaning no more slides.
I added a reInit
and resize
listener to the sandbox here to fix this. If this is the correct change, it might make sense to update your original sandbox for future users that may find this?
Happy to hear your thoughts on this ๐ Thanks!
Hi @vntw,
Thank you for noticing this.
I added a
reInit
andresize
listener to the sandbox here to fix this. If this is the correct change, it might make sense to update your original sandbox for future users that may find this?
Your suggestion does the trick, nice work ๐. I've updated the original CodeSandbox. I also added the skipSnaps: false;
option because skipping slides when vigorous dragging occurs might lead to confusing UX for fade sliders. From the docs:
Allow the carousel to skip scroll snaps if it's dragged vigorously. Note that this option will be ignored if the dragFree option is set to true.
Thank you for your efforts!
Best, David
Thank you @davidjerleke!
As of v.6 itโs possible to provide plugins to Embla. A Fade plugin will be added in the future:
Great solution with the fade effect!
I have an improvement suggestion for the CSS used in the SandBox.
I was applying the example CSS code to my project and noticed that since positon: absolute;
is used to stack the slides, it is also required to set the slide height on the .embla__container
.
In my case, I wanted the container to automatically use the height as defined by the slide markup itself. By changing the CSS to use display: grid;
as per the code below, the height of the slides is still defined by the slide side markup.
.embla__container {
transform: none !important; /* override Embla */
display: flex;
}
.embla__slide {
transform: none !important; /* required if loop is active */
flex: 0 0 auto;
width: 100%;
height: 250px;
opacity: 0;
transition: opacity 1s;
counter-increment: embla;
border-radius: 0.5rem;
font-size: 5rem;
}
.embla--is-ready .embla__container {
display: grid;
}
.embla--is-ready .embla__slide {
grid-row: 1;
grid-column: 1;
}
Great solution with the fade effect! I have an improvement suggestion for the CSS used in the SandBox [...]```
I think best practice would be to do something like this:
.embla.fade.ready .embla__slide { position: absolute; } .embla__slide.is-selected { position: relative; }
This requires the classes module but works perfect for me. Height of the container is automatically adapted to your selected slide.
The sandbox linked multiple times here doesn't load anymore. Does anyone have a copy of the code?
Finally got an hour without interruptions to work on the embla-carousel-fade
plugin. I have dragging between slides left to implement. Here's a sneak preview for anyone interested:
https://github.com/davidjerleke/embla-carousel/assets/11529148/8011050e-4c12-45fd-b310-1aa2e9160d95
Finally got an hour without interruptions to work on the
embla-carousel-fade
plugin. I have dragging between slides left to implement. Here's a sneak preview for anyone interested:fade-plugin-wip.mp4
๐๐ผ๐ฅบ
Finally got an hour without interruptions to work on the
embla-carousel-fade
plugin. I have dragging between slides left to implement. Here's a sneak preview for anyone interested:https://github.com/davidjerleke/embla-carousel/assets/11529148/8011050e-4c12-45fd-b310-1aa2e9160d95
David, any info when this will be available? I really need this ๐ฅบ
David, any info when this will be available? I really need this ๐ฅบ
@nikolay17538583 unfortunately no. I'm doing this on my unpaid spare time so I never know when I get my next chance to work on this.
Weโre getting close to a release people. I only have two edge cases left to fix and after that I will clean up some code and add a page to the documentation.
Anyone who wants to help out and speed up the release of this plugin can keep an eye on this issue as I will publish CodeSandboxes here as soon as Iโm done with fixing the edge cases. If you guys test the sandboxes and help out, we might be able to catch some obvious bugs before the release.
Best, David
Let us know if there's a sandbox ready; happy to help test.
Yes let us know when it's ready i'm interested too :)
@davidjerleke any chance to use this plugin now, even the active dev version?
Same here, I'd be happy to use an active dev version for now too. I appreciate the work @davidjerleke!
@davidjerleke we're using splide in our projects and since it seems it's a dead end, we're thinking to move everything on Embla. A fade plugin would really make it the definitive js carousel!
[!IMPORTANT]
This is NOT the finished product but a work in progress. Most things are in place but not everything yet.
@davidjerleke Looks perfect! Do you think it'll be possible to apply the lazy rendering solution discussed here while using this new plugin? Rendering only the slides in view is especially useful for performance when dealing with heavy content like images (note how in your example app above, all images are loaded even though only one is shown), custom components, or even videos where you want the player to be destroyed when it goes out of view.
Hi @davidjerleke. I think we can modify function positionSlides
function positionSlides() {
const { scrollSnaps, slideRegistry } = emblaApi.internalEngine()
const slides = emblaApi.slideNodes()
scrollSnaps.forEach((scrollSnap, scrollSnapIndex) => {
const slidesInSnap = slideRegistry[scrollSnapIndex]
slidesInSnap.forEach((slideIndex) => {
slides[slideIndex].style.transform = `translateX(${scrollSnap}px)`
})
})
}
Replace
function positionSlides() {
emblaApi.slideNodes().forEach((slide, slideIndex) => {
slide.style.transform = `translateX(${slideIndex * -100}%)`
})
}
What do you think, is this possible? Demo
@sarussss thank you for your input ๐. My solution works with slides that are less than 100% wide too - They will be centered and also works when slidesToScroll: 'auto'
. That's the motivation for my solution.
@davidjerleke thank you for your feedback. I think it's not really necessary because when using fade, we will adjust the width in the parent element and fade only works well when there is only 1 slide in each viewport.
Don't care too much about these things, these are just some of my thoughts, because I don't understand Embla as deeply as you do, so if anything is incorrect, please forgive me.
P/S: Thanks for your hard work, the fade plugin is awesome.
Out of curiosity, will the fade duration be adjustable? For both autoplay and next / previous trigger, I feel as though a duration adjustment is almost a necessity. Great work thus far!
@ItsFrankieD yes, the default duration option for the carousel constructor changes the fade duration.
Do you think it'll be possible to apply the lazy rendering solution discussed here while using this new plugin? Rendering only the slides in view is especially useful for performance when dealing with heavy content like images (note how in your example app above, all images are loaded even though only one is shown), custom components, or even videos where you want the player to be destroyed when it goes out of view.
@meirroth yes. The plugin will expose the slide opacity states with a method called opacities()
. Not sure that opacities
will be the final method name when released though so feel free to suggest a name. Let's say you want to load images for all slides that have an opacity greater than 0. You will be able to achieve that like this:
function loadImages(emblaApi) {
const opacities = emblaApi.plugins().fade.opacities();
opacities.forEach((opacity, snapIndex) => {
if (opacity === 0) return // Not visible so bail here
const slidesInSnap = emblaApi.internalEngine().slideRegistry[snapIndex];
slidesInSnap.forEach((slideIndex) => { /* Load image for slideIndex */ })
})
}
emblaApi.on('scroll', loadImages);
@davidjerleke Thank you! I look forward to using this plugin on our homepage ๐
@meirroth, @sarussss, @ItsFrankieD, @sitoexpress, @walton-alex, @AndreiMotinga, @mil920, @HIT2022 and anyone else interested, feel free to test the fade plugin here.
Let me know how it goes.
@davidjerleke Thanks i tested it and i adapted it to ts and put it on my shadcn carousel and it work well.
@mil920 thanks for letting me know! The package is written in TypeScript so that won't be a problem once officially released.
Do you think it'll be possible to apply the lazy rendering solution discussed here while using this new plugin? Rendering only the slides in view is especially useful for performance when dealing with heavy content like images (note how in your example app above, all images are loaded even though only one is shown), custom components, or even videos where you want the player to be destroyed when it goes out of view.
@meirroth yes. The plugin will expose the slide opacity states with a method called
opacities()
. Not sure thatopacities
will be the final method name when released though so feel free to suggest a name. Let's say you want to load images for all slides that have an opacity greater than 0. You will be able to achieve that like this:function loadImages(emblaApi) { const opacities = emblaApi.plugins().fade.opacities(); opacities.forEach((opacity, snapIndex) => { if (opacity === 0) return // Not visible so bail here const slidesInSnap = emblaApi.internalEngine().slideRegistry[snapIndex]; slidesInSnap.forEach((slideIndex) => { /* Load image for slideIndex */ }) }) } emblaApi.on('scroll', loadImages);
@davidjerleke I tested again the Fade plugin you shared, and even tried it with the Vue wrapper and works perfectly.
Regarding the lazy rendering solution above, would it make sense from API perspective for slidesInView
to return only the slides that is currently visible while using this plugin, as supposed to returning ALL the slides like it does now? I think that will keep the lazy rendering solution consistent between Fade and not Fade carousels.
https://stackblitz.com/edit/embla-carousel-nuxt-fade-lazy?file=app.vue
Regarding the lazy rendering solution above, would it make sense from API perspective for slidesInView to return only the slides that is currently visible while using this plugin, as supposed to returning ALL the slides like it does now? I think that will keep the lazy rendering solution consistent between Fade and not Fade carousels.
@meirroth thanks for your ideas! I've updated the work in progress plugin here with the following:
It's now in place so calling emblaApi.destroy()
cleans up the inline styles and removes the event listeners that the fade plugin is using.
I was able to shift slides with 0
opacity out of view using transform
and it doesn't seem to glitch at all. Try it out if you want and if you agree, this recreates parts of the core Embla functionality which is nice:
// Logging slides in view will work
emblaApi.on('slidesInView', (emblaApi) => {
console.log(emblaApi.slidesInView())
})
However, I'm not sure it makes sense to try recreating the inViewThreshold option. Because when shifting slides with 0
opacity out of view and > 0
in view they will disappear/appear entirely in contrast to a scrolling carousel where slides gradually scroll into view.
However, I'm not sure it makes sense to try recreating the inViewThreshold option. Because when shifting slides with
0
opacity out of view and> 0
in view they will disappear/appear entirely in contrast to a scrolling carousel where slides gradually scroll into view.
@davidjerleke Not sure I follow ๐ฌ But my lazy load implementation above works with your update, and 100% matches non fade carousels which is neat!
Hi @davidjerleke Effect fade only work on desktop. Mobile will run as a slide effect as usual. Is there any way to achieve that?
@sarussss I donโt have this problem. Are you sure youโve double checked everything in your code? Try the app view
link here. Itโs working as expected for me.
Hi @davidjerleke. I mean I want to do that:
It's not a bug, I want to do it with embla, but I don't know how to do it.
@sarussss use the breakpoints option:
const emblaNode = document.querySelector('.embla')
const emblaApi = EmblaCarousel(emblaNode, { loop: true }, [Fade({
breakpoints: {
'(min-width: 768px)': { active: false }
}
})])
@davidjerleke thank of ton.
@sarussss donโt forget to grab the latest updates from the work in progress React sandbox. Just copy the plugin code from the sandbox and replace it with your current plugin code.
Only code cleanup and creating the documentation page for the fade plugin left to do before release. All features done โ .
Awesome, thank you!
Released in 8.1.0
.
In my tests the fade effect seemed a little stuck, perhaps due to the greater number of children in the item, change duration with 20 and in CSS this rule made it smoother;
.embla__slide {
transition-timing-function: linear;
}
@ribeiroeder I suggest you also try lazy loading slides, that might help performance. Here's the implementation from earlier in this thread: https://stackblitz.com/edit/embla-carousel-nuxt-fade-lazy?file=app.vue
Love the carousel and was able to get it working right away. The one thing that I need that it doesn't provide is a way to have a scroll option for single/multiple slides and a fade option to handle next/previous transition when it's just showing a single slide at a time.
Is that something that has been requested before?