How to create a slider using only JavaScript and CSS, without including other libraries

My example below is going to show you how to create the simple slider from images. You can use a solution like this for any group of images you have, you would need a wrapper element for the images and for the navigation elements.

When adding the image widget in a sidebar, the output would be more complicated in terms of markup, but for this simple demo, I will simplify the markup completely, let’s say like this, also including the two elements that are going to be used for navigation:

<div id="my-custom-slider-demo" class="sidebar-slider">
	<a id="sidebar-slider-prev" onclick="customNavToPrevSlide()"> ❮ </a>
	<a id="sidebar-slider-next" onclick="customNavToNextSlide()"> ❯ </a>

	<div id="demo-slide1" class="widget_media_image">
		<b class="widget-title">Slide 1 Title</b>
		<a href="#"><img width="700" height="200" src="photo1.jpg"></a>
	</div>
	<div id="demo-slide2" class="widget_media_image">
		<b class="widget-title">Slide 2 Title</b>
		<a href="#"><img width="700" height="200" src="photo2.jpg"></a>
	</div>
	<div id="demo-slide3" class="widget_media_image">
		<b class="widget-title">Slide 3 Title</b>
		<a href="#"><img width="700" height="200" src="photo3.jpg"></a>
	</div>
</div>

In this markup, the slide is any element that contains an image, and that is marked with the class widget_media_image. Whatever is inside the “slide” will need to transition between the two states: active/inactive. By default, I would consider using only one class to specify which slide is active, by adding the active class to that element, and whatever does not have that class would be handled as “inactive” in the custom CSS.

I would also put in place a simple CSS:

#my-custom-slider-demo {
	display: block;
	overflow: hidden;
	position: relative;
}
#my-custom-slider-demo #sidebar-slider-prev,
#my-custom-slider-demo #sidebar-slider-next {
	background-color: rgba(0,0,0,0.5);
	color: #FFF;
	cursor: pointer;
	display: inline-block;
	font-size: 32px;
	height: 48px;
	line-height: 42px;
	opacity: 0;
	padding: 0;
	position: absolute;
	text-align: center;
	top: calc(50% - 24px);
	transition: 0.2s all;
	width: 48px;
	z-index: 5;
}
#my-custom-slider-demo #sidebar-slider-next {
	right: 0;
}
#my-custom-slider-demo:hover #sidebar-slider-prev,
#my-custom-slider-demo:hover #sidebar-slider-next{
	opacity: 1;
}
#my-custom-slider-demo .widget_media_image {
	height: 100%;
	left: 0;
	opacity: 0;
	position: absolute;
	top:0;
	transition: 0.8s all;
	z-index: 0;
	width: 100%;
}
#my-custom-slider-demo .widget_media_image:first-of-type,
#my-custom-slider-demo .widget_media_image.active {
	opacity: 1;
	z-index: 1;
}
#my-custom-slider-demo .widget_media_image img {
	height: auto;
	width: 100%;
}
#my-custom-slider-demo .widget_media_image b {
	background-color: rgba(0,0,0,0.5);
	bottom: 0;
	color: #FFF;
	display: inline-block;
	font-size: 14px;
	left: 0;
	padding: 10px 20px;
	position: absolute;
	text-transform: uppercase;
}
@media all and (max-width: 600px) {
	#my-custom-slider-demo .widget_media_image b {
		display: none;
	}
}

I would first style the elements so that these are all displayed in the same position, and the images to stretch to the maximum width of the wrapper. The slides titles will be placed over the images, and the navigation arrows will only display when you move the mouse over the slider so that these do not cover too much space or attract attention, the main focus would be the image. By default, the first element that contains the image would be visible.

The JavaScript code is

let currentSlide = 0, theSlides = document.getElementsByClassName('widget_media_image'), customSliderTimer, next, prev, theWrapper = document.getElementById('my-custom-slider-demo');
function customNavToNextSlide() {
	next = ( currentSlide < theSlides.length - 1 ) ? currentSlide + 1 : 0;
	customSetCurrentSlide(next);
}
function customNavToPrevSlide() {
	prev = ( currentSlide > 0 ) ? currentSlide - 1 : theSlides.length - 1;
	customSetCurrentSlide(prev);
}
function customSetCurrentSlide(to) {
	clearInterval(customSliderTimer);
	for (let i = 0; i < theSlides.length; i ++) {
		if ( currentSlide == i ) {
			theSlides[currentSlide].classList.remove('active');
		}
		if ( next == i ) {
			theSlides[to].classList.add('active');
		}
	}
	currentSlide = to;
	customSliderStart();
}
function customSliderStart() {
	customSliderTimer = setInterval(function() {
		customNavToNextSlide();
	}, 5000);
}
function customSliderInit() {
	let height = theSlides[0].getElementsByTagName('img')[0].height;
	theWrapper.style.height = height + 'px';
	for (let i = 0; i < theSlides.length; i ++) {
		theSlides[i].style.height = height + 'px';
	}
}
if (typeof theSlides !== 'undefined') {
	window.addEventListener('resize', customSliderInit);
	customSliderInit();
	if ( theSlides.length > 1 ) {
		customSliderStart();
	}
}

So, I would need to check if there are any elements that contain the images and look like my “slides”, by looking for the class widget_media_image. By default, the first slide would be active, and after 5 seconds (in the script this appears as the second parameter for setInterval inside the customSliderStart function, but you can change it to what you need) the next slide will become active, and so on. However, when I click the navigation arrows, I have to make sure that another transition is not ready to fire, so I have to clear the interval first, so the slider will not glitch.


When asambling the HTML + CSS + JavaScript, the output would be similar to this.

Did you find this script/tutorial useful?

Send me your feedback on the contact page and please consider making a donation to support my work. Thank you!

Share the article
  • Distribuie pe LinkedIn