Creating an image slider in the WordPress Gutenberg editor is an excellent way to add visual interest and engagement to your WordPress content (posts and pages). Unfortunately, by default, WordPress has no built-in tools to create an image slider. While many plugins, such as Elementor and Divi, can help you create the image sliders, it is also possible to make the image slider without the help of any third-party Gutenberg plugins. This post will walk you through the process of making a basic image slider in Gutenberg without the need for plugins.

How to Create the Image Slider in Gutenberg (Without Plugin)
In Gutenberg, the image slider can be made in two ways: Using the Cover block and the Gallery block. Both approaches have advantages and disadvantages.
Here is a brief comparison of them:
- The Cover block allows you to add an image with a title and a text overlay. You can also adjust the opacity, color, and gradient of the overlay. You can use reusable blocks to create multiple cover blocks with different images, and then use the Columns block to arrange them horizontally.
- The Gallery block allows you to add multiple images in a grid layout. You can also adjust the number of columns, the cropping, and the link settings of the images.
Method One: Create an Image Slider Using a Cover Block
Add the Code Snippet to the functions.php File
First, we will add the PHP snippet to the functions.php file.
On your WordPress dashboard, go to Appearance > Theme File Editor. You can find Theme File Editor under the Tools menu if you’re using a block theme.
Once you enter the Theme File Editor page, select the functions.php file. Afterward, paste the PHP snippet below at the end of the function file content. Next, update the theme file by clicking the Update File button.
/* * [slider height="475px" source="slider"]*/ add_shortcode( 'slider', 'slider_func' ); function slider_func( $atts ) { $atts = shortcode_atts( array( 'height' => '475px', 'source' => 'slider', ), $atts, 'slider' ); static $asearch_first_call = 1; $source = $atts["source"]; $height = $atts["height"]; $style0 = '<style> #prev{ left:0; border-radius: 0 10px 10px 0; } #next{ right:0; border-radius:10px 0 0 10px; } #prev svg,#next svg{ width:100%; fill: #fff; } #prev:hover, #next:hover{ background-color: rgba(0, 0, 0, 0.8); } </style> '; $js0 = <<<EOD <script> const arrowHtml = '<span class="icon-arrow_back" id="prev"></span><span class="icon-arrow_forward" id="next"></span>' let arrowIconLeft = '<?xml version="1.0" ?><!DOCTYPE svg PUBLIC \'-//W3C//DTD SVG 1.1//EN\' \'https://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\'><svg height="50px" id="Layer_1" style="enable-background:new 0 0 50 50;" version="1.1" viewBox="0 0 512 512" width="50px" color="#fff" xml:space="preserve" xmlns="https://www.w3.org/2000/svg" xmlns:xlink="https://www.w3.org/1999/xlink"><polygon points="352,115.4 331.3,96 160,256 331.3,416 352,396.7 201.5,256 "/></svg>'; </script> EOD; $style = '<style> .'.$source.'{ position: relative; overflow: hidden; width: 100%!important; height: '.$height.'; padding: 0px!important; } .'.$source.' > div { width: 100%!important; position: absolute; transition: all 1s; height: '.$height.'; margin: 0px!important; } .'.$source.' > div { height: '.$height.'; } .'.$source.' > span{ height: 50px; position: absolute; top:50%; margin:-25px 0 0 0; background-color: rgba(0, 0, 0, 0.4); color:#fff; line-height: 50px; text-align: center; cursor: pointer; } </style>'; $js = <<<EOD <script> document.querySelector('.$source').innerHTML += arrowHtml; let slides$source = document.querySelectorAll('.$source > div'); let slideSayisi$source = slides$source.length; let prev$source = document.querySelector('.$source #prev'); let next$source = document.querySelector('.$source #next'); prev$source.innerHTML = arrowIconLeft; next$source.innerHTML = arrowIconLeft; next$source.querySelector('svg').style.transform = 'rotate(180deg)'; for (let index = 0; index < slides{$source}.length; index++) { const element{$source} = slides{$source}[index]; element{$source}.style.transform = "translateX("+100*(index)+"%)"; } let loop{$source} = 0 + 1000*slideSayisi{$source}; function goNext{$source}(){ loop{$source}++; for (let index = 0; index < slides{$source}.length; index++) { const element{$source} = slides{$source}[index]; element{$source}.style.transform = "translateX("+100*(index-loop{$source}%slideSayisi{$source})+"%)"; } } function goPrev{$source}(){ loop{$source}--; for (let index = 0; index < slides{$source}.length; index++) { const element{$source} = slides{$source}[index]; element{$source}.style.transform = "translateX("+100*(index-loop{$source}%slideSayisi{$source})+"%)"; } } next{$source}.addEventListener('click',goNext{$source}); prev{$source}.addEventListener('click',goPrev{$source}); document.addEventListener('keydown',function(e){ if(e.code === 'ArrowRight'){ goNext{$source}(); }else if(e.code === 'ArrowLeft'){ goPrev{$source}(); } }); </script> EOD; if ( $asearch_first_call == 1 ){ $asearch_first_call++; return "{$style0}{$style}{$js0}{$js}"; } elseif ( $asearch_first_call > 1 ) { $asearch_first_call++; return "{$style}{$js}"; }}
Note: If you are afraid of breaking your site after adding the new function to the functions.php file, you can create a child theme or custom plugin. Read here to learn more.

