{"id":5224,"date":"2021-06-08T02:00:00","date_gmt":"2021-06-08T00:00:00","guid":{"rendered":"https:\/\/alvarotrigo.com\/epa\/javascript-slider-how-to-make-one\/"},"modified":"2025-06-10T10:34:24","modified_gmt":"2025-06-10T08:34:24","slug":"javascript-slider-how-to-make-one","status":"publish","type":"post","link":"https:\/\/alvarotrigo.com\/blog\/javascript-slider-how-to-make-one\/","title":{"rendered":"JavaScript Image Slider [ How To Build One ]"},"content":{"rendered":"\n<p>How can you make a JavaScript image slider from the scratch? <strong>How do JavaScript image slideshows really work?<\/strong> Do we really need JavaScript for carousels nowadays? CSS has come a long way, and it&#8217;s actually possible to <a href=\"https:\/\/alvarotrigo.com\/fullPage\/blog\/create-a-slider-with-pure-CSS\/\">make a pretty decent slider with pure CSS<\/a>.<\/p>\n\n\n\n<p>However, you&#8217;re still very limited in what you can do with CSS alone, so if you want something more complex, you&#8217;ll need to build your image slider using JavaScript.<\/p>\n\n\n\n<p>But then your next question becomes, how to build one? Well fear not my friend, because <strong>by the end of this post you&#8217;ll know how to build an image slider in JavaScript -source code provided!-, including navigation buttons and breadcrumbs.<\/strong><\/p>\n\n\n\n<p>Let&#8217;s do it!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"create-the-structure-for-the-image-slider-with-html\">Create the Structure for The Image Slider with HTML<\/h2>\n\n\n\n<p>First, we&#8217;ll have to create the basic structure for the image slider. The html for our image slider will look like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"container\"<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"slider\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"slider__slides\"<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"slider__slide active\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"slider__slide\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"slider__slide\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"slider__slide\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>So, <code>container<\/code> is just the element that contains the future JavaScript images slideshow. This can be absolutely any part of your site, but I&#8217;ve just gone for a simple flexbox:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-class\">.container<\/span> {\n    <span class=\"hljs-attribute\">display<\/span>: flex;\n    <span class=\"hljs-attribute\">align-items<\/span>: center;\n    <span class=\"hljs-attribute\">justify-content<\/span>: center;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Next is the main <code>slider<\/code> element. This will hold the image slides and the navigation elements:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-class\">.slider<\/span> {\n    <span class=\"hljs-attribute\">display<\/span>: block;\n    <span class=\"hljs-attribute\">position<\/span>: relative;\n    <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">100%<\/span>;\n    <span class=\"hljs-attribute\">max-width<\/span>: <span class=\"hljs-number\">900px<\/span>;\n    <span class=\"hljs-attribute\">margin<\/span>: <span class=\"hljs-number\">10px<\/span>;\n    <span class=\"hljs-attribute\">background-color<\/span>: white;\n    <span class=\"hljs-attribute\">overflow<\/span>: hidden;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>You can adjust the size in any way that floats your boat &#8211; just make sure there&#8217;s a <code>position<\/code> property applied to it.<\/p>\n\n\n\n<p>We also have a container <code>div<\/code> for the slides, <code>slider__slides<\/code> and four <code>slider__slide<\/code> elements, which I&#8217;ve styled like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\">\n<span class=\"hljs-selector-class\">.slider__slides<\/span> {\n  <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">100%<\/span>;\n  <span class=\"hljs-attribute\">padding-top<\/span>: <span class=\"hljs-number\">66%<\/span>;\n}\n\n<span class=\"hljs-selector-class\">.slider__slide<\/span> {\n    <span class=\"hljs-attribute\">display<\/span>: flex;\n    <span class=\"hljs-attribute\">align-items<\/span>: center;\n    <span class=\"hljs-attribute\">justify-content<\/span>: center;\n    <span class=\"hljs-attribute\">font-size<\/span>: <span class=\"hljs-number\">50px<\/span>;\n    <span class=\"hljs-attribute\">font-weight<\/span>: bold;   \n    <span class=\"hljs-attribute\">position<\/span>: absolute;\n    <span class=\"hljs-attribute\">top<\/span>: <span class=\"hljs-number\">0<\/span>;\n    <span class=\"hljs-attribute\">left<\/span>: <span class=\"hljs-number\">0<\/span>;\n    <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">100%<\/span>;\n    <span class=\"hljs-attribute\">height<\/span>: <span class=\"hljs-number\">100%<\/span>;\n    <span class=\"hljs-attribute\">background-color<\/span>: lemonchiffon;\n    <span class=\"hljs-attribute\">transition<\/span>: <span class=\"hljs-number\">1s<\/span>;\n    <span class=\"hljs-attribute\">opacity<\/span>: <span class=\"hljs-number\">0<\/span>;\n}\n\n<span class=\"hljs-selector-class\">.slider__slide<\/span><span class=\"hljs-selector-class\">.active<\/span> {\n    <span class=\"hljs-attribute\">opacity<\/span>: <span class=\"hljs-number\">1<\/span>;\n}\n\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Now, here&#8217;s where it gets a little interesting. Setting <code>padding-top<\/code> to a percentage in <code>slider__slides<\/code> will maintain its aspect ratio.<\/p>\n\n\n\n<p>The the slides themselves are positioned absolutely, <code>top<\/code> and <code>left<\/code> are both <code>0<\/code>, while <code>width<\/code> and <code>height<\/code> are both <code>100%<\/code>.<\/p>\n\n\n\n<p>This means that each slide will completely fill the first parent element that has a <code>position<\/code> property applied to it (that&#8217;s why I said make sure you do that to the <code>slider<\/code> element).<\/p>\n\n\n\n<p>This <em>also<\/em> means that the four slides are stacked directly on top of each other. Notice that I&#8217;ve set the <code>opacity<\/code> of each slide to <code>0<\/code> &#8211; this makes them transparent. But the <code>.slider__slide.active<\/code> part means that any element which has <em>both<\/em> the <code>slider__slide<\/code> and <code>active<\/code> classes will have an opacity of <code>1<\/code> &#8211; making the active slide visible.<\/p>\n\n\n\n<p>Here&#8217;s what that gives us:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_gOxeGVP\" data-src=\"\/\/codepen.io\/anon\/embed\/gOxeGVP?height=450&amp;theme-id=1&amp;slug-hash=gOxeGVP&amp;default-tab=css,result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed gOxeGVP\" title=\"CodePen Embed gOxeGVP\" class=\"cp_embed_iframe lazyload\" style=\"width:100%;overflow:hidden\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" data-load-mode=\"1\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>As expected, we can only see slide 1 at the moment, with its pale yellow (<code>lemonchiffon<\/code>, to be precise) background. Now let&#8217;s add the images&#8230;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"putting-images-into-the-javascript-image-slideshows\">Putting Images into the JavaScript Image Slideshows<\/h2>\n\n\n\n<p>There are a few ways to make an image slider in JavaScript.<\/p>\n\n\n\n<p>One is to add the images using the css <code>background<\/code> property, and have a separate class for each image. Another way is to have just have one slide, and change it&#8217;s background image directly with JS.<\/p>\n\n\n\n<p>However, the approach we&#8217;ll take here is to use an <code>img<\/code> element inside each slide, like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"slider__slide active\"<\/span>&gt;<\/span>\n     <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"https:\/\/upload.wikimedia.org\/wikipedia\/commons\/thumb\/5\/56\/Shakuzoji_Kuginuki_Jizo-3586.jpg\/800px-Shakuzoji_Kuginuki_Jizo-3586.jpg\"<\/span> <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">\"A rooftop in Japan\"<\/span> \/&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>I&#8217;ve added one image for each slide, but we can still only see the first image, the one with the <code>active<\/code> class:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_KKvoXOX\" data-src=\"\/\/codepen.io\/anon\/embed\/KKvoXOX?height=450&amp;theme-id=1&amp;slug-hash=KKvoXOX&amp;default-tab=css,result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed KKvoXOX\" title=\"CodePen Embed KKvoXOX\" class=\"cp_embed_iframe lazyload\" style=\"width:100%;overflow:hidden\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" data-load-mode=\"1\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>So now let&#8217;s add the navigation elements so people can cycle through the images on the slider.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"add-forwards-and-backwards-buttons-to-the-javascript-image-slider\">Add Forwards and Backwards Buttons to the JavaScript Image Slider<\/h2>\n\n\n\n<p>Users look for navigation buttons at the far left and right edges of sliders &#8211; so that&#8217;s where we&#8217;ll put them!<\/p>\n\n\n\n<p>First let&#8217;s add these elements to the markup, inside <code>slider<\/code>, but below <code>slider__slides<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"container\"<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"slider\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"slider__slides\"<\/span>&gt;<\/span>\n      <span class=\"hljs-comment\">&lt;!-- our slides go here --&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"nav-button--prev\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"slider__nav-button\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"nav-button--next\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"slider__nav-button\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>As well as the <code>slider__nav-button<\/code> class, each button has a unique <code>id<\/code> &#8211; as we&#8217;re making our image slider using JavaScript, we&#8217;ll need these IDs so that we can select these elements within our JS code.<\/p>\n\n\n\n<p>You can style your buttons however you want, of course. Personally, I&#8217;m just gonna keep it simple with a grey box. Hey &#8211; sometimes the simple option is the best:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-class\">.slider__nav-button<\/span> {\n    <span class=\"hljs-attribute\">position<\/span>: absolute;\n    <span class=\"hljs-attribute\">height<\/span>: <span class=\"hljs-number\">70px<\/span>;\n    <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">70px<\/span>;\n    <span class=\"hljs-attribute\">background-color<\/span>: <span class=\"hljs-number\">#333<\/span>;\n    <span class=\"hljs-attribute\">opacity<\/span>: .<span class=\"hljs-number\">8<\/span>;\n    <span class=\"hljs-attribute\">cursor<\/span>: pointer;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>I&#8217;ve set <code>opacity<\/code> to <code>.8<\/code>, so the buttons will be a little transparent and won&#8217;t fully block whatever is behind them. And since we want these to be clickable we need <code>cursor: pointer<\/code> so that the user knows they can click it.<\/p>\n\n\n\n<p>Now, because these two buttons are at different sides of the slider, we&#8217;ll need to use slightly different CSS to position each one. We can use the <code>id<\/code>s for that:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-id\">#nav-button--prev<\/span> {\n    <span class=\"hljs-attribute\">top<\/span>: <span class=\"hljs-number\">50%<\/span>;\n    <span class=\"hljs-attribute\">left<\/span>: <span class=\"hljs-number\">0<\/span>;\n    <span class=\"hljs-attribute\">transform<\/span>: <span class=\"hljs-built_in\">translateY<\/span>(-<span class=\"hljs-number\">50%<\/span>);\n}\n\n<span class=\"hljs-selector-id\">#nav-button--next<\/span> {\n    <span class=\"hljs-attribute\">top<\/span>: <span class=\"hljs-number\">50%<\/span>;\n    <span class=\"hljs-attribute\">right<\/span>: <span class=\"hljs-number\">0<\/span>;\n    <span class=\"hljs-attribute\">transform<\/span>: <span class=\"hljs-built_in\">translateY<\/span>(-<span class=\"hljs-number\">50%<\/span>);\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Setting <code>top<\/code> to <code>50%<\/code> will put the <em>top<\/em> of the element halfway down the parent. So it won&#8217;t be perfectly centered vertically &#8211; it&#8217;ll be a little lower than it should be.<\/p>\n\n\n\n<p>The solution is to also add <code>transform: translateY(-50%);<\/code>. When you translate by a percentage, you move the element by a proportion of <em>its own size<\/em>. So <code>-50%<\/code> will perfectly center the button, not matter what its height happens to be. Pretty nice trick!<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"adding-arrows-to-the-navigation-buttons-with-css\">Adding Arrows To The Navigation Buttons With CSS<\/h3>\n\n\n\n<p>At the moment our navigation buttons are just grey boxes &#8211; we should indicate that these are buttons somehow. There are loads of ways of doing this &#8211; you could use an image of an arrow, an SVG, or even just write &#8220;Prev&#8221; and &#8220;Next&#8221;. But here&#8217;s another way:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-id\">#nav-button--prev<\/span><span class=\"hljs-selector-pseudo\">::after<\/span>,\n<span class=\"hljs-selector-id\">#nav-button--next<\/span><span class=\"hljs-selector-pseudo\">::after<\/span> {\n    <span class=\"hljs-attribute\">content<\/span>: <span class=\"hljs-string\">\"\"<\/span>;\n    <span class=\"hljs-attribute\">position<\/span>: absolute;\n    <span class=\"hljs-attribute\">border<\/span>: solid white;\n    <span class=\"hljs-attribute\">border-width<\/span>: <span class=\"hljs-number\">0<\/span> <span class=\"hljs-number\">4px<\/span> <span class=\"hljs-number\">4px<\/span> <span class=\"hljs-number\">0<\/span>;\n    <span class=\"hljs-attribute\">display<\/span>: inline-block;\n    <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">3px<\/span>;\n    <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">40%<\/span>;\n    <span class=\"hljs-attribute\">height<\/span>: <span class=\"hljs-number\">40%<\/span>;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This uses the <code>after<\/code> pseudoelement, which means we can add it to the JavaScript images slideshow without having to add anymore html. It creates a box with a solid white border along only its right and bottom edges.<\/p>\n\n\n\n<p>All we need to do now, is rotate the boxes so that the borders look like arrows, and use &#8216;translate&#8217; to make sure they&#8217;re centred within the button:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-id\">#nav-button--next<\/span><span class=\"hljs-selector-pseudo\">::after<\/span>{\n    <span class=\"hljs-attribute\">top<\/span>: <span class=\"hljs-number\">50%<\/span>;\n    <span class=\"hljs-attribute\">right<\/span>: <span class=\"hljs-number\">50%<\/span>;\n    <span class=\"hljs-attribute\">transform<\/span>: <span class=\"hljs-built_in\">translate<\/span>(<span class=\"hljs-number\">25%<\/span>, -<span class=\"hljs-number\">50%<\/span>) <span class=\"hljs-built_in\">rotate<\/span>(-<span class=\"hljs-number\">45deg<\/span>);\n}\n\n<span class=\"hljs-selector-id\">#nav-button--prev<\/span><span class=\"hljs-selector-pseudo\">::after<\/span> {\n    <span class=\"hljs-attribute\">top<\/span>: <span class=\"hljs-number\">50%<\/span>;\n    <span class=\"hljs-attribute\">right<\/span>: <span class=\"hljs-number\">50%<\/span>;\n    <span class=\"hljs-attribute\">transform<\/span>: <span class=\"hljs-built_in\">translate<\/span>(<span class=\"hljs-number\">75%<\/span>, -<span class=\"hljs-number\">50%<\/span>) <span class=\"hljs-built_in\">rotate<\/span>(<span class=\"hljs-number\">135deg<\/span>);\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>And let&#8217;s also add a media query to shrink these buttons a bit on smaller screens:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-keyword\">@media<\/span> screen <span class=\"hljs-keyword\">and<\/span> (<span class=\"hljs-attribute\">max-width:<\/span> <span class=\"hljs-number\">640px<\/span>) {\n  <span class=\"hljs-selector-class\">.slider__nav-button<\/span> {\n    <span class=\"hljs-attribute\">height<\/span>: <span class=\"hljs-number\">40px<\/span>;\n    <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">40px<\/span>;\n  }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>If we put all this togther, here&#8217;s what we get:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_xxLWXvM\" data-src=\"\/\/codepen.io\/anon\/embed\/xxLWXvM?height=450&amp;theme-id=1&amp;slug-hash=xxLWXvM&amp;default-tab=css,result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed xxLWXvM\" title=\"CodePen Embed xxLWXvM\" class=\"cp_embed_iframe lazyload\" style=\"width:100%;overflow:hidden\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" data-load-mode=\"1\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>Okay, it&#8217;s starting to look like a slider! Moving on&#8230;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"add-breadcrumbs-to-the-javascript-images-slideshow\">Add Breadcrumbs To The JavaScript Images Slideshow<\/h2>\n\n\n\n<p>Breadcrumbs (or navigation dots, bullets or whatever else you want to call them) are actually pretty easy to add. First let&#8217;s update our HTML once again:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"container\"<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"slider\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"slider__slides\"<\/span>&gt;<\/span>\n      <span class=\"hljs-comment\">&lt;!-- our slides go here --&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"nav-button--prev\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"slider__nav-button\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"nav-button--next\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"slider__nav-button\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"slider__nav\"<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"slider__navlink active\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"slider__navlink\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"slider__navlink\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"slider__navlink\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Now we have a <code>slider__nav<\/code> element, which contains four <code>slider__navlink<\/code> divs &#8211; one for each slide. The first one has an <code>active<\/code> class added to it also, which we can use to make the active breadcrumb stand out from the rest.<\/p>\n\n\n\n<p>Traditionally, breadcrumbs like these go at the bottom of a slider:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-class\">.slider__nav<\/span> {\n    <span class=\"hljs-attribute\">position<\/span>: absolute;\n    <span class=\"hljs-attribute\">bottom<\/span>: <span class=\"hljs-number\">3%<\/span>;\n    <span class=\"hljs-attribute\">left<\/span>: <span class=\"hljs-number\">50%<\/span>;\n    <span class=\"hljs-attribute\">transform<\/span>: <span class=\"hljs-built_in\">translateX<\/span>(-<span class=\"hljs-number\">50%<\/span>);\n    <span class=\"hljs-attribute\">text-align<\/span>: center;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>We&#8217;ve put the container for the breadcrumbs 3% away from the bottom of the image slider, and used the same centering trick we used with the buttons, only this time horizontally. Now for the breadcrumbs themselves:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-class\">.slider__navlink<\/span> {\n    <span class=\"hljs-attribute\">display<\/span>: inline-block;\n    <span class=\"hljs-attribute\">height<\/span>: <span class=\"hljs-number\">20px<\/span>;\n    <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">20px<\/span>;\n    <span class=\"hljs-attribute\">border-radius<\/span>: <span class=\"hljs-number\">50%<\/span>;\n    <span class=\"hljs-attribute\">border<\/span>: <span class=\"hljs-number\">1px<\/span> <span class=\"hljs-number\">#fff<\/span> solid;\n    <span class=\"hljs-attribute\">background-color<\/span>: <span class=\"hljs-number\">#333<\/span>;\n    <span class=\"hljs-attribute\">opacity<\/span>: .<span class=\"hljs-number\">8<\/span>;\n    <span class=\"hljs-attribute\">margin<\/span>: <span class=\"hljs-number\">0<\/span> <span class=\"hljs-number\">10px<\/span> <span class=\"hljs-number\">0<\/span> <span class=\"hljs-number\">10px<\/span>;\n    <span class=\"hljs-attribute\">cursor<\/span>: pointer;\n}\n\n<span class=\"hljs-selector-class\">.slider__navlink<\/span><span class=\"hljs-selector-class\">.active<\/span> {\n    <span class=\"hljs-attribute\">background-color<\/span>: <span class=\"hljs-number\">#fff<\/span>;\n    <span class=\"hljs-attribute\">border<\/span>: <span class=\"hljs-number\">1px<\/span> <span class=\"hljs-number\">#333<\/span> solid;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Pretty simple stuff here &#8211; just using <code>border-radius<\/code> to make them circles, and setting the background colour to white on the active slide. The rest are filled in with the same grey used in the buttons.<\/p>\n\n\n\n<p>Here&#8217;s what we get:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_bGrvYbq\" data-src=\"\/\/codepen.io\/anon\/embed\/bGrvYbq?height=450&amp;theme-id=1&amp;slug-hash=bGrvYbq&amp;default-tab=css,result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed bGrvYbq\" title=\"CodePen Embed bGrvYbq\" class=\"cp_embed_iframe lazyload\" style=\"width:100%;overflow:hidden\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" data-load-mode=\"1\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>We&#8217;re almost there &#8211; we just need to make these buttons actually do something! We&#8217;ll be using JavaScript for that.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"putting-the-javascript-into-the-image-slideshows\">Putting the JavaScript into the Image Slideshows<\/h2>\n\n\n\n<p>First, let&#8217;s make it easy to deal with our slides and breadcrumbs using JS:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">let<\/span> slides = <span class=\"hljs-built_in\">document<\/span>.getElementsByClassName(<span class=\"hljs-string\">\"slider__slide\"<\/span>);\n<span class=\"hljs-keyword\">let<\/span> navlinks = <span class=\"hljs-built_in\">document<\/span>.getElementsByClassName(<span class=\"hljs-string\">\"slider__navlink\"<\/span>);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The first line goes through our markup, finds every element called <code>slider__slide<\/code>, and stores a pointer to it in an array called <code>slides<\/code>. The next line does the same for our breadcrumb elements, this time putting them in an array called <code>navlinks<\/code>.<\/p>\n\n\n\n<p>We also need to keep track of which slide is currently active, so lets make a variable for that:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">let<\/span> currentSlide = <span class=\"hljs-number\">0<\/span>;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>I&#8217;ve set this to 0 because as you may know, in JavaScript arrays are indexed from 0, not 1. So our first slide is in <code>slides[0]<\/code>, the second is in <code>slides[1]<\/code>, and so on.<\/p>\n\n\n\n<p>Now we need to add event listeners to each of our buttons:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-built_in\">document<\/span>.getElementById(<span class=\"hljs-string\">\"nav-button--next\"<\/span>).addEventListener(<span class=\"hljs-string\">\"click\"<\/span>, () =&gt; {\n    changeSlide(currentSlide + <span class=\"hljs-number\">1<\/span>)\n});\n<span class=\"hljs-built_in\">document<\/span>.getElementById(<span class=\"hljs-string\">\"nav-button--prev\"<\/span>).addEventListener(<span class=\"hljs-string\">\"click\"<\/span>, () =&gt; {\n    changeSlide(currentSlide - <span class=\"hljs-number\">1<\/span>)\n});\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>When a user clicks one of these buttons, our image slider JavaScript source code will call a function called changeSlide (which we&#8217;ll create in a minute), and pass an argument &#8211; <code>currentSlide + 1<\/code> for the forwards button, and <code>currentSlide - 1<\/code> for the backwards one. That lets us know which slide the user is trying to move to, so we can put the <code>active<\/code> class onto that slide, and take it off of the current slide.<\/p>\n\n\n\n<p>As you can see here, I&#8217;ve wrapped the function call within an anonymous function &#8211; this is necessary when you want to pass an argument using an event listener. For example, this doesn&#8217;t work:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-built_in\">document<\/span>.getElementById(<span class=\"hljs-string\">\"nav-button--next\"<\/span>).addEventListener(<span class=\"hljs-string\">\"click\"<\/span>, changeSlide(currentSlide + <span class=\"hljs-number\">1<\/span>));\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>So that&#8217;s why you have to put the function call within the <code>() =&gt; { }<\/code> block.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"creating-the-javascript-function-that-will-change-the-slide\">Creating the JavaScript Function That Will Change The Slide<\/h3>\n\n\n\n<p>Here&#8217;s what the <code>changeSlide()<\/code> function looks like:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-19\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">changeSlide<\/span>(<span class=\"hljs-params\">moveTo<\/span>) <\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (moveTo &gt;= slides.length) {moveTo = <span class=\"hljs-number\">0<\/span>;}\n    <span class=\"hljs-keyword\">if<\/span> (moveTo &lt; <span class=\"hljs-number\">0<\/span>) {moveTo = slides.length - <span class=\"hljs-number\">1<\/span>;}\n    \n    slides&#91;currentSlide].classList.toggle(<span class=\"hljs-string\">\"active\"<\/span>);\n    navlinks&#91;currentSlide].classList.toggle(<span class=\"hljs-string\">\"active\"<\/span>);\n    slides&#91;moveTo].classList.toggle(<span class=\"hljs-string\">\"active\"<\/span>);\n    navlinks&#91;moveTo].classList.toggle(<span class=\"hljs-string\">\"active\"<\/span>);\n    \n    currentSlide = moveTo;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Let&#8217;s break this down step-by-step:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>changeSlide takes one argument, <code>moveTo<\/code>, which is the number of the slide you want to change to.<\/li>\n\n\n\n<li>The first line checks if <code>moveTo<\/code> is equal to or greater than <code>slides.length<\/code> &#8211; that would mean we&#8217;re on the final slide, and trying to move forward. In this case, we&#8217;ll set moveTo to 0 &#8211; which will take us back to the first slide.<\/li>\n\n\n\n<li>The next line does the same if the user tries to go <em>backwards<\/em> from the first slide &#8211; we&#8217;ll just loop them to the final slide<\/li>\n\n\n\n<li>The next four lines use the <code>slides<\/code> and <code>navlinks<\/code> arrays we created earlier. By using <code>classList.toggle(\"active\")<\/code>, our code will remove the <code>active<\/code> class from the current slide, and add it to the one we&#8217;re trying to move to.<\/li>\n\n\n\n<li>Finally, we set <code>currentSlide<\/code> to equal <code>moveTo<\/code>, since that&#8217;s the active slide now.<\/li>\n<\/ol>\n\n\n\n<p>As you might remember from earlier, we added <code>transition: 1s<\/code> to our <code>slider__slides<\/code> element. This means that the change in opacity that is triggered when we add or remove the <code>active<\/code> class take 1 second to complete &#8211; giving a nice fade-in effect.<\/p>\n\n\n\n<p>But before we look at the end result there&#8217;s just one more thing we need to do&#8230;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"making-the-breadcrumbs-clickable\">Making The Breadcrumbs Clickable<\/h3>\n\n\n\n<p><img decoding=\"async\" class=\"post-picture lazy\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP89B8AAukB8\/71MdcAAAAASUVORK5CYII=\" data-src=\"https:\/\/i.imgflip.com\/5bm6wt.jpg\" alt=\"Picture of Columbo advising you to make your breadcrumbs clickable\" width=\"500\" height=\"605\"><\/p>\n\n\n\n<p>Ever tried to click something, that you thought was clickable, but it turned out not to be clickable? Remember that feeling of disappointment that swelled up in your gut? Let&#8217;s not do that to our users! Let&#8217;s make it easy for them to jump from one slide to another by clicking the breadcrumbs:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-built_in\">document<\/span>.querySelectorAll(<span class=\"hljs-string\">'.slider__navlink'<\/span>).forEach(<span class=\"hljs-function\">(<span class=\"hljs-params\">bullet, bulletIndex<\/span>) =&gt;<\/span> {\n    bullet.addEventListener(<span class=\"hljs-string\">'click'<\/span>, () =&gt; {\n        <span class=\"hljs-keyword\">if<\/span> (currentSlide !== bulletIndex) {\n            changeSlide(bulletIndex);\n        }\n    })\n})\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Here we&#8217;ve used <code>querySelectorAll<\/code> to grab all of the <code>slider__navlink<\/code> elements, and then we&#8217;re using <code>forEach<\/code> to loop through them.<\/p>\n\n\n\n<p>So on the first loop, <code>bullet<\/code> will point to the first slide, and <code>bulletIndex<\/code> will equal 0.<br>\nOn the next loop, <code>bullet<\/code> will point to the second slide, and <code>bulletIndex<\/code> will equals 1.<br>\nAnd so on.<\/p>\n\n\n\n<p>The idea is, if they click a button, we know they want to change to slide <code>bulletIndex<\/code> &#8211; so we can just pass that value to our funtion with <code>changeSlide(bulletIndex)<\/code>.<\/p>\n\n\n\n<p>However, we&#8217;d better first check if they are already on slide <code>bulletIndex<\/code>. There&#8217;s no point fading out and then back in to the same slide. So the <code>if<\/code> statement ensures we&#8217;ll only call <code>changeSlide<\/code>, if <code>currentSlide<\/code> does not equal <code>bulletIndex<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"the-final-product\">The Final Product<\/h2>\n\n\n\n<p>OK we&#8217;re done! Below you can see what we ended up with.<\/p>\n\n\n\n<p>Can you guess which famous video game series these images are a tip of the hat to?<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>100 points if you can guess just from the first image<\/li>\n\n\n\n<li>75 points if you guess on the second image<\/li>\n\n\n\n<li>30 points if you get it on the third image<\/li>\n\n\n\n<li>10 points if you need all four images to figure it out<\/li>\n\n\n\n<li>0 points if you don&#8217;t know<\/li>\n<\/ul>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_abyYVoP\" data-src=\"\/\/codepen.io\/anon\/embed\/abyYVoP?height=450&amp;theme-id=1&amp;slug-hash=abyYVoP&amp;default-tab=css,result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed abyYVoP\" title=\"CodePen Embed abyYVoP\" class=\"cp_embed_iframe lazyload\" style=\"width:100%;overflow:hidden\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" data-load-mode=\"1\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>Of course, we&#8217;ve only scractched the surface of what&#8217;s possible when creating an image slider using JavaScript. You have a good framework here that you can experiment with. You can change the shape, style, and position of these elements however you need, and of course, you can play around with different transitions when moving between slides.<\/p>\n\n\n\n<p>But if you want to make something that&#8217;s not only visually slick but super-performant too, why reinvent the wheel? <a href=\"https:\/\/alvarotrigo.com\/fullPage\/\">Take a look at fullPage.js<\/a> and see if it&#8217;s the tool for you.<\/p>\n\n\n\n<p>As the name implies fullPage.js helps you create fullscreen scrolling websites. You get a range of different effects that will impress your visitors, it&#8217;s really easy to set up, and it works with other frameworks and CMSs including React and WordPress.<\/p>\n\n\n\n<p>Check it out!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"related-articles\">Related Articles<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/alvarotrigo.com\/blog\/create-a-slider-with-pure-CSS\/\">Create a Slider with pure CSS<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/alvarotrigo.com\/blog\/news-slider\/\">News Slider &#8211; Examples For Inspiration<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/alvarotrigo.com\/blog\/wordpress-slider-plugins\/\">Top 10 WordPress Slider Plugins<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/alvarotrigo.com\/blog\/what-is-a-slider\/\">What is a slider?<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>How can you make a JavaScript Image Slider from the scratch? How do slideshows really work? Do we really need JavaScript for carousels nowadays? CSS has come a long way, and it&#8217;s actually possible to<\/p>\n","protected":false},"author":6,"featured_media":5223,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[108],"tags":[9,10,43],"class_list":["post-5224","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-sliders","tag-css","tag-javascript","tag-slider"],"acf":[],"_links":{"self":[{"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/posts\/5224","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/comments?post=5224"}],"version-history":[{"count":4,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/posts\/5224\/revisions"}],"predecessor-version":[{"id":18866,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/posts\/5224\/revisions\/18866"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/media\/5223"}],"wp:attachment":[{"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/media?parent=5224"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/categories?post=5224"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/tags?post=5224"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}