A simple text slider

Hello there,


The above was build using an owl carousel slider, but now I believe that conceiving 3rd party library is too taxing on the overall code. The simple JS can deliver such a thing.

Please help me to get the mathematical logic clear I want to give an honest attempt to make one without seeing any example; that will be the first principal approach.

15 items are there(Hypothetically, for example): At JS level what will happen that adjacent text boxes will be replaced till the end of the queue based on which arrow is triggered.

Hi @codeispoetry, one approach would be as follows:

  • Have a container with relative positioning and hidden overflow
  • Inside the container is the actual slider with absolute positioning, and a CSS transform transition as desired
  • Remember the index of the leftmost visible slide (starting with zero)
  • When clicking left or right:
    • Increment or decrement that index
    • Add the widths of the elements up to the current index, and apply a CSS transform to the slider translating it accordingly along the x axis

HTH :-)

2 Likes

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
</head>
<body>
	<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<link rel="stylesheet" href="style.css">
</head>
<body>
	<div class="wrapper">
		<div class="container">
			<div class="slider">
				<div class="slide">01</div>
				<div class="slide">02</div>
				<div class="slide">03</div>
				<div class="slide">04</div>
				<div class="slide">05</div>
				<div class="slide">06</div>
				<div class="slide">07</div>
				<div class="slide">08</div>
				<div class="slide">09</div>
				<div class="slide">10</div>
			</div>
		</div>
		<div class="arrow">
			<div class="left"><</div>
			<div class="right">></div>
		</div>
	</div>
</body>
</html>

CSS:

@import url('https://fonts.googleapis.com/css?family=PT+Sans');
@import url('https://fonts.googleapis.com/css?family=Lato:100,100i,300,300i,400,400i,700,700i,900,900i');
html,
body {
  margin  :0;
  padding :0;
  font-family: 'Lato', sans-serif;
  background-color: #F7F7F7;
}
* {
  box-sizing: border-box;
}
h1, h2, h3, h4, h5, h6, ul, span, p {margin: 0; padding: 0;}
p {
	font-size: 1.2rem;
  line-height: 1.551;
}
h1{
	font-size: 5rem;
	font-weight: normal;
	color: #4A4949;
}
h3 {
  font-size: 3rem;
  font-weight: normal;
  color: #4A4949;
}
h4 {
  font-size: 2.6rem;
  font-weight: normal;
  color: #4A4949;
}
h6 {
  font-size: 1.5rem;
}


ul {
  list-style-type: none;
}


.wrapper {
  display: flex;
  max-width: 1200px;
  margin: auto;
}
.container {
  position: relative;
  
}
.slider {
  display: flex;
  justify-content: space-between;
  border:1px solid #000000;
  position: absolute;
  overflow: hidden;
}
.slide {
  width: 30%;
  min-width: 30%;
  padding: 10px 20px;
  border:2px solid #DCDCDC;
  margin:20px;
}
.arrow {
  margin: auto;
  margin-top: 150px;
}
.right, .left {
  padding: 5px 10px;
  border: 2px solid #DCDCDC;
  margin: 10px;
  font-size: 1.2rem;
  font-weight: bold;
  color: #000000;
}

Hi there everyone,
I am unable to position the slider div in the middle.

const slide = document.getElementsByClassName("slide");

The syntax is not completely visible, but I think we have to access:

slide[i]

based on the left and right arrow clicked i should increase or decrease.

The remaining will be taken care of by CSS because based on media query and screen resolution it is the css, which will decide how many items to show.

JS task will be to change the first element in the JS array/nodes.

Furthermore, not yet tested on live, but this is what I can visualize:

	const leftSlide = document.querySelector(".left");
	const rightSlide = document.querySelector(".right");

	leftSlide.addEventListener("click", IncreaseZero);
	function IncreaseZero() {
		for (var i = 0; i < slide.length; i++) {
			i = i;
		        slide[0] = slide[i] ;
		}
	}

	rightSlide.addEventListener("click", DecreaseZero);
	function DecreaseZero() {
		for (var i = 0; i < slide.length; i++) {
			i = i;
   		       slide[0] = slide[i] ;
		}
	}

Finally I refined the code, but still could not put it in synchronization with the actual HTML so that first element in slide should get modified and sliding happens→

	<script>
		const slide = document.getElementsByClassName("slide");
		const leftSlide = document.querySelector(".left");
		const rightSlide = document.querySelector(".right");

		leftSlide.addEventListener("click", IncreaseZero);
		function IncreaseZero() {
			for (var i = 0; i < slide.length; i++) {				
			  slide[0] = slide[i];
			  i = i++;
			}
		}

		rightSlide.addEventListener("click", DecreaseZero);
		function DecreaseZero() {
			for (var i = 0; i < slide.length; i++) {				
			  slide[0] = slide[i];
			  i = i--;
			}
		}
	</script>

I think we have to assign an extra class first to first element and based on node inccrement/decrement we have to change that class/toggling.

Well the idea is not to modify any .slide at all, but apply a transform to the .slider – add the widths of the slides up to the current index, and translate the slider horizontally so that the previous slides are overflowing to the left (and thus hidden).

https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements

https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translate()

1 Like

I would use JavaScript to make this responsive: including hiding the buttons if there is nothing hidden.

Anyone disagree?

1 Like

My intention was also to use JS. Can my code be refined?

If you wish I can show you code I have that works (but it’s not responsive as it stands). It is an alternative approach but I’m not saying it is more refined :grinning:

1 Like

Sure, Thanks!

OK, here is my code that I wrote before the first reply to this thread.

My terminology is somewhat different . . . .

  • The whole thing has class “slider”;
  • Within the slider is a “view” (red border) and an element for the buttons (“buttons”);
  • Within the view is a “container” wider than the view, with its overflow hidden;
  • Within the “container” are a number of text boxes with class “box”.

I have used negative values of CSS margin-left to move the container instead of using CSS transform.

Note the “-400” in the JavaScript limits the shifting of the container. That would need to be changed by calculation if there are more text boxes or the width of the “view” is changed. At present it allows no more than two text boxes (200 pixels wide) to disappear off to the left.

With sliders like this there is always a question as to which way the arrows should point.

Standby for comments on my code from this forum’s coding puritans :grinning:

2 Likes

Transform is more performant and utilises the GPU. I think you’ll find margin-left is a more expensive operation and triggers repaints (I had a list somewhere of all the properties that trigger re-flows)

You can kind of see it when you scroll, it’s a bit jittery.

I don’t have the time right now, but here is one article on the topic
https://www.paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/

3 Likes