How to Add a Stylish Horizontal Scrolling Effect in Elementor Without Elementor Pro
Creating a unique user experience on your WordPress site can be as simple as adding a horizontal scroll effect. This guide will walk you through the process of adding a smooth, stylish horizontal scrolling effect in Elementor without using Elementor Pro or any additional plugins. Perfect for beginners and experienced designers alike!
Step 1: Set Up Your Page and Add a Flexbox Container
- Create a New Page in WordPress and open it with Elementor.
- Click the Plus (+) icon to add a new container, selecting the Flexbox option.
- Customize the Background – To make it stand out, choose a darker color. In the Style tab, set the background color to black or any other dark shade that complements your design.
Step 2: Adjust Layout and Sizing
- Go to the Layout settings and set the Content Width to Full Width.
- Adjust the Minimum Height to
100 VH
for a full-screen effect. - In the Advanced tab, remove the default padding to create a clean, seamless layout.
Step 3: Adding Inner Containers and Elements
- Add Two Containers within the main container. Use the Duplicate option after adding the first container.
- Set Direction to Row: Choose the main container, and under the Layout section, change the direction to Row so that the containers are displayed side-by-side.
Step 4: Add Animated Text and Image Widgets
- Select the First Container to add animated text and a button. Add an animated headline, a text widget, and a button for interaction.
- Customize the Animated Headline with the rotating text style for added visual interest.
- Add an Image Widget to the second container for a visually balanced layout. Choose an image, and under Advanced > Width, set it to Custom Width and adjust to around
70%
.
Step 5: Add and Style Additional Images
- In the first container, add two more images below the first image widget.
- Set each image’s width to custom sizes, around
26%
for smaller images. - Adjust Border Radius in the Style tab to give your images rounded corners (e.g.,
10px
).
Step 6: Enable Motion Effects
- For the interactive touch, go to Advanced > Motion Effects for each image.
- Enable Mouse Effects and add a 3D Tilt for a subtle dynamic movement when hovering over the images.
Step 7: Set Up the Second Section with Additional Elements
- Add Another Flexbox Container and set the layout direction to Column for this section.
- Customize the Background by adding an image or a color overlay, like a soft green shade.
- Inside this container, add another Animated Headline and an Image Widget.
Step 8: Finalize with an Ending Section
- Add a Heading and Button Widget to create a conclusion for your page.
- Style the button by setting the Background Color to black and aligning it in the center.
- Adjust the content width to full width for a balanced, clean look.
Step 9: Enable Horizontal Scrolling with Custom Code
- Go to Elementor > Custom Code and create a new code snippet. Name it Horizontal Scroll Animation.
<style>
/* Horizontal Scroll */
.mdw-horizontal-scroll{
--progress-bar: true;
--progress-bar-color: #FFFF00;
--progress-bar-height: 2px;
}
body{
--disable-movement-desktop: false;
--disable-movement-tablet: false;
--disable-movement-mobile: true;
--hide-default-scrollbar: false;
--disable-horizontal-scroll-mobile: false;
}
html.hide-scrollbar::-webkit-scrollbar{
display: none;
}
html.hide-scrollbar{
-ms-overflow-style: none;
scrollbar-width: none;
}
.mdw-horizontal-scroll{
overflow: hidden;
--initial-height: var(--min-height,100vh);
}
.mdw-horizontal-scroll:after{
content: "";
left: 0;
top: calc(100vh - var(--progress-bar-height,2px));
width: 100vw;
height: var(--progress-bar-height,2px);
background: var(--progress-bar-color,FFFF00);
transform: scaleX(calc(var(--progress,0)*100%));
position: fixed;
transform-origin: left;
will-change: transform;
transition: transform 0.1s linear;
opacity: 0;
}
.mdw-horizontal-scroll.fixed:after{
opacity: 1;
}
.mdw-horizontal-scroll.progress-bar-disabled:after{
display: none;
}
.mdw-horizontal-scroll > .e-con,
.mdw-horizontal-scroll > .e-container{
transition: none;
height: var(--initial-height,100vh);
}
body.tiny-scroll .mdw-horizontal-scroll > .e-con,
body.tiny-scroll .mdw-horizontal-scroll > .e-container{
will-change: transform;
transition: transform 1s cubic-bezier(0,.33,.07,1.03);
}
.mdw-horizontal-scroll.fixed > .e-con,
.mdw-horizontal-scroll.fixed > .e-container{
position: fixed;
top: 0;
left: 0;
}
.mdw-horizontal-scroll.bottom{
justify-content: flex-end;
}
.mdw-horizontal-scroll > .e-con > *,
.mdw-horizontal-scroll > .e-container > *{
height: var(--min-height, 100vh);
}
.mdw-horizontal-scroll.hs-disabled{
height: auto !important;
}
.mdw-horizontal-scroll.hs-disabled:after{
display: none;
}
.mdw-horizontal-scroll.hs-disabled > .e-con,
.mdw-horizontal-scroll.hs-disabled > .e-container{
flex-direction: column;
height: auto;
}
.mdw-horizontal-scroll.hs-disabled.fixed > .e-con,
.mdw-horizontal-scroll.hs-disabled.fixed > .e-container{
position: relative;
}
.mdw-horizontal-scroll.hs-disabled > .e-con > *,
.mdw-horizontal-scroll.hs-disabled > .e-container > *{
height: auto;
}
.mdw-horizontal-scroll.hs-disabled > .e-con > .e-con,
.mdw-horizontal-scroll.hs-disabled > .e-container > .e-container{
width: 100%;
}
/* Scrolling Movement */
.e-con[class^='mdw-hs-movement'],
.e-con[class*=' mdw-hs-movement'],
.e-container[class^='mdw-hs-movement'],
.e-container[class*=' mdw-hs-movement'],
.elementor-widget[class^='mdw-hs-movement'] .elementor-widget-container,
.elementor-widget[class*=' mdw-hs-movement'] .elementor-widget-container{
transform: translateX(calc(var(--e-transform-translateX,0px) + var(--translateX,0)*-1px)) translateY(calc(var(--e-transform-translateY,0px) + var(--translateY,0)*1px)) rotate(calc(var(--rotateZ,0deg) + var(--rotate,0)*1deg));
transition: none;
}
body.tiny-scroll .e-con[class^='mdw-hs-movement'],
body.tiny-scroll .e-con[class*=' mdw-hs-movement'],
body.tiny-scroll .e-container[class^='mdw-hs-movement'],
body.tiny-scroll .e-container[class*=' mdw-hs-movement'],
body.tiny-scroll .elementor-widget[class^='mdw-hs-movement'] .elementor-widget-container,
body.tiny-scroll .elementor-widget[class*=' mdw-hs-movement'] .elementor-widget-container{
will-change: transform;
transition: transform 1s cubic-bezier(0,.33,.07,1.03);
}
.e-con[class^='mdw-hs-movement-translate-x'],
.e-con[class*=' mdw-hs-movement-translate-x'],
.e-container[class^='mdw-hs-movement-translate-x'],
.e-container[class*=' mdw-hs-movement-translate-x'],
.elementor-widget[class^='mdw-hs-movement-translate-x'] .elementor-widget-container,
.elementor-widget[class*=' mdw-hs-movement-translate-x'] .elementor-widget-container{
--translateX: calc(var(--parallax,0)*var(--speed-x,10)*var(--direction-x,1));
}
.e-con[class^='mdw-hs-movement-translate-y'],
.e-con[class*=' mdw-hs-movement-translate-y'],
.e-container[class^='mdw-hs-movement-translate-y'],
.e-container[class*=' mdw-hs-movement-translate-y'],
.elementor-widget[class^='mdw-hs-movement-translate-y'] .elementor-widget-container,
.elementor-widget[class*=' mdw-hs-movement-translate-y'] .elementor-widget-container{
--translateY: calc(var(--parallax,0)*var(--speed-y,10)*var(--direction-y,1));
}
.e-con[class^='mdw-hs-movement-rotate'],
.e-con[class*=' mdw-hs-movement-rotate'],
.e-container[class^='mdw-hs-movement-rotate'],
.e-container[class*=' mdw-hs-movement-rotate'],
.elementor-widget[class^='mdw-hs-movement-rotate'] .elementor-widget-container,
.elementor-widget[class*=' mdw-hs-movement-rotate'] .elementor-widget-container{
--rotate: calc(var(--parallax,0)*var(--speed-r,10)*var(--direction-r,1));
}
/* Reveal Animtion */
.mdw-reveal-animation,
.mdw-reveal-animation-left,
.mdw-reveal-animation-right,
.mdw-reveal-animation-top,
.mdw-reveal-animation-bottom{
animation: none !important;
transition: all 1s ease-in-out !important;
clip-path: polygon(0 0, 100% 0, 100% 100%, 0% 100%);
}
.mdw-reveal-animation:not(.animated),
.mdw-reveal-animation-left:not(.animated),
.mdw-reveal-animation-right:not(.animated),
.mdw-reveal-animation-top:not(.animated),
.mdw-reveal-animation-bottom:not(.animated){
opacity: 0;
}
.mdw-reveal-animation:not(.animated),
.mdw-reveal-animation-bottom:not(.animated){
transform: translateY(2em);
clip-path: polygon(0 100%, 100% 100%, 100% 100%, 0% 100%);
}
.mdw-reveal-animation-left:not(.animated){
transform: translateX(-2em);
clip-path: polygon(0 0, 0 0, 0 100%, 0% 100%);
}
.mdw-reveal-animation-right:not(.animated){
transform: translateX(2em);
clip-path: polygon(100% 0, 100% 0, 100% 100%, 100% 100%);
}
.mdw-reveal-animation-top:not(.animated){
transform: translateY(-2em);
clip-path: polygon(0 0, 100% 0, 100% 0, 0 0);
}
/* For Mobile Devices */
@media (max-width: 767px){
.mdw-horizontal-scroll > .e-con,
.mdw-horizontal-scroll > .e-container{
transition: transform 0.1s linear;
}
}
</style>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
if(!MDWNonce109){
var MDWNonce109 = true
;(function($){
function init(){
$('body').append('<div class="mdw-100vh" style="height: 100vh;display: none;"></div>')
if($('body').css('--hide-default-scrollbar') && $('body').css('--hide-default-scrollbar').trim() == 'true'){
$('html').addClass('hide-scrollbar')
}
}
function getValue(text, defaultValue){
return (text.match(/\d+/) ? text.match(/\d+/)[0] : defaultValue)/100
}
function getDirection(text){
return text.search('reverse') > -1 ? -1 : 1
}
function horizontalScroll(scroll, windowWidth, windowHeight, disableMobile){
$('.mdw-horizontal-scroll').each(function(){
var $this = $(this),
container = $this.find('.e-con, .e-container').eq(0),
containerTop = $this.offset().top,
totalWidth = 0,
extraWidth = 0,
passed = scroll - containerTop,
translate = passed,
minHeight = $this.css('--min-height') ? $this.css('--min-height') : '100vh'
container.children().each(function(){
totalWidth += $(this).outerWidth() + parseFloat($(this).css('margin-left')) + parseFloat($(this).css('margin-right'))
})
if( windowWidth < 768 && disableMobile ){
totalWidth = windowWidth
$this.addClass('hs-disabled')
}else{
$this.removeClass('hs-disabled')
}
$this.attr('total-width', totalWidth)
if(totalWidth > windowWidth){
extraWidth = totalWidth - windowWidth
}
$this.height('calc(' + minHeight + ' + ' + extraWidth + 'px)')
if(passed < 0){ translate = 0 }
if(passed > extraWidth){ translate = extraWidth }
var progress = translate/extraWidth
if(progress <= 0){
$this.removeClass('fixed bottom')
}
if(progress > 0 && progress < 1){
$this.addClass('fixed')
$this.removeClass('bottom')
}
if(progress >= 1){
$this.removeClass('fixed')
$this.addClass('bottom')
}
container.css('transform', 'translateX(-' + translate + 'px)')
$this.css('--progress', progress)
if($this.css('--progress-bar') && $this.css('--progress-bar') == 'true'){
$this.removeClass('progress-bar-disabled')
}else{
$this.addClass('progress-bar-disabled')
}
})
}
var parallaxUpdate = false
function scrollMovement(scroll, windowWidth, windowHeight, disableMobile){
var enableMovement = false
if(windowWidth > 0){
enableMovement = !$('body').css('--disable-movement-mobile') || $('body').css('--disable-movement-mobile').trim() != 'true'
}
if(windowWidth > 767){
enableMovement = !$('body').css('--disable-movement-tablet') || $('body').css('--disable-movement-tablet').trim() != 'true'
}
if(windowWidth > 1024){
enableMovement = !$('body').css('--disable-movement-desktop') || $('body').css('--disable-movement-desktop').trim() != 'true'
}
if(enableMovement){
$("[class^='mdw-hs-movement'], [class*=' mdw-hs-movement']").each(function(i){
var $this = $(this),
className = $this.attr('class'),
element = $this.hasClass('elementor-widget') ? $this.find('.elementor-widget-container') : $this,
parent = element.parent(),
elementRect = element.get(0).getBoundingClientRect(),
parentRect = parent.get(0).getBoundingClientRect(),
isHorizontal = $this.closest('.mdw-horizontal-scroll').length,
offset = 100,
elementVisible = elementRect.right > -1*offset && elementRect.left - windowWidth < offset && elementRect.top - windowHeight < offset && elementRect.bottom > -1*offset,
parentVisible = parentRect.right > -1*offset && parentRect.left - windowWidth < offset && parentRect.top - windowHeight < offset && parentRect.bottom > -1*offset,
hasChild = $this.find("div[class^='mdw-hs-movement'],div[class*=' mdw-hs-movement']").length,
totalWidth = parseFloat($this.closest('.mdw-horizontal-scroll').attr('total-width')),
parallax
$this.css({
'--speed-x': 0,
'--speed-y': 0,
'--speed-r': 0
})
className.split(' ').forEach(function(c){
if(c.startsWith('mdw-hs-movement-translate-x')){
$this.css('--speed-x', getValue(c, 10))
$this.css('--direction-x', getDirection(c))
}
if(c.startsWith('mdw-hs-movement-translate-y')){
$this.css('--speed-y', getValue(c, 10))
$this.css('--direction-y', getDirection(c))
}
if(c.startsWith('mdw-hs-movement-rotate')){
$this.css('--speed-r', getValue(c, 10))
$this.css('--direction-r', getDirection(c))
}
})
if( windowWidth < 768 && disableMobile ){ isHorizontal = false }
if(isHorizontal){
var HSRect = $this.closest('.mdw-horizontal-scroll').find('.e-con, .e-container').get(0).getBoundingClientRect(),
leftPos = Math.round(elementRect.left + element.outerWidth()/2 - parseFloat(element.css('transform').split(' ')[4]) - HSRect.left)
if(leftPos < windowWidth/2 || totalWidth < windowWidth){
parallax = - HSRect.top - HSRect.left
}else if(leftPos > totalWidth - windowWidth/2){
parallax = - HSRect.top - HSRect.left - totalWidth + windowWidth
}else{
parallax = windowWidth/2 - elementRect.left - element.outerWidth()/2 - HSRect.top
}
}else{
var topPos = Math.round(elementRect.top + scroll + element.outerHeight()/2 - parseFloat(element.css('transform').split(' ')[5]))
if(topPos < windowHeight/2 || $('body').outerHeight(true) < windowHeight){
parallax = scroll
}else if(topPos > $('body').outerHeight(true) - windowHeight/2){
parallax = scroll - $('body').outerHeight(true) + windowHeight
}else{
parallax = windowHeight/2 - element.outerHeight()/2 - elementRect.top
}
}
if(parentVisible || elementVisible || hasChild || parallaxUpdate){
$(this).css('--parallax', parallax)
}
})
}else{
$("[class^='mdw-hs-movement'], [class*=' mdw-hs-movement']").css('--parallax', 0)
}
}
var currentTime, lastTime
function scrollActivity(delayCall=true){
var scroll = $(window).scrollTop(),
windowWidth = $(window).width(),
windowHeight = $('.mdw-100vh').height(),
disableMobile = $('body').css('--disable-horizontal-scroll-mobile') && $('body').css('--disable-horizontal-scroll-mobile') == 'true'
lastTime = new Date()
setTimeout(function(){
currentTime = new Date()
if(currentTime - lastTime > 200 && delayCall){
scrollActivity(false)
}
},500)
horizontalScroll(scroll, windowWidth, windowHeight, disableMobile)
scrollMovement(scroll, windowWidth, windowHeight, disableMobile)
}
function scrollToSection(){
var link = $(this).attr('href')
if( link && link != '#' && link[0] == '#' ){
var el = $('.' + link.substr(1)).eq(0),
parentHS = el.closest('.mdw-horizontal-scroll'),
disableMobile = $('body').css('--disable-horizontal-scroll-mobile') && $('body').css('--disable-horizontal-scroll-mobile') == 'true'
if(parentHS.length){
var scrollAmount = parentHS.offset().top + el.offset().left - parentHS.find('.e-con, .e-container').eq(0).offset().left
if($(window).width() < 768 && disableMobile){
scrollAmount = el.offset().top
}
$('html, body').stop().animate({scrollTop:scrollAmount}, 300, 'linear')
}
}
}
$(document).ready(function(){
init()
scrollActivity()
$('body').on('click', 'a', scrollToSection)
})
function runParallax(){
if(parallaxUpdate) return
parallaxUpdate = true
setTimeout(function(){
parallaxUpdate = false
},1000)
var repeatParallax = setInterval(function(){
if(parallaxUpdate){
scrollActivity()
}else{
clearInterval(repeatParallax)
}
},100)
}
var currentIsTrackpad,
previosIsTrackpad
function detectScrollResolution(e){
var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent)
if(e.wheelDeltaY !== undefined && e.deltaY !== undefined && !isSafari){
var del = e.deltaY != 0 ? e.deltaY : 1,
delVal = Math.abs(e.wheelDeltaY/del),
currentIsTrackpad = delVal > 2.9 && delVal <= 3
if(currentIsTrackpad && previosIsTrackpad){
$('body').addClass('tiny-scroll')
}else{
$('body').removeClass('tiny-scroll')
}
previosIsTrackpad = currentIsTrackpad
}else{
$('body').removeClass('tiny-scroll')
}
}
$(window).on('load resize', function(){
runParallax()
setTimeout(runParallax, 1000+100)
})
$(window).on('load resize scroll', scrollActivity)
window.addEventListener('mousewheel', detectScrollResolution)
$('body').on('keydown', function(e) {
if (e.key == " " || e.code == "Space" || e.keyCode == 32){
$('body').removeClass('tiny-scroll')
}
})
$('body').on('click', function(){
$('body').removeClass('tiny-scroll')
})
})(jQuery)
}
</script>
Step 10: Final Adjustments in CSS
- In the Advanced tab for your main container, add the CSS class
mdw-horizontal-scroll
. - Publish and preview your page. Your horizontal scroll effect is ready to view!
Step 11: Preview and Fine-Tune
- Preview the Page to see how your horizontal scroll effect appears.
- Make any necessary tweaks to padding, motion effects, or alignment as needed.
Final Thoughts
With this horizontal scrolling effect, you’ve added a unique layer of interactivity to your Elementor site, creating an engaging user experience without any extra plugins. If you want more tutorials like this one, subscribe to our newsletter or check out our other Elementor tips and tricks!
5/5 - (9 votes)