You are currently viewing Panorama Slider Carousel –  Elementor SwiperJS Slider Tutorial

Panorama Slider Carousel – Elementor SwiperJS Slider Tutorial

(This page includes affiliate links. If you click and purchase, I receive a small commission at no extra cost from you and that way you can support me. I only recommend tools that I have personally used and loved.)

Don’t want to make from scratch? Get the template instead 🙂

Introduction – Making Panorama Slider Carousel with Elementor and SwiperJS 

In this tutorial, we will create a custom swiperjs slider with panorama effect. If you have solid background then you can do it with Elementor’s carousel widget without any extra code. Watch the tutorial to find out how.

Layout for containers or DIV: 

Swiperjs layout in elementor

Start Earning by becoming an Elementor Affiliate

Please watch the video for panoramic slider. If you have solid background color then there is easier way to make it. If you are using gradient, image, video, then it's better to use this slider. InitialSlide in code is set to 1. If your slider does not show first slide in center, make initialslide:0 in the code. Also make sure to upload the svg mask provided in download and change the url in code so that it uses mask from your storage.
(video tutorial available on youtube)

 Panorama Slider Code

  1. .dm-panorama-swiper is the CSS class for the main container that has all the slides, navigation, and pagination.
  2.  Although we have used swiperjs’s provided nextEl and prevEl for the next/previous buttons, we cannot use them. As in this version, I have used a panorama shape mask which cuts out anything outside the slider. So if you want the next/previous button overlayed on your slider, then use nextEl and prevEl buttons. If you want the buttons to be outside the slider, then we can use custom element for previous/next slide effect.
  3. .dm-panorama-swiper-custom-prev is the CSS class of element for the custom prev slide effect.
  4. .dm-panorama-swiper-custom-next is the CSS class of element for the custom next slide effect.
  5. We are using centeredSlides for this and when using with loop:true, the slide does not start with first slide, so line 21, I have set initialSlide = 1 (by default it is set to 0). This is important for centeredSlides so that it starts with first slide in center. If you don’t want centerSlides, please remove initialSlide and centerSlides code or set it to false and 0.
  6. direction allows you to choose between horizontal and vertical direction for your slider.
  7. loop can be set to true/false to enable or disable looping.
  8. slidesPerView is set to auto, so to set our desired slides go to line 96  – width: calc((100% – 200px) / 3); Here the 200px is used to show previous and next slide a bit (100px from left slide and 100px from right slide). Change the /3 to the number of slides you want to show. If you make 200px to 0px, it would not having any offset slides on both sides.
  9. To add more features, refer to the “Custom Carousel” blog post or its video to learn how to customize further. Link – https://dmmotionarts.com/custom-base-slider-with-autoplay-elementor-swiperjs-slider-tutorial/
  10. wrapperClass is used to use custom CSS class for our swiper-wrapper. This is important as we don’t want elementor swiper styling to be applied here.
  11. slideClass is used to use custom CSS class for our slides. Important for the same reason as above.
  12. nextEl and prevEl is the CSS class that we use for navigation buttons. It can be added to any icon, image or text.
  13. In pagination, el: allows us to specify which container/div is our pagination container.
  14. We have different pagination types available. You can read or watch video on “Custom Carousel Blog Post” page.
  15. Important: from line 189, change mask url to your panorama svg. You can download the template and it comes with the svg file or you can make one yourself in any vector software. Just make sure to edit your svg (open with notepad) and add preserveAspectRatio=”none”, fastest way is to ask chatGPT to allow the svg to stretch without keeping the aspect ratio.
				
					<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/11.0.5/swiper-bundle.css" integrity="sha512-pmAAV1X4Nh5jA9m+jcvwJXFQvCBi3T17aZ1KWkqXr7g/O2YMvO8rfaa5ETWDuBvRq6fbDjlw4jHL44jNTScaKg==" crossorigin="anonymous" referrerpolicy="no-referrer" />

