akiran / react-slick

React carousel component
http://react-slick.neostack.com/
MIT License
11.77k stars 2.11k forks source link

slick-slide calculating width wrong #809

Closed lightninglu10 closed 6 years ago

lightninglu10 commented 7 years ago

Hey guys, react-slick is calculating the width of the slick-slide incorrectly. It's inside of a container with 1190px and I have slidesToShow: 5, and it's calculating the width as 268px per card when it should be 238px. Not sure what's going on here.

I'm on a screen size of 1440px and there's 50px of padding on slick-list so it looks like it's almost trying to get the full screen size?

Issue can be seen here: https://lunyr.github.io/Lunyr-Alpha/

lightninglu10 commented 7 years ago

update: it calculates the width wrong initially, but then if I resize the browser, the elements are the correct width.

Any idea what's going on?

lightninglu10 commented 7 years ago

Found the issue. I'm using an external library for styling called Aphrodite. It seems like it doesn't render the aphrodite CSS quickly enough for react-slick to pick up on the initial width.

So I set an initial width inline and now it works fine. This seems like a bug with react-slick.

KuriatoV commented 7 years ago

or just call resize before the render) but yes,its seems like a bug

lightninglu10 commented 7 years ago

How do you call resize before rendering?

On Jul 23, 2017, at 8:51 AM, Valentyn Kuriato notifications@github.com wrote:

or just call resize before the render) but yes,its seems like a bug

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or mute the thread.

KuriatoV commented 7 years ago

maybe not exactly before,but straight after in componentDidMount by using ref this.refs.[your ref name].onWindowResize()

jchapelle commented 7 years ago

I actually encountered exactly the same issue few hours ago ;-)

The answer of KuriatoV helped me a lot. Thanks to him ... You'll find a more precise answer below.

You just have to make sure that you pass down a prop to the slider in order to trigger the "componentWillReceiveProps" function

class Slider extends React.PureComponent {

  componentWillReceiveProps(){
    this.refs.slick.innerSlider.onWindowResized()
  }

  render () {

    var settings = {
      dots: false,
      infinite: true,
      speed: 100,
      slidesToShow: 1,
      slidesToScroll: 1,
      fade: true,
      lazyLoad: true,
      nextArrow: <NextArrow />,
      prevArrow: <PreviousArrow />,
    };
    return (
      <Slick ref="slick" {...settings}>
        {this.props.pictures.map((picture, index)=> <div key={index}> <Img picture={picture}></Img> </div>)}
      </Slick>
    );
  }
}
KuriatoV commented 7 years ago

nice one :)

iamcam commented 7 years ago

The solution here didn't quite work, but I was able to have the slider properly re-render using this method here in #299

via @omritoptix componentDidMount() { setTimeout(() => { window.dispatchEvent(new Event('resize')) }, 0); }

mikepii commented 7 years ago

I had this issue when using a "scale" css animation (in a modal) in Chrome. It calculates the initial size based on the pre-animation scale size. In a window resize event, it calculates the width of each item in the slider based on the currently scaled size during the animation.

sag1v commented 7 years ago

i'm facing the same (or related) issue, the slides are bigger than they should be but a window resize make them recalculate and display properly.

kv0906 commented 7 years ago

I'm facing this problem right now, the slide's width is not calculated until resize. I try many approaches above but no hope :/

sag1v commented 7 years ago

@kv0906 I'm using the componentDidMount life cycle method to dispatch the resize event but I'm doing it with setTimeout of 150 ms. you may need to play with the ms to get it right. it's a hack but that's the only thing working for me at the moment.

    componentDidMount() {
        setTimeout(() => { window.dispatchEvent(new Event('resize')); }, 150);
    }
a-eid commented 7 years ago

I am having the same issue ,non of the above solutions is working for me.

zachfeldman commented 7 years ago

My solution, for those that don't want to rely on setTimeouts or put the slider in another component:

componentDidMount() {

    $('img').on('load', ()=>{
      this.refs.slick.innerSlider.onWindowResized()
    })

  }

Note: you still have to have a ref to slick like in @jchapelle 's answer above

mbielkin commented 7 years ago

Issue is still actual. Updated my project to React v16 and react-slick to v0.15.4. Carousel now looks bad after dynamic changing of items because of incorrect width calculating. After emulating window resize event everything works fine.

componentDidUpdate() {
    window.dispatchEvent(new Event('resize'));
}
mmakarios commented 7 years ago

Best solution for me was using onLoad attribute on my img tags inside the slider.

<Slider>
  {images.map((image, index) => (
    <div key={index}>
      <img
        src={image.large_url}
        onLoad={() => window.dispatchEvent(new Event('resize'))}
      />
    </div>
  ))}
</Slider>
zeckdude commented 6 years ago

The answer from @mmakarios is by far the best! Thanks!

MetaLic commented 6 years ago

check the meta viewport tag in your html file, it should be <meta name="viewport" content="width=device-width, initial-scale=1">

laveesingh commented 6 years ago

https://github.com/akiran/react-slick/commit/8591dace983fa1bc103964459ab99eaa34eed8de solves the problem. Changes will be released soon.

zachfeldman commented 6 years ago

Very cool! Thank you @laveesingh

nickcobbett commented 6 years ago

i'm experiencing a similar issue where the carousel doesn't render on initial load, but if i navigate to a different page and then come back it renders. Is there an event I could dispatch other than resize that might handle that?

Gabriel-diez commented 6 years ago

Same problem as @nickcobbett , the width of slick-slide is set to 0. My slider contains images. Images are correctly load but their size is 0. If i refresh, the slider correcly appear. LazyLoad is set to false.

Firing resize event doesn't do anything. I tried to forceUpdate onLoad or after some seconds, but no success.

Any Idea on what could be the issue ?

Should i open a new issue @laveesingh ?

jesobreira commented 4 years ago

I'm having the same issue and the resizing events didn't work. What worked for me was manually setting the width on the style props.

CorySchulz commented 2 years ago

I had the same issue. I was applying a css transform to scale the panel before showing it in a modal panel. It was calculating the width of the image including the css scale transformation, which is not expected behavior.

I'm using Cash Dom as opposed to jQuery which is using the getBoundingClientRect value, which does not return the correct width of the .slick-list object. https://github.com/fabiospampinato/cash/blob/1c1b316e53cc3322e417a93a0e7c4745852796d0/src/dimensions/normal.ts#L32

Replacing these lines in the setDimensions function fixed the width calculations for me:

// _.listWidth = _.$list.width();
// _.listHeight = _.$list.height();
_.listWidth = _.$list[0].clientWidth;
_.listHeight = _.$list[0].clientHeight;
Screen Shot 2022-07-18 at 5 14 22 PM