kenwheeler / slick

the last carousel you'll ever need
kenwheeler.github.io/slick
MIT License
28.39k stars 5.88k forks source link

centerMode not centering correctly #2795

Open nathanhornby opened 7 years ago

nathanhornby commented 7 years ago

I've been having issues getting centerMode to center the first slide on initialisation when using variableWidth. I find that I have to move to the next slide, and back again for Slick to work out what the center actually is.

====================================================================

The provided jsfiddle required too much reworking to be relevant as this is a variable width example. I kept it as simple as possible though.

http://jsfiddle.net/1wyegw6L/16/

Interestingly in my real-world example the offset goes the other way, to the right. It actually looks like the first slide is just being offset by 50% with no correction for the slides width:

screen shot 2017-03-14 at 15 49 19

But once I've gone forward and then back a slide it corrects itself:

screen shot 2017-03-14 at 15 50 39

====================================================================

What is the expected behaviour?

Center the slideshow with a focus on the first slide.

====================================================================

What is observed behaviour?

The first slide is off-center on initialisation, but centers itself after navigation.

====================================================================

More Details

- Which browsers/versions does it happen on? Chrome 56.0.2924.87 (64-bit)

- Which jQuery/Slick version are you using? jQuery 3.1.1 Slick 1.6.0

- Did this work before? Before when?

nathanhornby commented 7 years ago

I just had a showerthought that maybe it's due to Slick not knowing the width of the elements on initialisation because they're images that might not have loaded yet. But I tried explicitly stating the width and it didn't seem to help:

http://jsfiddle.net/1wyegw6L/18/

I also tried creating the same example but using divs instead of images, just in case it was a similar but different issue to above:

http://jsfiddle.net/1wyegw6L/19/

But… same thing 😢

In fact the slides don't even need variable widths for the problem to occur, simply having the option turned on is enough:

http://jsfiddle.net/1wyegw6L/20/

nathanhornby commented 7 years ago

This has become a show-stopper on a project where I've used this plugin quite extensively - so I've created an SO in addition to this issue. Any kind of input would be appreciated @kenwheeler

kenwheeler commented 7 years ago

Yeah this is a legit bug

nathanhornby commented 7 years ago

@kenwheeler Awesome thanks for confirming Ken! 99% of the time it's a mistake at my end, so it's somewhat comforting to know ☺️

henrybarn commented 7 years ago

Any suggestions on a temp fix @nathanhornby @kenwheeler? I've tried reiniting, disabling lazyload, navigating to slide 1 after init, nothing will work

nathanhornby commented 7 years ago

I'm afraid not no - waiting on a fix myself :(

On Wed, 12 Apr 2017, 23:09 henryaaron, notifications@github.com wrote:

Any suggestions on a temp fix @nathanhornby https://github.com/nathanhornby @kenwheeler https://github.com/kenwheeler? I've tried reiniting, disabling lazyload, navigating to slide 1 after init, nothing will work

— You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub https://github.com/kenwheeler/slick/issues/2795#issuecomment-293721786, or mute the thread https://github.com/notifications/unsubscribe-auth/AB4jgAcJusf45d95U7cTqIOJsOxFQ8VQks5rvUuegaJpZM4McxSw .

mrpritchett commented 7 years ago

Also able to confirm this. I weep that I won't be able to use Slick Slider on a client project because of this bug. But fully believe that the mythical Ken Wheeler shall save the day. :P

henrybarn commented 7 years ago

I'm glad to work on it but I haven't even figured out where the bug stems from. I unslick'ed and slick'ed from the console with all images downloaded and saw the same issue so I don't think it's an issue with downloading the images

nathanhornby commented 7 years ago

I took a quick look when i reported it but the problem is a bit beyond me i feel. There must be a difference in the calculation when the slider is initialised to when it's interacted with - the fact it 'fixes' itself as soon as you slide leads me to believe this - in which case it could be as simple as a typo in an algorithm somewhere, or a function not being called.

darktef commented 7 years ago

I tried to resize window after 1sec timeout, it is still buggy, but seems a good enough temp solution for now.

window.setTimeout(refreshWindow, 1000)

function refreshWindow() {
  $(window).resize()
}
mrpritchett commented 7 years ago

I was able to "solve" this by creating a breakpoint every 200px going up to a high number. Not ideal, but the client was happy. 😂 ... 😢

nathanhornby commented 7 years ago

@mrpritchett Curious, how did that solve your issue? The container isn't the problem for me - variable-width slides don't seem to be centred correctly at any width.

mrpritchett commented 7 years ago

For me it was a miscalculation between centerPadding and the browser width. So setting that at each breakpoint at a reasonable resolution change (200px) was enough to fake it. I did have instances where it wouldn’t center at all, but after playing with centerPadding and the breakpoints they seem to smooth over.

On Apr 25, 2017, at 11:55 AM, Nathan Hornby notifications@github.com wrote:

@mrpritchett https://github.com/mrpritchett Curious, how did that solve your issue? The container isn't the problem for me - variable-width slides don't seem to be centred correctly at any width.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/kenwheeler/slick/issues/2795#issuecomment-297076647, or mute the thread https://github.com/notifications/unsubscribe-auth/ADLMOVKYUzzxmpd4uL2UvLnW4-H1rSnQks5rzhdmgaJpZM4McxSw.

nathanhornby commented 7 years ago

Interesting. I think it's very specific circumstances that trigger this bug. I mean, the variableWidth example on the Slick website works fine, all whilst using centerMode, and doesn't utilise centerPadding at all. But my dead-simple jsfiddle upthread demonstrates that given the most basic of circumstances it doesn't work at all. I really don't get it.

henrybarn commented 7 years ago

My settings are: centerMode, variableWidth, and initialSlide 0.

My observations are that the slide either centers properly, or the center is the left edge of initialSlide-1 (the last slide), or the center is the left edge of initialSlide-2 (second to last slide).

The refreshWindow fix didn't work for me unfortunately.

henrybarn commented 7 years ago

Very annoyingly, the ms I open the console, the slide centers.

henrybarn commented 7 years ago

My fix (doesn't ALWAYS work):

Disable lazyLoading.

$(window).load(function(){
        $('.slider').slick("slickGoTo",1,true);
    $('.slider').slick("slickGoTo",0,true);
});
nathanhornby commented 7 years ago

@henrybarnathan That does seem to do the trick! I haven't been able to test properly yet but it entirely fixes the issue on the jsfiddle: http://jsfiddle.net/b84okape/1/

finbarmaginn commented 7 years ago

+1, i seem to have a variation of the same bug. there is another bug somewhere that talks about centerMode and whitespace at the start and end of the group of slides. it is to do with the clones that are made for centerMode. This means of the first of the two clones is always aligned straight to the left of my container and causes my active slide (which is supposed to be in the center) to be to the left of center. then after the autoplay kicks in i get the bug that is described here. once the screen is resized then the active slide is snapped to the center. see below for the settings i've been playing with:

settings = { centerMode: true, dots: false, variableWidth: true, autoplay: true, focusOnSelect: true, pauseOnHover: false, arrows: false, centerPadding: "7.5px", infinite:true }

i also have some sass to style my center image and create some spacing:

`.slick-slide { margin: 0 2.5px; img { opacity: 0.5; height: 190px; margin: 10px 0; } }

.slick-center { img { opacity: 1; transition: all 0.75s; height: 210px; margin: 0; } }`

diegovdc commented 6 years ago

I came here because of the same or a similar bug. For me centerMode only works correctly when slidesToShow is an odd number.

sergioavazquez commented 6 years ago

I have the same problem, centerMode simple does not center items. I've tried changing the amount of slides, and several other settings but no luck yet. Any news on a fix for this?

Roywcm commented 6 years ago

Same problem here. Only using odd numbers on slidesToShow works. Annoying bug.

luizrrodrigues commented 6 years ago

Same here: https://gyazo.com/0858b983bb601c7458d7c157fb60c98e 0858b983bb601c7458d7c157fb60c98e

In first load working fine, when click next/prev or direct slide not centered right.

My code: 44649ae9b66574434f1a23599b08a47a

844ac1f0911c7374af61014511778f82

ForkInSpace commented 6 years ago

the centerMode problem on even number of slides is a deal breaker. Been using this slider for about a year on number of projects and kinda sucks that this bug hasn't been fixed. :/ Temporary and "sometimes works" fixes aren't acceptable unfortunately. Good slider tho.

philippehenoch commented 5 years ago

In getTrackCSS function, spec.left doesn't have the correct value at the first render. I haven't find yet where the calculation error is

marionviault commented 5 years ago

I had the same problem ; Fixed it by refreshing the slideshow right after initializing it, with $('mySlideshow').slick('refresh'); It quickly glitches on page loading, but it's better than having it offset before change.

Smile3D commented 5 years ago

Hi guys I have a problem with CenterMode

https://monosnap.com/file/0e0SWTDgUSaIbkKj8emNJ1cwoLBzOs This screen is on the MacBoock Safari with screen size 1280px - part of nex slide is visible but I dont need this

https://monosnap.com/file/yyDjCmGyiyU0jBloVcyGmlA25gQ47d On win chrome it is ok

js $('.rooms-slider').slick({ centerMode: true, dots: false, centerPadding: '50px', slidesToShow: 1, variableWidth: true, prevArrow: '.prev-slide', nextArrow: '.next-slide', responsive: [ { breakpoint: 769, settings: { dots: true, centerMode: false, variableWidth: false, centerPadding: '0px', } }, { breakpoint: 480, settings: { dots: true, } } ] });

css `.slide { @include animate(height);

    background-position: 50% 50%;
    background-size: cover;
    background-repeat: no-repeat;
    width: 320px;
    height: 500px;
    outline: none;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;

    @include media('>=375px') {
        width: 375px;
    }

    @include media('>=414px') {
        width: 414px;
    }

    @include media('>=768px') {
        width: 768px;
    }

    @include media('>=1024px') {
        width: 1024px;
    }

    @include media('>=1200px') {
        width: 1200px;
    }

    @include media('>=1280px') {
        width: 1280px;
    }

    @include media('>=1366px') {
        height: 600px;
        width: 700px;
        margin: 0 25px;
    }

    @include media('>=1920px') {
        width: 1260px;
    }`
KonstantinGreat commented 5 years ago

Had problems on safari iphone, fixed it by set centerPadding to 0

rafaelfndev commented 4 years ago

I fixed this by adding box-sizing border-box on slick-list:

.slick-list {
    box-sizing: border-box;
}
astralmaster commented 4 years ago

Two and a half years later, the bug still exists.

timbowen commented 4 years ago

Two and a half years later, the bug still exists.

centerPadding to 0 fixes it.

Arly0 commented 4 years ago

If you have centerMode: even number - try add centerPadding : '100px' and dont use variableWidth

KonstantinGreat commented 3 years ago

i decide same problem by centerPadding to 0 and zero padding to wrapper

dubbelgustaf commented 3 years ago

Also having troubling with centerMode and wrong margins. For me the problem appears when SlidesToShow is greater than actual "slides".

I dont know if youre experince the same kind of problem (im not using variableWidth) but this is how i did. It seems to work

$('.m-slider-list').each(function(item) {
    var sliderId = $(this).attr('data-slider-list-id');

    $('.m-slider-list[data-slider-list-id="'+sliderId+'"]').slick({
        slidesToShow: slidesToShow(sliderId, 5),
        slidesToScroll: 1,
        autoplay: true,
        autoplaySpeed: 10000,
        cssEase: 'ease-in-out',
        centerMode: true,
        prevArrow: '<div class="slick-prev"><i class="fa-thin fa-angle-left" aria-hidden="true"></i></div>',
        nextArrow: '<div class="slick-next"><i class="fa-thin fa-angle-right" aria-hidden="true"></i></div>',
        arrows: true,
        responsive: [
            {
                breakpoint: 1700,
                    settings: {
                           slidesToShow: slidesToShow(sliderId, 4),
                           slidesToScroll: 1
                    }
            },
            {
                breakpoint: 1500,
                settings: {
                    slidesToShow: slidesToShow(sliderId, 3),
                    slidesToScroll: 1
                }
            },
            {
                breakpoint: 1000,
                settings: {
                    slidesToShow: slidesToShow(sliderId, 2),
                    slidesToScroll: 1
                }
            },
            {
                breakpoint: 700,
                settings: {
                    slidesToShow: slidesToShow(sliderId, 1),
                    slidesToScroll: 1
                }
            },
        ]
    });
});

Heres the simple function for slidesToShow
function slidesToShow(sliderId, slidesToShowDefault) {
    var slidesToShow = slidesToShowDefault;
    var initSlidesToShow = $('.m-slider-list[data-slider-list-id="'+sliderId+'"]').find('.m-slider-list-item').length;
    if(initSlidesToShow < slidesToShow) {
        slidesToShow = initSlidesToShow;
    } else {
        slidesToShow = slidesToShowDefault;
    }
    return slidesToShow;
}
sefihanow commented 2 years ago

Had problems on safari iphone, fixed it by set centerPadding to 0

thank you mate, you fixed my problem on IOS mobile

ziruhel786 commented 2 years ago

It could happen IOS mobile if your wrapper has a negative margin. In my case my wrapper has

    margin-left: -30px;
    margin-right: -30px;

And it solved by adding centerPadding: '15px'

martin-merch commented 1 year ago

Setting background-position: center; on the slide class fixed it for me

Breeze8 commented 11 months ago

2023 year, 6 years this bug exist

AlexNik17 commented 9 months ago

This is common due to paddings. Remove paddings from slick-slide and add them for child elements.

fzn0x commented 5 months ago

Hi guys, the trick is using afterChange.

    const settings = {
        className: "center slider variable-width slick-gradient",
        centerMode: true,
        infinite: true,
        slidesToShow: 1,
        speed: 100,
        rows: 1,
        slidesPerRow: 1,
        arrows: false,
        centerPadding: "100px",
        beforeChange: (_oldIndex, newIndex) => {
            // ...
        },
        afterChange: (currentIndex) => {
            // Select the element with the class 'slick-track'
            var element = document.querySelector('.slick-track');

            // Get the current transform value
            var currentTransform = getComputedStyle(element).transform;

            // Extract the x translation value. The match function attempts to find the numbers in the matrix transform, which are separated by commas.
            // The matrix format is matrix(a, b, c, d, tx, ty) where tx is our x translation.
            // If the transform is in the translate3d format, it should still match correctly.
            var match = currentTransform.match(/matrix\(([^,]+),([^,]+),([^,]+),([^,]+),([^,]+)/);

            if (match) {
                var currentX = parseFloat(match[5]); // Get the x translation value

                // Calculate the new x value by adding 45
                var newX = currentX + 45;

                // Set the new transform value
                element.style.transform = 'translate3d(' + newX + 'px, 0px, 0px)';
            } else {
                console.log("Could not parse the current transform value.");
            }
        },
        variableWidth: true,
    };

Consider to follow me if this solves your issue. :D