Add the Cover Block
Next, we’re going to add some Cover blocks to the content (page/post). The number of blocks depends on how many slides you want to create; it should be more than one and unlimited for their numbers.
Afterward, insert the images for each block and tweak and style up your blocks with your preference, such as adding the text and buttons, adjusting the overlay opacity, etc.

Make all Cover Blocks in One Group.
Once you add the cover blocks, we will group them.
Click the Document Overview button, then select all the Cover blocks. Next, click the three-dot button (⋮) and select Group.

Add the Additional CSS Class
Once you group all the Cover blocks, please add a class.
On the Group block settings, navigate to Advanced -> ADDITIONAL CSS CLASS(ES). Afterward, add the slider
CSS class name to the ADDITIONAL CSS (ES) input field.

Add the Shortcode
Next, we will add the Shortcode block to the content area. You can place the Shortcode under the Group block.
Once you add the Shortcode block, please copy the code below and paste it into the available field.
[slider height="475px" source="slider"]

To see the result, you can preview your page by clicking the Preview button.

Note: The slider height in this example is 475 pixels. By changing the value on the PHP snippet and shortcode above, you can adjust the slider’s size to your preference.

Method Two: Create an Image Slider Using Gallery Block
This method turns the Gallery block into an image slider. You can add more than one slide to each page using this easier method than the previous one.
Add the Code Snippet to the functions.php File
As with the previous method, the first thing you must do is add a code snippet to the function.php file.
On your WordPress dashboard, go to Appearance > Theme File Editor. You can find Theme File Editor under the Tools menu if you’re using a block theme.
Once you enter the Theme File Editor page, select the functions.php file. Afterward, paste the PHP snippet below at the end of the function file content. Next, update the theme file by clicking the Update File button.
/** Turns Gallery block into image slider */ add_filter( 'wp_footer', function ( ) { ?> <script> document.querySelectorAll(".gallery-block-slider")?.forEach( slider => { var src = []; var alt = []; var img = slider.querySelectorAll("img"); img.forEach( e => { src.push(e.src); if (e.alt) { alt.push(e.alt); } else { alt.push("image"); } }) let i = 0; let image = ""; let myDot = ""; src.forEach ( e => { image = image + `<div class="wpcookie-slide" > <img decoding="async" loading="lazy" src="${src[i]}" alt="${alt[i]}" > </div>`; i++ }) i = 0; src.forEach ( e => { myDot = myDot + `<span class="wp-dot"></span>`; i++ }) let dotDisply = "none"; if (slider.classList.contains("dot")) dotDisply = "block"; const main = `<div class="gallery-block-slider">${image}<span class="wpcookie-controls wpcookie-left-arrow" > <svg xmlns="https://www.w3.org/2000/svg" xml:space="preserve" width="35" height="35" color="#fff" style="enable-background:new 0 0 50 50" viewBox="0 0 512 512"><path d="M352 115.4 331.3 96 160 256l171.3 160 20.7-19.3L201.5 256z"/></svg> </span> <span class="wpcookie-controls wpcookie-right-arrow" > <svg xmlns="https://www.w3.org/2000/svg" xml:space="preserve" width="35" height="35" color="#fff" style="enable-background:new 0 0 50 50" viewBox="0 0 512 512"><path d="M180.7 96 352 256 180.7 416 160 396.7 310.5 256 160 115.4z"/></svg> </span> <div class="dots-con" style="display: ${dotDisply}"> ${myDot}</div></div> ` slider.insertAdjacentHTML("afterend",main ); slider.remove(); }) document.querySelectorAll(".gallery-block-slider")?.forEach( slider => { var slides = slider.querySelectorAll(".wpcookie-slide"); var dots = slider.querySelectorAll(".wp-dot"); var index = 0; slider.addEventListener("click", e => {if(e.target.classList.contains("wpcookie-left-arrow")) { prevSlide(-1)} } ) slider.addEventListener("click", e => {if(e.target.classList.contains("wpcookie-right-arrow")) { nextSlide(1)} } ) function prevSlide(n){ index+=n; console.log("prevSlide is called"); changeSlide(); } function nextSlide(n){ index+=n; changeSlide(); } changeSlide(); function changeSlide(){ if(index>slides.length-1) index=0; if(index<0) index=slides.length-1; for(let i=0;i<slides.length;i++){ slides[i].style.display = "none"; dots[i].classList.remove("wpcookie-slider-active"); } slides[index].style.display = "block"; dots[index].classList.add("wpcookie-slider-active"); } } ) </script> <style> gallery-block-slider * { padding = 0; margin = 0; } .gallery-block-slider{ margin:0 auto; position:relative; overflow:hidden; } .wpcookie-slide{ max-height: 100%; width:100%; display:none; animation-name:fade; animation-duration:1s; } .wpcookie-slide img{ width:100%; } @keyframes fade{ from{opacity:0.5;} to{opacity:1;} } .wpcookie-controls{ position:absolute; top:50%; font-size:1.5em; padding:15px 10px; border-radius:5px; background:white; cursor: pointer; transition: 0.3s all ease; opacity: 15%; transform: translateY(-50%); } .wpcookie-controls:hover{ opacity: 60%; } .wpcookie-left-arrow{ left:0px; border-radius: 0px 5px 5px 0px; } .wpcookie-right-arrow{ right:0px; border-radius: 5px 0px 0px 5px; } .gallery-block-slider svg { pointer-events: none; } .dots-con{ text-align:center; } .wp-dot{ display:inline-block; background:#c4c4c4; padding:8px; border-radius:50%; margin:10px 5px; } .wpcookie-slider-active{ background:#818181; } @media (max-width:576px){ .gallery-block-slider{width:100%; } .wpcookie-controls{ font-size:1em; position: absolute; display: flex; align-items: center; } .dots-con{ display:none; } } </style> <?php });
Add the Gallery Block
Open the WordPress editor in Gutenberg, then add a Gallery block to the content section. Afterward, add the images by uploading new ones or selecting from your library.

Add the Additional CSS Class
Next, we will add the CSS class to the Gallery block.
On the Group block settings, navigate to Advanced -> ADDITIONAL CSS CLASS(ES). Afterward, add the gallery-block-slider
and dot
CSS class names to the ADDITIONAL CSS (ES) input field.

That’s it. Preview your page to see the result.

The Bottom Line
This article shows how easily you can make the image slider in the WordPress Gutenberg editor using two methods. which, in both methods, doesn’t require the help of any WordPress plugin. Depending on your needs and preferences, you can choose the method that suits you best.