<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/11.0.5/swiper-bundle.min.js" integrity="sha512-Ysw1DcK1P+uYLqprEAzNQJP+J4hTx4t/3X2nbVwszao8wD+9afLjBQYjz7Uk4ADP+Er++mJoScI42ueGtQOzEA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>


<script>

window.addEventListener("load", (event) => {
      
    const swiper = new Swiper('.dm-panorama-swiper', {
      // Optional parameters
      direction: 'horizontal',
      loop: true,
      grabCursor: true,
      mousewheel:false,
      centeredSlides:true,
      initialSlide: 1,
      freeMode:false,
      slidesPerView:'auto',
    
      // Wrapper and slide class
      wrapperClass: 'dm-panorama-swiper-wrapper',
      slideClass: 'dm-panorama-swiper-slide', 
    
    navigation: {
    nextEl: ".dm-panorama-swiper-next",
    prevEl: ".dm-panorama-swiper-prev",
  },
  pagination: {
    el: ".dm-panorama-swiper-pagination",
    // type: "fraction",
    // type: "progressbar",
    bulletClass: "dm-panorama-bullet",
    bulletActiveClass: "dm-panorama-bullet-active",
    clickable: true,
    
    
  },
  
  
   breakpoints: {
       
       1024: {
           
           spaceBetween: 20,
       },
       
        767: {
            
          spaceBetween: 20,
        },
        
        0: {
            
          spaceBetween: 20,
          
        },
      },
  
    });
    

    
 });    
    
    
    
</script>

<style>

.dm-panorama-swiper {
    
    overflow-x:clip;
}

/*offset next and previous slide*/

/*200px means 100px from left and 100px from right is visible, /3 means 3 slides should be shown fully*/

.dm-panorama-swiper-slide {
    
    width: calc((100% - 200px) / 3);
    
}

/*Tablet Slide*/

@media(max-width:1024px) {
    
   .dm-panorama-swiper-slide {
    
    width: calc((100% - 200px) / 2);
    
} 
    
}

/*Mobile Slide*/

@media(max-width:767px) {
    
   .dm-panorama-swiper-slide {
    
    width: calc((100% - 80px) / 1);
    
} 
    
}


.dm-panorama-swiper-wrapper .e-con.e-flex{
        
        flex-shrink: 0 !important;
}
    
    

    
/*Show cursor pointer on arrows*/
    
    .dm-panorama-swiper-next,
    .dm-panorama-swiper-prev {
        
        cursor:pointer;
        
    }

   
   
/*Pagination Container Size*/

/*Remove for progressbar type*/
    
    .dm-panorama-swiper-pagination {
        
       width:fit-content !important
    }
    
    /*For mobile*/
    
    @media(max-width:767px) {
        
    .dm-panorama-swiper-pagination {
        
       width:fit-content !important;
    }
        
        
    }

/*For Bullet Pagination*/
   
   .dm-panorama-bullet {
       
       position:relative;
       width:8px;
       height: 8px;
       aspect-ratio: 1;
       background:black;
       border-radius:100px;
       cursor:pointer;
       
       opacity: 0.2;
       
   }
   
   .dm-panorama-bullet.dm-panorama-bullet-active {
       
       opacity: 1;
       
   }
   
/*Panorama Mask*/
   
   .dm-panorama-swiper {
     
       /* mask */
  mask-image: url("https://dmmotionarts.com/wp-content/uploads/2025/12/Panorama-Shape-StretchingAllowed.svg");
  mask-size: 100% 100%;       /* scale mask to full container */
  mask-repeat: no-repeat;
  mask-position: center;
  mask-mode: alpha;

  /* Safari / WebKit */
  -webkit-mask-image: url("https://dmmotionarts.com/wp-content/uploads/2025/12/Panorama-Shape-StretchingAllowed.svg");
  -webkit-mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-position: center;
  -webkit-mask-mode: alpha;

       
   }

  
</style>
				
			

Leave a Reply