react-multi-carousel
Lightweight fully customizable React carousel component supports multiple items and SSR(Server-side rendering) with typescript.
The technical details of this carousel can be found at www.w3js.com -> react-multi-carousel.
NPM
NPM.
Bundle size
Bundle-size.
2.5kB
Demo.
Demo and documentation can be found at here.
Demo for the SSR are at here
Try to disable JavaScript to test if it renders on the server-side.
Codes for SSR at github.
Codes for the documentation at github.
Install
$ npm install react-multi-carousel --save
import Carousel from 'react-multi-carousel';
import 'react-multi-carousel/lib/styles.css';
Technical approach.
Detailed Can be found in this blog post at w3js.
How the SSR mode works?
The current most common solution is to detect the device type of the user based on the user agent. (server-side or client-side).
Based based on the device type, we decided how many items we are showing in the Carousel.
For example, we want to show 3 items at the same time on desktop (screen size 1024 - 2000px possibily) and 2 items on tablet(700px - 1024px) and 1 item on mobile. ---> this can be achieved through user-agent detection.
More detailed can be found in this blog post here.
Codes for SSR at github.
Demo for the SSR are at here Try to disable JavaScript to test if it renders on the server-side.
Features.
- Server-side rendering
- Infinite mode
- Custom animation
- AutoPlay mode
- Responsive
- Swipe to slide
- Mouse drag to slide
- Keyboard control to slide
- Multiple items
- Show / hide arrows
- Custom arrows / control buttons
- Custom dots
- Custom styling
- Accessibility support
Examples
const responsive = {
desktop: {
breakpoint: { max: 3000, min: 1024 },
items: 3
},
tablet: {
breakpoint: { max: 1024, min: 464 },
items: 2
},
mobile: {
breakpoint: { max: 464, min: 0 },
items: 1
}
};
<Carousel
disableSwipeOnMobile
disableDrag
shouldShowDots={true}
responsive={responsive}
forSSR
slidesToSlide={2}
infinite={true}
autoPlay={this.props.deviceType !== 'mobile' ? true : false}
autoPlaySpeed={1000}
keyBoardControl={true}
customTransition='all .5'
transitionDuration={500}
containerClassName='container-border-green'
removeArrowOnDeviceType={['tablet', 'mobile']}
deviceType={this.props.deviceType}
dotListClassName='custom-dot-list-style'
itemClassName='carousel-item-gutter-padding-left-40'
containerClassName='carousel-container-padding-bottom-80'
>
{fakerData.map(card => {
return <Card {...card} />;
})}
</Carousel>
Custom Arrows.
You can pass your own custom arrows to make it the way you want, the same for the position. For example, add media query for the arrows to go under when on smaller screens.
You custom arrows will receive a list of props/state that's passed back by the carousel such as the currentSide, is dragging or swiping in progress. An Example.
const CustomRightArrow = ({ onClick, ...rest }) => {
const { onMove, state: { currentSlide, deviceType } } = rest;
// onMove means if dragging or swiping in progress.
return <button onClick={() => onClick()} />
}
<Carousel customRightArrow={<CustomRightArrow />} />
Custom button group.
This is very useful if you don't want the dots, or arrows and you want to fully customize the control functionality and styling yourself.
const ButtonGroup = ({ next, previous, ...rest }) => {
const { state: { currentSlide } } = rest;
return (
<div className="carousel-button-group"> // remember to give it position:absolute
<ButtonOne className={currentSlide === 0 : 'disable' : ''} onClick={() => previous()} />
<ButtonTwo onClick={() => next()} />
</div>
);
};
<Carousel removeArrow customButtonGroup={<ButtonGroup />}>
<ItemOne>
<ItemTwo>
</Carousel>
Custom dots.
You can pass your own custom dots to replace the default one
You custom dots will receive a list of props/state that's passed back by the carousel such as the currentSide, is dragging or swiping in progress. An Example.
const CustomDot = ({ onClick, ...rest }) => {
const { onMove, index, state: { currentSlide, deviceType } } = rest;
// onMove means if dragging or swiping in progress.
return <button className={currentSlide === index ? 'active' : 'inactive'} onClick={() => onClick()} />
}
<Carousel shouldShowDots customDot={<CustomDot />} />
The items you passed as children.
All the items you passed as children will received a list of props/state of the current carousel that's passed back by the Carousel.
This is useful if you want to support accessibility or do your own stuff.
An Example.
Inspect the element in the chrome debugger.
const CarouselItem = ({ isvisible, currentSlide, onMove }) => {
return <div aria-hidden={isvisible ? 'false':'true'} className={isvisible? 'special style' : 'normal style'}></div>
}
<Carousel>
<CarouselItem />
<CarouselItem />
<CarouselItem />
</Carousel>
paritialVisibile props.
Shows the next / previous items paritially, this is very useful if you want to indicate to the users that this carousel component is swipable, has more items behind it.
paritialVisibile = 'right' means showing only next items paritially
paritialVisibile = {true} means showing both.
An Example.
const responsive = {
desktop: {
breakpoint: { max: 3000, min: 1024 },
items: 3,
paritialVisibilityGutter: 40 // this is needed to tell the amount of px that should be visible.
},
tablet: {
breakpoint: { max: 1024, min: 464 },
items: 2,
paritialVisibilityGutter: 30 // this is needed to tell the amount of px that should be visible.
},
mobile: {
breakpoint: { max: 464, min: 0 },
items: 1,
paritialVisibilityGutter: 30 // this is needed to tell the amount of px that should be visible.
}
}
<Carousel paritialVisibile='right' responsive={responsive}>
<ItemOne />
<ItemTwo />
</Carousel>
afterChanged call back.
This is a callback function that is invoked each time there has been a sliding.
An Example.
<Carousel afterChanged={(previousSlide, { currentSlide, onMove }) => {
doSpeicalThing()
}}>
</Carousel>
beforeChanged call back
This is a callback function that is invoked each time before a sliding.
An Example.
<Carousel beforeChanged={(nextSlide, { currentSlide, onMove }) => {
doSpeicalThing()
}}>
</Carousel>
Combine beforeChanged and nextChanged, real usage.
They are very useful in the following cases:
- The carousel item is clickable, but you don't want it to be clickable while the user is dragging it or swiping it.
<Carousel beforeChanged={() => this.setState({ isMoving: true })} afterChanged={() => this.setState({ isMoving: false })}>
<a onClick={(e) => {
if(this.state.isMoving) {
e.preventDefault()
}
}} href='https://w3js.com'>Click me</a>
</Carousel>
- Preparing for the next slide.
<Carousel beforeChanged={(nextSlide) => this.setState({ nextSlide: nextSlide })}>
<div>Initial slide</div>
<div onClick={() => {
if(this.state.nextSlide === 1) {
doVerySpecialThing();
}
}}>Second slide</div>
</Carousel>
General Props
responsive: responsiveType;
deviceType?: string;
forSSR?: boolean;
slidesToSlide: number;
disableDrag?: boolean;
removeArrow?: boolean;
disableSwipeOnMobile?: boolean;
removeArrowOnDeviceType?: string | Array<string>;
children: any;
customLeftArrow?: React.ReactElement<any> | null;
customRightArrow?: React.ReactElement<any> | null;
customDot?: React.ReactElement<any> | null;
customButtonGroup?: React.ReactElement<any> | null;
infinite?: boolean;
minimumTouchDrag: number; // default 50px. The amount of distance to drag / swipe in order to move to the next slide.
afterChanged?: (previousSlide: number, state: any) => void; // Change callback after sliding everytime. `(previousSlide, currentState) => ...`
beforeChanged?: (nextSlide: number, state: any) => void; // Change callback before sliding everytime. `(previousSlide, currentState) => ...`
contentClassName?: string; // Use this to style your own track list.
itemClassName?: string; // Use this to style your own Carousel item. For example add padding-left and padding-right
containerClassName?: string; // Use this to style the whole container. For example add padding to allow the "dots" or "arrows" to go to other places without being overflown.
dotListClassName?: string; // Use this to style the dot list.
keyBoardControl?: boolean;
autoPlay?: boolean;
autoPlaySpeed?: number; // default 3000ms
shouldShowDots?: boolean;
// Show next/previous item partially, if its right, only show the next item partially, else show both
// partialVisbile has to be used in conjunction with the responsive props, details are in documentation.
partialVisbile?: "right" | boolean;
customTransition?: string;
transitionDuration?: number;
// if you are using customTransition, make sure to put the duration here.
// for example, customTransition="all .5" then put transitionDuration as 500.
// this is needed for the resizing to work.
Specific Props
Name | Type | Default | Description |
---|
responsive | Object | {} | How many items to show on each breakpoint. |
deviceType | string | none | Only pass this when use for server-side rendering, what to pass can be found in the example folder. |
forSSR | bool | false | For SSR |
slidesToSlide | number | 1 | How many slides to slide. |
Contribute
Submit an issue for feature request or submit a pr.