Have you ever wanted to create a simple carousel in React.js? In that case, you are on the right place. In this easy tutorial, we will create a simple carousel you can then take and use anywhere you want and with any content you want. I tried to make this tutorial simple. So, even beginners and people wanting to learn React.js should be able to complete it. I hope this tutorial will help you learn about React.js and get started with it in an enjoyable way. Table of Contents: Briefing Workspace and HTML SASS Styling the carousel component and its content Styling carousel indicators Putting it together React.js Preparing carousel functionality From HTML to React Putting it together Closing thoughts on creating a simple carousel and learning React.js Demo on . Codepen Briefing Let’s start with briefly describing the goals for this React.js carousel tutorial. Our main goal is to create a simple carousel. This carousel will contain a number of slides, two directional arrows on its sides and finally an indicator (something like a dot) for each slide. User will be able to cycle through slides either by using arrows or by clicking on one of the indicators below the carousel. Also, when user reaches the last slide and click on “right” arrow, carousel will show the first slide. The same is true for situation when user is on the first slide and clicks on the “left” arrow. Carousel will show the last slide. In other words, user will be able to cycle through slides infinitely in both directions. In the beginning, I wanted to implement a functionality that would allow the carousel to cycle through slides automatically, in specific intervals. However, a lot of people don’t consider this to be a good practice in UX. And, I agree. Still, if you would like to have this functionality, you can take it as a challenge to test your skills. In the end, the best way to learn anything is by doing it. This is especially true about coding. So, take charge and put your new skills to the test. And, that being said, we can start.Workspace and HTML Workspace and HTML The first step is setting up our workspace. Then, we will put together the HTML code that is necessary for this carousel tutorial. Luckily, because we are working with React.js, that will be a one-liner. Anyway, back to the workspace. React.js requires two libraries in order to work as it should. These libraries are React and React-DOM. In this carousel tutorial, we will use to get both of them. These are all necessary assets we need to build our carousel. CDN Aside from these required assets, I also used some additional, mainly for styling purposes. These assets are web fonts and , both are available on Google Fonts. Next, I also used for directional arrow icons we are going to use in our carousel. Finally, I used so we can use the latest JavaScript syntax without worrying that something will not work. Also, working with React.js is easier when you use babel. Roboto Open Sans Font Awesome babel compiler The second step we will make is getting our HTML code ready. This will be very quick since the majority of our code will be in Reat.js (or JavaScript). All we need to do is prepare one div element. In the end, we will use this element as a “place” in DOM where we will render carousel React component. Let’s also give this div some class so we can find it easily, such as “carousel-container“. And, this is all for HTML. Code: <div class="carousel-container"></div> SASS The third step is adding some styles. Otherwise, our carousel will work, but its layout will be broken. As a result, it will be pretty much unusable. Meaning, all slides will be visible, stacked one under the other. Let’s start with the outer layer of our carousel and move to the center. First, let’s reset some default properties of element, such as padding, margin and . Then, we can continue by styling the “carousel-cotainer” , our only piece of HTML code. ul list-style-type div We will set its property to “flex”, to “column”, center the content and set . This is necessary if we want to prevent the arrows on sides from “jumping” up and down every time the next slide has a different height than the previous one. Otherwise, you can ignore these styles and move on to styling carousel itself. display flex-direction min-height Code: // SASS variable for media query breakpoint $breakpoint-desktop: 992px; // Resetting default styles ul { padding: 0; margin: 0; list-style-type: none; } // Fix for jumping arrows .carousel-container { display: flex; flex-direction: column; justify-content: center; min-height: 210px; } Styling the carousel component and its content Carousel itself needs only one line of CSS. We need to set its to “relative”. Then, we can move on and add some styles for slides. We will center all slides using , center the content using property, set some and set to “none”. Then, we will set to “block” for the slide that is currently active. I also added some on left and right for smaller screens so the arrows don’t overlap the text. position margin text-align max-width display display padding Next, we can add some styles for the content of our slides. In this tutorial, each slide will contain some short text, author of the text and its source. I chose Open Sans and bigger for the content, with small on the bottom, and Roboto and smaller for the author and source. When we are done with this, we can move on to directional arrows. font-size margin font-size We will set of both to “absolute”, to “block”, to “#111”, to “pointer” and to “.75”. Then, we will use combination of and properties to center them on the vertical axis. Next, we will remove on and increase the on . We can also use to make the change in opacity smoother. Finally, we will use (for left arrow) and (for right arrow) properties to position each arrow on horizontal axis. position display color cursor opacity top transform outline focus opacity hover transition left right Code: .carousel { position: relative; } // Carousel slides .carousel__slide { margin-right: auto; margin-left: auto; display: none; max-width: 900px; list-style-type: none; text-align: center; @media (max-width: 991px) { padding-right: 60px; padding-left: 60px; } &--active { display: block; } } // Content of slides .carousel-slide__content { margin-bottom: 19px; font-family: 'Open Sans', 'Trebuchet MS', sans-serif; font-size: 16px; @media (max-width: $breakpoint-desktop - 1px) { font-size: 18px; } } .carousel-slide__author, .carousel-slide__source { font-family: 'Roboto', arial, sans-serif; font-size: 14px; @media (min-width: $breakpoint-desktop) { font-size: 16px; } } .carousel-slide__source { font-style: italic; color: #888; } // Carousel arrows .carousel__arrow { position: absolute; top: 50%; display: block; color: #111; cursor: pointer; opacity: .75; transform: translateY(-50%); transition: opacity .15s cubic-bezier(.4, 0, 1, 1); &:focus { outline: 0; } &:hover { opacity: .5; } &--left { left: 32px; } &--right { right: 32px; } } Styling carousel indicators The last part of our carousel are indicators on the bottom. Instead of using dots, I decided to use subtle lines. These lines will be right under the slides and centered on the horizontal axis. We will use to achieve this. The of these lines will be “24px” while “3px”. We will set the property to “block” and set to “pointer”. The default of these lines will be “#111”, with set to “.15”. flexbox width height display cursor background-color opacity On the will increase to “.5”. And, we can again use to make this change smoother. Currently active line will have of “.75”, for both, state as well as . hover opacity transition opacity default hover Code: // Carousel indicators .carousel__indicators { display: flex; flex-direction: row; justify-content: center; margin-top: 20px; li { &:nth-of-type(n + 2) { margin-left: 9px; } } } .carousel__indicator { display: block; width: 24px; height: 3px; background-color: #111; cursor: pointer; opacity: .15; transition: opacity .15s cubic-bezier(.4, 0, 1, 1); &:hover { opacity: .5; } &--active { &, &:hover { opacity: .75; } } } Putting it together This is all we need when it comes to styling. Below is the whole content of our SASS stylesheet. Code: // SASS variable for media query breakpoint $breakpoint-desktop: 992px; // Resetting default styles ul { padding: 0; margin: 0; list-style-type: none; } // Fix for jumping arrows .carousel-container { display: flex; flex-direction: column; justify-content: center; min-height: 210px; } .carousel { position: relative; } // Carousel slides .carousel__slide { margin-right: auto; margin-left: auto; display: none; max-width: 900px; list-style-type: none; text-align: center; @media (max-width: 991px) { padding-right: 60px; padding-left: 60px; } &--active { display: block; } } // Content of slides .carousel-slide__content { margin-bottom: 19px; font-family: 'Open Sans', 'Trebuchet MS', sans-serif; font-size: 16px; @media (max-width: $breakpoint-desktop - 1px) { font-size: 18px; } } .carousel-slide__author, .carousel-slide__source { font-family: 'Roboto', arial, sans-serif; font-size: 14px; @media (min-width: $breakpoint-desktop) { font-size: 16px; } } .carousel-slide__source { font-style: italic; color: #888; } // Carousel arrows .carousel__arrow { position: absolute; top: 50%; display: block; color: #111; cursor: pointer; opacity: .75; transform: translateY(-50%); transition: opacity .15s cubic-bezier(.4, 0, 1, 1); &:focus { outline: 0; } &:hover { opacity: .5; } &--left { left: 32px; } &--right { right: 32px; } } // Carousel indicators .carousel__indicators { display: flex; flex-direction: row; justify-content: center; margin-top: 20px; li { &:nth-of-type(n + 2) { margin-left: 9px; } } } .carousel__indicator { display: block; width: 24px; height: 3px; background-color: #111; cursor: pointer; opacity: .15; transition: opacity .15s cubic-bezier(.4, 0, 1, 1); &:hover { opacity: .5; } &--active { &, &:hover { opacity: .75; } } } React.js We are in the final part of this tutorial. Now, our job is to create React component for our carousel and make it work, so to speak. I decided to write the whole carousel as one big component. However, be aware that this is not exactly the best practice. It is better to create small components and then use each individually as needed. For now, I decided to make it a little bit easier and faster. And, the truth is that I am not so good in React.js yet. You know, we all are learning. Preparing the workplace First, we will save from React and method from React-DOM into so we can use them quickly when we need. And, we can do the same with carousel container . Finally, we will create one more that will store the data for our carousel. We will use an with one object for every slide. Each will contain “content”, “author” and “source” with some random values. We will use these values to populate our slides with data. Component render consts div const array object keys Code: const { Component } = React; const { render } = ReactDOM; const carouselContainer = document.querySelector(".carousel-container"); // Data for carousel const carouselSlidesData = [ { content: "Tomorrow, you will be released. If you are bored of brawling with thieves and want to achieve something there is a rare blue flower that grows on the eastern slopes. Pick one of these flowers. If you can carry it to the top of the mountain, you may find what you were looking for in the first place.", author: "Bane", source: "facebook" }, { content: "You have learn to bury your guilt with anger. I will teach you to confront it and to face the truth.", author: "Ra's Al Ghul", source: "Snapchat" }, { content: "Introduce a little anarchy, upset the established order and everything becomes chaos. I'm an agent of chaos. Oh, and you know the thing about chaos? It's fair.", author: "Joker", source: "facebook" }, { content: "I can't do that as Bruce Wayne... as a man. I'm flesh and blood. I can be ignored, destroyed. But as a symbol, I can be incorruptible, I can be everlasting.", author: "Bruce Wayne", source: "facebook" }, { content: "But it's not who you are underneath... it's what you do that defines you.", author: "Rachel Dawes", source: "twitter" }, { content: "When their enemies were at the gates the Romans would suspend democracy and appoint one man to protect the city. It wasn't considered an honor, it was a public service.", author: "John Blake", source: "Google+" }, { content: "Master Wayne, you've been gone a long time. You look very fashionable. Apart from the mud.", author: "Alfred Pennyworth", source: "twitter" } ]; Preparing carousel functionality The next step is building the carousel. For this, we will create new “Carousel” that the React we store in . We will start with a constructor method that will contain and the of Carousel component. Inside it, we will define new “activeIndex” and set it to “0”. This is the index of active slide when carousel is loaded, or the first slide. class extends Component const super state key Next, we will create new “goToSlide” that takes “index” as a parameter. This method will access the of Carousel and change the of “activeIndex” to the of “index”. Then, we will create two more methods, and . We will use these methods when user clicks on one of the carousel arrows to either show the previous or next slide. These methods will look very similar. method state component value value goToPrevSlide() goToNextSlide() Both will load and store the value of “activeIndex” from Carousel state. Next, they will store the slides data from props and also the number of slides (the length of the slides array). The goToPrevSlide method will then check if the index (“activeIndex”) is smaller than 1. If so, then it will set the index to the index of the last slide (slidesLength). Otherwise, it will decrease the index by 1 and use it as a new value for “activeIndex” key inside Carousel state. The method will do the same thing, but with small differences and in the opposite direction. It will also load and store the of “activeIndex” from Carousel , just like method. And, it will store the slides data from props as well. However, it will not care about the last slide, but about the last but slide ( — 1). goToNextSlide() value state goToPrevSlide() slides.length Then, it will check if the (“activeIndex”) is equal to the value of const. If so, it will set the of the “index” to “-1” and load the first slide. Otherwise it will increase the of the by 1 and use it as a new value for “activeIndex” key inside Carousel state. index slidesLength value value index Code: // Carousel wrapper component class Carousel extends Component { constructor(props) { super(props); this.state = { activeIndex: 0 }; } goToSlide(index) { this.setState({ activeIndex: index }); } goToPrevSlide(e) { e.preventDefault(); let index = this.state.activeIndex; let { slides } = this.props; let slidesLength = slides.length; if (index < 1) { index = slidesLength; } --index; this.setState({ activeIndex: index }); } goToNextSlide(e) { e.preventDefault(); let index = this.state.activeIndex; let { slides } = this.props; let slidesLength = slides.length - 1; if (index === slidesLength) { index = -1; } ++index; this.setState({ activeIndex: index }); } } From HTML to React This is the final step. We will now create the structure for our carousel. We will wrap this code inside method. The structure is following: there will be one with class “carousel”. This will contain two elements (arrows) with one element in each (icons). Then, there will be one with class “carousel__slides”. This list will use method to cycle through slides data and generate one for each slide. Every will contain two elements, one for content and one from author and source. render() div anchor span unordered list map() array list item list item p Author will be wrapped inside strong element and source inside small. Slide that is currently active (its index is equal to ) will have “carousel__slide–active” class. Next, there will be one more at the bottom for carousel indicator, with class “carousel__indicators”. Here, we will again use method to through slides data . Now, each list item will contain one element with class “carousel__indicator”. Active indicator (its is equal to ) will have “carousel__indicator–active” class. this.state.activeIndex unordered list map() array anchor index this.state.activeIndex Now, we need to add functionalities to specific elements. In other words, click on the left arrow will trigger method while click on the right . Finally, click on any carousel indicator will trigger method. I almost forgot. This is the last step. We need to use method to render the Carousel component inside the “carousel-container” . One last thing we need to remember use the “carouselSlidesData” as a value for “slide” . goToPrevSlide() goToNextSlide() goToSlide() render() div prop Code: // Carousel wrapper component class Carousel extends Component { render() { return ( <div className="carousel"> <a href="#" className="carousel__arrow carousel__arrow--left" onClick={e => this.goToPrevSlide(e)} > <span className="fa fa-2x fa-angle-left" /> </a> <ul className="carousel__slides"> {this.props.slides.map((slide, index) => <li className={ index == this.state.activeIndex ? "carousel__slide carousel__slide--active" : "carousel__slide" } key={index} > <p className="carousel-slide__content">{slide.content}</p> <p> <strong className="carousel-slide__author"> {slide.author} </strong>, {" "}<small className="carousel-slide__source"> {slide.source} </small> </p> </li> )} </ul> <a href="#" className="carousel__arrow carousel__arrow--right" onClick={e => this.goToNextSlide(e)} > <span className="fa fa-2x fa-angle-right" /> </a> <ul className="carousel__indicators"> {this.props.slides.map((slide, index) => <li key={index}> <a className={ index == this.state.activeIndex ? "carousel__indicator carousel__indicator--active" : "carousel__indicator" } onClick={e => this.goToSlide(index)} /> </li> )} </ul> </div> ); } } // Render Carousel component render(<Carousel slides={carouselSlidesData} />, carouselContainer); Putting it together We have HTML container and we have styles. And now, we also have React component for our carousel. This is all we need to get our React carousel up and running. Below is the whole code we just discussed in one piece. Code: const { Component } = React; const { render } = ReactDOM; const carouselContainer = document.querySelector(".carousel-container"); // Data for carousel const carouselSlidesData = [ { content: "Tomorrow, you will be released. If you are bored of brawling with thieves and want to achieve something there is a rare blue flower that grows on the eastern slopes. Pick one of these flowers. If you can carry it to the top of the mountain, you may find what you were looking for in the first place.", author: "Bane", source: "facebook" }, { content: "You have learn to bury your guilt with anger. I will teach you to confront it and to face the truth.", author: "Ra's Al Ghul", source: "Snapchat" }, { content: "Introduce a little anarchy, upset the established order and everything becomes chaos. I'm an agent of chaos. Oh, and you know the thing about chaos? It's fair.", author: "Joker", source: "facebook" }, { content: "I can't do that as Bruce Wayne... as a man. I'm flesh and blood. I can be ignored, destroyed. But as a symbol, I can be incorruptible, I can be everlasting.", author: "Bruce Wayne", source: "facebook" }, { content: "But it's not who you are underneath... it's what you do that defines you.", author: "Rachel Dawes", source: "twitter" }, { content: "When their enemies were at the gates the Romans would suspend democracy and appoint one man to protect the city. It wasn't considered an honor, it was a public service.", author: "John Blake", source: "Google+" }, { content: "Master Wayne, you've been gone a long time. You look very fashionable. Apart from the mud.", author: "Alfred Pennyworth", source: "twitter" } ]; // Carousel wrapper component class Carousel extends Component { constructor(props) { super(props); this.state = { activeIndex: 0 }; } goToSlide(index) { this.setState({ activeIndex: index }); } goToPrevSlide(e) { e.preventDefault(); let index = this.state.activeIndex; let { slides } = this.props; let slidesLength = slides.length; if (index < 1) { index = slidesLength; } --index; this.setState({ activeIndex: index }); } goToNextSlide(e) { e.preventDefault(); let index = this.state.activeIndex; let { slides } = this.props; let slidesLength = slides.length - 1; if (index === slidesLength) { index = -1; } ++index; this.setState({ activeIndex: index }); } render() { return ( <div className="carousel"> <a href="#" className="carousel__arrow carousel__arrow--left" onClick={e => this.goToPrevSlide(e)} > <span className="fa fa-2x fa-angle-left" /> </a> <ul className="carousel__slides"> {this.props.slides.map((slide, index) => <li className={ index == this.state.activeIndex ? "carousel__slide carousel__slide--active" : "carousel__slide" } key={index} > <p className="carousel-slide__content">{slide.content}</p> <p> <strong className="carousel-slide__author"> {slide.author} </strong>, {" "}<small className="carousel-slide__source"> {slide.source} </small> </p> </li> )} </ul> <a href="#" className="carousel__arrow carousel__arrow--right" onClick={e => this.goToNextSlide(e)} > <span className="fa fa-2x fa-angle-right" /> </a> <ul className="carousel__indicators"> {this.props.slides.map((slide, index) => <li key={index}> <a className={ index == this.state.activeIndex ? "carousel__indicator carousel__indicator--active" : "carousel__indicator" } onClick={e => this.goToSlide(index)} /> </li> )} </ul> </div> ); } } // Render Carousel component render(<Carousel slides={carouselSlidesData} />, carouselContainer); Closing thoughts on creating a simple carousel and learning React.js Congratulations! You just built your own Carousel with React.js. I hope you enjoyed this tutorial and learned something or at least practiced what you already know. As I mentioned, I am still rather a beginner when it comes to React.js. So, if you find any mistake or way to improve the code, please share it in comment, tweet me or write a mail. Whatever you like. This will help improve this tutorial and make it more helpful. I am still learning React and this was my first attempt to use it for creating a carousel. I know that there are many things that can be done better. I promise that I will get back to this tutorial in the next few days, review it and do my best to improve it. Then, I will publish updated version with code that follows the best practices. For now, please be lenient. Thank you very much for your time. And, until next time, have a great day! . Did you like this article? Please subscribe Are you on social media? Let’s connect! You can find me on and . Twitter Dribbble Originally published at Alex Devero Blog .
Share Your Thoughts