Effects & DesignElementor

How To Make An Amazing Slider Banner Using Elementor Free

Tools and Links Used

Hostinger Fast, beginner friendly WordPress hosting.
Get Hosting
Elementor The free page builder this tutorial is built with.
Get Elementor
Elementor Pro The Pro upgrade used throughout this tutorial.
Get Elementor Pro
Project Files Download the resources used in this tutorial.
Download Files
Kitpapa Ready made Elementor template kits.
Get Templates
Kitninja eCommerce Elementor template kits.
Get Templates

Prompt Used in This Tutorial

Slider Curve Shape Effect CSS And JS Code
<style>
  [class^='mdw-curved-slider'],
  [class*=' mdw-curved-slider'] {
    height: var(--min-height, 100vh);
    overflow: hidden;
    position: relative;
  }

  [class^='mdw-curved-slider'] canvas,
  [class*=' mdw-curved-slider'] canvas {
    position: absolute;
    top: 0;
    left: 0;
  }
</style>

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/0.160.0/three.min.js"></script>

<script>
  if (!MDWNonce111) {
    var MDWNonce111 = true;

    const selector = "[class^='mdw-curved-slider'], [class*=' mdw-curved-slider']";
    const scene = [], renderer = [], options = [], camera = [];
    const planes = [], slideAmount = [], time = [];

    document.addEventListener('DOMContentLoaded', function () {
      function getWidth(gap) {
        return 1 + gap / 100;
      }

      function getPlaneWidth(el, camera) {
        const vFov = camera.fov * Math.PI / 180;
        const height = 2 * Math.tan(vFov / 2) * camera.position.z;
        const aspect = el.clientWidth / el.clientHeight;
        const width = height * aspect;
        return el.clientWidth / width;
      }

      function init() {
        Array.from(document.querySelectorAll(selector)).forEach(function (el, index) {
          const className = el.getAttribute('class');
          const classNameIndex = className.indexOf('mdw-curved-slider');
          const shortClass = className.substring(classNameIndex, className.indexOf(' ', classNameIndex));
          const values = shortClass.split('-');

          options[index] = {
            speed: 300,
            gap: 10,
            curve: 15,
            direction: -1
          };

          values.forEach(function (value, i) {
            if (value == 'speed' && values[i + 1] && !isNaN(values[i + 1])) {
              options[index].speed = values[i + 1];
            }
            if (value == 'gap' && values[i + 1] && !isNaN(values[i + 1])) {
              options[index].gap = values[i + 1];
            }
            if (value == 'curve' && values[i + 1] && !isNaN(values[i + 1])) {
              options[index].curve = values[i + 1];
            }
            if (value == 'reverse') { options[index].direction = 1; }
          });

          const images = [];
          time[index] = 0;

          Array.from(el.querySelectorAll('.elementor-widget-image-gallery .gallery-item')).forEach(function (el) {
            images.push(el.querySelector('img').getAttribute('src'));
          });

          slideAmount[index] = images.length;
          const allImages = [...images];

          scene[index] = new THREE.Scene();
          camera[index] = new THREE.PerspectiveCamera(75, el.clientWidth / el.clientHeight, 0.1, 20);
          camera[index].position.z = 2;

          renderer[index] = new THREE.WebGLRenderer({ alpha: true, antialias: true });
          renderer[index].setSize(el.clientWidth, el.clientHeight);
          renderer[index].setPixelRatio(window.devicePixelRatio);

          const previousCanvas = el.querySelector('canvas');
          if (previousCanvas) el.removeChild(previousCanvas);
          el.appendChild(renderer[index].domElement);

          const geometry = new THREE.PlaneGeometry(1, 1, 20, 20);
          const planeSpace = getPlaneWidth(el, camera[index]) * getWidth(options[index].gap);
          const totalImage = Math.ceil(el.clientWidth / planeSpace) + 1 + images.length;
          const initialOffset = Math.ceil(el.clientWidth / (2 * planeSpace) - 0.5);

          for (let i = slideAmount[index]; i < totalImage; i++) {
            allImages.push(images[i % slideAmount[index]]);
          }

          planes[index] = [];

          allImages.forEach(function (image, i) {
            const loader = new THREE.TextureLoader();
            loader.load(
              image,
              function (texture) {
                const material = new THREE.ShaderMaterial({
                  uniforms: {
                    tex: { value: texture },
                    curve: { value: options[index].curve }
                  },
                  vertexShader: `
                    uniform float curve;
                    varying vec2 vertexUV;
                    void main(){
                      vertexUV = uv;
                      vec3 newPosition = position;
                      float distanceFromCenter = abs(modelMatrix*vec4(position, 1.0)).x;
                      newPosition.y *= 1.0 + (curve/100.0)*pow(distanceFromCenter,2.0);
                      gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);
                    }
                  `,
                  fragmentShader: `
                    uniform sampler2D tex;
                    varying vec2 vertexUV;
                    void main(){
                      gl_FragColor = texture2D(tex, vertexUV);
                    }
                  `
                });

                const mesh = new THREE.Mesh(geometry, material);
                mesh.position.x = -1 * options[index].direction * (i - initialOffset) * getWidth(options[index].gap);
                mesh.frustumCulled = false;
                planes[index].push(mesh);
                scene[index].add(mesh);
              }
            );
          });
        });
      }

      init();

      // ✅ Scroll tracking system
      let previousScrollY = window.scrollY;
let scrollPosition = 0;
let smoothedScroll = 0;

function animate() {
  scrollPosition = window.scrollY;

  // Smooth the scroll position with easing (0.1 = ease factor)
  smoothedScroll += (scrollPosition - smoothedScroll) * 0.1;

  const scrollDelta = smoothedScroll - previousScrollY;

  Array.from(document.querySelectorAll(selector)).forEach(function (el, index) {
    if (!planes[index]) return;

    const direction = scrollDelta > 0 ? 1 : -1;
    const deltaAmount = Math.abs(scrollDelta) * 0.01;

    const planeWidth = getWidth(options[index].gap);
    const loopWidth = planeWidth * planes[index].length;

    planes[index].forEach(function (plane) {
      plane.position.x += direction * deltaAmount;

      if (plane.position.x > loopWidth / 2) {
        plane.position.x -= loopWidth;
      } else if (plane.position.x < -loopWidth / 2) {
        plane.position.x += loopWidth;
      }
    });

    renderer[index].render(scene[index], camera[index]);
  });

  previousScrollY = smoothedScroll;
  requestAnimationFrame(animate);
}


      requestAnimationFrame(animate);
    });
  }
</script>
Slider Curve Shape CSS Class
mdw-curved-slider

Get Your FREE Freelancing Roadmap

Stop hopping between tutorials. Grab the Freelancing Mastery Handbook to learn how to choose a skill, build your foundation, find clients, and confidently start your freelancing journey.

Free eBook Download

Related Tutorials

From learning the right skills to building a stronger digital presence, we help you turn ideas into practical, professional results.

Vibe Code a REAL Animated WordPress Website with Claude + Elementor

21.8K views

View Tutorial

Vibe Coding Full Course for Beginners – Build & Launch a Real SaaS

3.3K views

View Tutorial

Edit Videos with ChatGPT Codex — Raw Clips to Finished Reel

3.4K views

View Tutorial

Browse All Tutorials