Slick carousel - force slides to have the same height
Asked Answered
L

13

97

I'm having trouble with the Slick carousel JS plugin with multiple slidesToShow which have different heights.

I need the Slides to have the same height, but with CSS flex-box it doesn't work as the slides have conflicting CSS definitions.

Also, I didn't find anything useful in the forums and on the web.

HTML

<div class="slider">
  <div class="slide">
    <p>Lorem ipsum.</p>
  </div>
  <div class="slide">
    <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua</p>
  </div>
  <div class="slide">
    <p>At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
  </div>
  <div class="slide">
    <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr.</p>
  </div>
</div>

JS

$('.slider')
.slick({
    autoplay: false,
    dots: false,
    infinite: false,
    arrows: false,
    slidesToShow: 2,
    slidesToScroll: 2,
    rows: 0
});

CSS

.slide {
  height: 100%;
  background-color: #ccc;
  padding: 10px;
}
Lombardy answered 28/2, 2018 at 11:48 Comment(1)
Solution that is marked as correct won't work if "infinite" option is set to true.Pillar
H
255

Add a couple of CSS styles and it will be ready:

.slick-track
{
    display: flex !important;
}

.slick-slide
{
    height: inherit !important;
}

Enjoy! :-)

Haematoid answered 3/11, 2018 at 13:54 Comment(9)
Great! This code is working like a charm with the new version (1.9.0).Rheinland
Works great. I added some extra flex declarations for 2D centering of image of different sizes: .slick-track { display: flex !important; } .slick-slide { height: inherit !important; display: flex !important; justify-content: center; align-items: center; } Endow
This is a much simpler solution. I also had to add .slick-slide > div { height: 100%; } to account for the auto-generated div element.Postliminy
This is what everybody needs. +1Teleology
This is the exact solution I was looking for. Using the Slick JS params, does height animation transitions that are a no-go.Sessile
this is the CSS only solution to go, just in my case it didnt work with flex as i mentioned in the original postLombardy
In my case, there were two more divs between the track and slide class div. To make it work, I set height: 100% for them too, similar to what @Postliminy said :)Gingery
Why height: inherit works and not height: 100% I don't understand, but this is great.Incrassate
Why does height:inerhit only work when the parent is flex and not block?Aitch
L
33

Ok guys i found an easy solution. Just add a setPosition callback function (fires after position/size changes) which sets the height of the slides to the height of the slider (slideTrack):

JS

$('.slider').slick({
    autoplay: false,
    dots: false,
    infinite: false,
    arrows: false,
    slidesToShow: 2,
    slidesToScroll: 2,
  rows: 0
})
.on('setPosition', function (event, slick) {
    slick.$slides.css('height', slick.$slideTrack.height() + 'px');
});

Dont forget that your slides need to have full height:

CSS

.slide {
  height: 100%;
}

Here is a little jsFiddle to demonstrate: https://jsfiddle.net/JJaun/o29a4q45/

Lombardy answered 28/2, 2018 at 11:55 Comment(3)
I'm having a similar issue with a carousel. I tried to apply the setPosition fix to my script but it just breaks it. Can you see where I'm going wrong? codepen.io/moy/pen/KBZbZLIntarsia
You should update this answer to first set the $slides height to "auto" otherwise on resize your height measurements will be inaccurate since your $slideTrack height will be off because it's children $slides have a fixed pixel height.Rodger
You should update the answer to use slick.$slideTrack.find('.slick-slide') as cloned elements do not have the same height whilst transitioning.Cooperstein
C
12

The js solution from @JJaun is not perfect, because you see the height jumping if you use an background image for the slides. This worked for me:

.slick-track {
  display: flex !important;
}

.slick-slide {
  height: auto;
}
Cassiodorus answered 14/11, 2018 at 13:21 Comment(0)
R
6

As answered above.works fine on slick slider

.slick-track
{
    display: flex !important;
}

.slick-slide
{
    height: inherit !important;
}

but, i have an issue when using slick sync navigation

simple put below css to cover it.

.slick-slide {
    margin-bottom: 0;
    object-fit: cover;
}
Recept answered 25/3, 2021 at 5:4 Comment(0)
I
6

Solution on pure css

.slick-track {
    display: flex;
}

.slick-track .slick-slide {
    display: flex;
    height: auto;
}

.slick-slide img {
    height: 100%;
    object-fit: contain;
    object-position: center;
}
Immunoreaction answered 16/2, 2022 at 20:32 Comment(0)
H
3

Here's an SCSS-only solution if you're OK with using object-fit:

.slick {
  .slick-track {
    display: flex;

    .slick-slide {
      display: flex;
      height: auto;

      img {
        height: 100%;
        object-fit: cover;
        object-position: center;
      }
    }
  }
}
Hillhouse answered 18/4, 2019 at 11:53 Comment(0)
O
3
  1. .slick-track { display: flex; align-items: stretch; }

  2. .slick-slide { height: auto; flex: 1; }

  3. And, if you want to stick the last element in the bottom of the block, add display: flex for wrapper and margin-top: auto; to last element

Opalescent answered 6/5, 2021 at 8:1 Comment(0)
G
2

I've another css-only solution. you can override floated elements with table/table-cell.

$(function() {
  $('.slider')
    .slick({
      autoplay: false,
      dots: false,
      infinite: false,
      arrows: false,
      slidesToShow: 2,
      slidesToScroll: 2,
      rows: 0
    });
})
.slide {
  background-color: #ccc;
  padding: 10px;
  display: table-cell !important;
  float: none !important;
}

.slick-track {
  display: table !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick.min.js"></script>


<div class="slider">
  <div class="slide">
    <p>Lorem ipsum.</p>
  </div>
  <div class="slide">
    <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua</p>
  </div>
  <div class="slide">
    <p>At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
  </div>
  <div class="slide">
    <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr.</p>
  </div>
</div>
Guano answered 28/2, 2018 at 12:7 Comment(11)
in my actual usecase i have to build this in a finished bootstrap layout which i can not really change...here i have bootstrap columns with cards inside and those cards are not the same hight as the actual slides...something linke this jsfiddle.net/JJaun/o29a4q45/22 got an idea how to fix it?Lombardy
@JJaun, hımm nested elements, it's getting complicated with css. Than you should do it with your js way (calculating height), here is the updated one, jsfiddle.net/o29a4q45/43Guano
setting height of content triggers setPosition again. i've added a fix. check it again jsfiddle.net/o29a4q45/49Guano
yea i see, there is indeed no need to set the height on every setPosition event. thanks.Lombardy
@ocanal I tried to apply this to a problem I'm having but the code seems to break, can you see why? codepen.io/moy/pen/KBZbyLIntarsia
@user1406440, your codepen has js syntax error and missing slick reference file, here is the updated fiddle for your use case, jsfiddle.net/o29a4q45/128Guano
Doh! Sorry @ocanal, I posted that quickly before I went to bed. So it just looks like (when Slick was included) I just needed to remove the ; before the additional code? I realised I'd amended my markup sightly, I've got rid of the JS breaking but I don't get the 100% height - can you see why? codepen.io/moy/pen/mjXyPMIntarsia
@user1406440, i've changed resort to tile, and some minor fixes, updated one is here, codepen.io/anon/pen/QBQjWpGuano
Awesome, that's such a simple change to your first example - I'm clearing not thinking straight today! So all the markup/css was ok it was just the additional bit of js referencing slick-slide rather than resorts? Thanks again for your help!Intarsia
One last quick question actually, I've amended the code to slick.$slideTrack.height() - 30 + 'px' as I have a top/bottom margin on the track. Is that the best way or is there a height value that subtracts any margin from it? I know heightOuter etc but that's just for adding on padding.Intarsia
@Lombardy I'm unsure whether the JsFiddle is just old or whether the setPosition is buggy. I've tried implementing that code and played with the fiddle and found that if you were to include the dots or arrows and change slides with them, the height grows 5-10px on every click.Declared
B
2

For future searches:

You can simply use:

$('.slick').slick({ 
      /* your config */ 
 }).on('setPosition', function (event, slick) {
      slick.$slides.css('height', slick.$slideTrack.height() + 'px');
 });
Beaufert answered 7/10, 2020 at 3:48 Comment(0)
C
1

I've wrote a quick JS hack to make a gallery with different images heights to look a little neater.

It does the following:

  1. Get slider instance
  2. Find out it's height - images height will be set to that
  3. Get the src attr for each image and hide it
  4. Set src attr to image's parent as a background image together with some CSS.

    function equalizeImagesHeight(slider) {
        const slides = slider.find('.slick-slide');
        const imgHeight = $(slider)[0].clientHeight;
        slides.each(function(slide){
            const src = $(this).find('img').hide().attr('src');
            $(this).css({
                backgroundImage:'url('+src+')',
                minHeight: imgHeight,
                backgroundSize: "cover",
                backgroundPosition: "center"
            });
        });
    };
    

    equalizeImagesHeight($('.my-slider'));

Charity answered 5/7, 2018 at 15:6 Comment(0)
M
1

For me with latest version of slick in 2021 slick keep wrap my item's with additional div

So i do:

        .slick-track
        {
            display: flex !important;
            height: 100%;
        }

        .slick-slide
        {
            height: auto;

            .slick-slide> div
            {
                height: 100%;

                .myItemClass
                {
                    height: 100%;
                }
            }
        }
Misdeal answered 31/12, 2021 at 11:33 Comment(2)
you can just add {rows: 0} and it will not make an additional divLombardy
Good to know ill mind try it out next time ill use slick but still that can be usefull for someoneBefitting
S
0

Above suggestions didn't work for me. My slider images are al portrait but might have different h/w aspect ratios. I fixed it using js. Feels ugly though, wish I found something cleaner.

$carousel.on('setPosition', function (event, slick) {
      const $slideImages = slick.$slideTrack.find('.slick-slide-img');
      if($slideImages.first()[0].clientHeight >= $slideImages.first()[0].naturalHeight) return;
      $slideImages.height('auto');
      $slideImages.width('100%');
      const imgHeights = $slideImages.map(function(){
        return this.clientHeight;
      }).get();
      const maxHeight = Math.max.apply(null, imgHeights);
      $slideImages.height(maxHeight);
      $slideImages.width('auto');
    }

I had to use the setPosition event eventhough the code only needs to be executed once, after initialising slick. The init event doesn't work because the image heights on init are way off. Same for the first one or two setPosition events - hence the if($slideImages.first()[0].clientHeight >= $slideImages.first()[0].naturalHeight) return;.

Swound answered 24/8, 2020 at 13:14 Comment(0)
V
0

Here is a jQuery approach to make the slides equal in height.

$('.slick-elem').on('init reInit', function(event, slick, currentSlide, nextSlide) {

  setSlidesHeight(event);

});

function setSlidesHeight(event) {

  let $ = jQuery;
  let slickEl = $(event.target);
  let slidesEl = slickEl.find('.slick-slide');
  let maxHeight = -1;

  slidesEl.each(function(index, el) {

    maxHeight = maxHeight > $(el).height() ? maxHeight : $(el).height();

  });

  slidesEl.each(function(index, el) {

    $(el).height(maxHeight);

  });

}
Viceroy answered 14/2, 2023 at 18:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.