I need help trying to complete a JavaScript effect. I'm looking to accomplish the effect on this site https://www.lucidmotors.com/ - in the third section down on the home page you can see the text scroll/reveal is smooth over the other text.
I found this option on codepen https://codepen.io/Bes7weB/pen/zYKoexK similar to the effect I need, but its a little to choppy I need it to be smoother.
JS
var textWrapper = document.querySelector(".ml3");
textWrapper.innerHTML = textWrapper.textContent.replace(
/\S/g,
"<span class='letter'>$&</span>"
);
var letter = document.querySelectorAll(".letter");
var i = 0;
var currentID = 0;
var slideCount = letter.length;
document.addEventListener("scroll", (e) => {
let scrolled =
document.documentElement.scrollTop /
(document.documentElement.scrollHeight -
document.documentElement.clientHeight);
// var nextID = currentID + 1;
// if (nextID < slideCount) {
// letter[nextID].style.setProperty(
// "--percentage",
// `${scrolled / 1}` * nextID
// );
// }
// currentID = nextID;
letter.forEach(function (l, i) {
// console.log("====",i / letter.length, i, letter.length)
if (i / letter.length < scrolled) {
l.style.setProperty("--percentage", 1);
} else {
l.style.setProperty("--percentage", 0);
}
});
});
CSS
:root {
--percentage: 0;
}
body {
background-color: #000;
margin: 0;
height: 600vh;
}
.ml3 {
position: sticky;
top: 0;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
span {
font-family: Helvetica;
margin: 0;
padding: 0;
font-size: 48px;
color: #fff;
letter-spacing: -0.3px;
}
.ml3 span {
opacity: var(--percentage);
}
HTML
<div class="ml3">
<h1>THIS IS MY TEXT THAT IT'S GOING TO SHOW IN SCROLL</h1>
</div>
Any assistance would be great
This is probably what you're looking for, find it quite interesting and I think my answer can be improved, if you're interested only in the vertical scroll you should check the window.scrollY variable as well.
var textWrapper = document.querySelector(".ml3");
textWrapper.innerHTML = textWrapper.textContent.replace(
/\S/g,
"<span class='letter'>$&</span>"
);
var letter = document.querySelectorAll(".letter");
document.addEventListener("scroll", (e) => {
let scrolled =
document.documentElement.scrollTop /
(document.documentElement.scrollHeight -
document.documentElement.clientHeight) *
letter.length;
letter.forEach(function(l, i) {
if ((scrolled - i) > 1)
l.style.setProperty("--percentage", 1);
else if ((scrolled - i) < 0.2)
l.style.setProperty("--percentage", 0.2);
else
l.style.setProperty("--percentage", (scrolled - i));
});
});
:root {
--percentage: 0.2;
}
body {
background-color: #000;
margin: 0;
height: 600vh;
}
.ml3 {
position: sticky;
top: 0;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
span {
font-family: Helvetica;
margin: 0;
padding: 0;
font-size: 48px;
color: #fff;
letter-spacing: -0.3px;
}
.ml3 span {
opacity: var(--percentage);
}
<div class="ml3">
<h1>THIS IS MY TEXT THAT IT'S GOING TO SHOW IN SCROLL</h1>
</div>
Related
I want to have a webpage whose entire viewable area is filled with divs. I am currently using the following code:
var wh= window.innerHeight;
var ww= window.innerWidth;
var area= wh * ww;
i= 1;
while(area > 0) {
document.getElementById("map").innerHTML+= "<div class='map-box' id='box" + i + "'></div>";
area-= 20 * 20;
i+=1;
}
.map-box {width: 20px; height: 20px; border-color: grey; border-width: 1px; border-style: solid; display: inline-block; margin: 0; padding: 0;}
<body>
<div id='map'></div>
</body>
If you try to use this code is your browser, you will see that there are two flaws in this:
First, it creates too many extra divs which go outside the viewable screen.
Second, this code is also somewhat slow.
Can someone here help me address both of these flaws and also optimize this code for faster performance?
1.) That <div> is not 20x20, because of the border:
let d = document.getElementById("test");
console.log(d.offsetWidth, d.offsetHeight);
.map-box {
width: 20px;
height: 20px;
border-color: grey;
border-width: 1px;
border-style: solid;
display: inline-block;
margin: 0;
padding: 0;
}
<div id="test" class="map-box"></div>
2.) There's still the default border around the entire thing, and also some spacing between the lines:
var wh = window.innerHeight;
var ww = window.innerWidth;
var area = wh * ww;
i = 1;
while (area > 0) {
document.getElementById("map").innerHTML += "<div class='map-box' id='box" + i + "'></div>";
area -= 22 * 22; // hardcoding is not that nice
i += 1;
}
.map-box {
width: 20px;
height: 20px;
border-color: grey;
border-width: 1px;
border-style: solid;
display: inline-block;
margin: 0;
padding: 0;
}
#map {
background: blue;
}
body {
background: red;
}
<div id='map'></div>
3.) Half cells are evil, so the width/height should be rounded downwards to a multiple of 22. Suddenly the grid is becoming an actual rectangle, at least in Chrome/Edge. The between-spacing is still a problem:
var wh = Math.floor(window.innerHeight / 22) * 22; // <--!!
var ww = Math.floor(window.innerWidth / 22) * 22; // <--!!
var area = wh * ww;
i = 1;
while (area > 0) {
document.getElementById("map").innerHTML += "<div class='map-box' id='box" + i + "'></div>";
area -= 22 * 22;
i += 1;
}
.map-box {
width: 20px;
height: 20px;
border-color: grey;
border-width: 1px;
border-style: solid;
display: inline-block;
margin: 0;
padding: 0;
}
#map {
background: blue;
}
body {
background: red;
margin: 0; // <--!!
padding: 0; // <--!!
}
<div id='map'></div>
I don't actually know how to use line-height properly, this one works on my machine with my scaling/DPI, in Chrome/Edge, but that's all I can say about it. The 22-s are cut back, area now simply stores the number of <div>s to generate.
var wh = Math.floor(window.innerHeight / 22);
var ww = Math.floor(window.innerWidth / 22);
var area = wh * ww;
i = 1;
while (area > 0) {
document.getElementById("map").innerHTML += "<div class='map-box' id='box" + i + "'></div>";
area--;
i += 1;
}
.map-box {
width: 20px;
height: 20px;
border-color: grey;
border-width: 1px;
border-style: solid;
display: inline-block;
margin: 0;
padding: 0;
}
#map {
line-height: 0.6;
}
body {
margin: 0;
padding: 0;
}
<div id='map'></div>
Instead of accessing dom element's inner html on each loop iteration - do it once after the loop with "prepared" data to set there
const wh = window.innerHeight;
const ww = window.innerWidth;
let area = wh * ww;
i = 1;
const ms = Date.now();
const divs = [];
while (area > 0) {
divs.push("<div class='map-box' id='box" + i + "'></div>");
area -= 20 * 20;
i += 1;
}
document.getElementById("map").innerHTML = divs.join("");
console.log("done fast", Date.now() - ms);
js fiddle with comparison https://jsfiddle.net/aL7zqwy9/
The final solution, not ideal but
<html>
<body>
<div id='map'></div>
</body>
<style>
body {
margin: 0;
padding: 0;
/* Overflow appears when last row is added and shrinks the "width" */
overflow-y: hidden;
}
#map {
/* To exclude space between rows */
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.map-box {
width: 20px;
height: 20px;
border: 1px solid grey;
display: block;
margin: 0;
padding: 0;
/* So border thickness will not affect element size */
box-sizing: border-box;
}
</style>
<script>
const cellSize = 20; // px
const wh = window.innerHeight;
const ww = window.innerWidth;
// not always divisible by cell size without a remainder
const columnsCount = Math.floor(ww / cellSize);
const rowsCount = Math.floor(wh / cellSize);
const cellsCount = columnsCount * rowsCount;
console.log(`wh: ${wh}, ww: ${ww}, cols: ${columnsCount}, rows: ${rowsCount}`);
const divs = [];
for (let i = 0; i < cellsCount; i++) {
divs.push(`<div class='map-box' id='box${i}'></div>`);
}
document.getElementById("map").innerHTML = divs.join("");
</script>
</html>
So I am working on this project and I made a slider that slides 3 pics at a time but when it comes to the last 3 pics it stops (because of the condition) but I want to make it into infinite loop and I want it to autoslide every 3 seconds. Does anybody know how I can rewrite this part of code to make this work?
const carousel = document.querySelector(".carouselSlides");
const card = carousel.querySelector(".card");
const leftButton = document.querySelector(".slideLeft");
const rightButton = document.querySelector(".slideRight");
const carouselWidth = carousel.offsetWidth;
const cardStyle = card.currentStyle || window.getComputedStyle(card);
const cardMarginRight = Number(cardStyle.marginRight.match(/\d+/g)[0]);
const cardCount = carousel.querySelectorAll(".card").length;
let offset = 0;
const maxX = -(
(cardCount / 3) * carouselWidth +
cardMarginRight * (cardCount / 3) -
carouselWidth -
cardMarginRight
);
leftButton.addEventListener("click", function() {
if (offset !== 0) {
offset += carouselWidth + cardMarginRight;
carousel.style.transform = `translateX(${offset}px)`;
}
});
rightButton.addEventListener("click", function() {
if (offset !== maxX) {
offset -= carouselWidth + cardMarginRight;
carousel.style.transform = `translateX(${offset}px)`;
}
});
.carouselContainer {
display: flex;
align-items: center;
justify-content: space-around;
position: relative;
overflow: hidden;
height: 58vh;
width: 92vw;
margin: 0 auto;
}
.carouselSlides {
display: flex;
margin: 0;
padding: 0;
list-style: none;
width: 100%;
position: absolute;
left: 0;
transition: all 1s ease;
}
.button-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
}
.slideLeft {
position: relative;
color: #f1f1f1;
background-color: transparent;
border: none;
font-size: 4rem;
right: 26rem;
}
.slideRight {
position: relative;
color: #f1f1f1;
background-color: transparent;
border: none;
font-size: 4rem;
left: 26rem;
}
<div class="carouselContainer">
<div class="carouselSlides">
<div id="slide0" class="card">
<div class="card__thumbnail">
<span class="card__title">FADE</span>
<button class="morebtn" onclick="">READ MORE</button>
</div>
</div>
</div>
<div class="button-wrapper">
<button class="slideLeft">‹</button>
<button class="slideRight">›</button>
</div>
</div>
So basically this is Day 3 (other days, I pretty much did nothing to complete the game) of making a game from HTML5. So I'm making a moves system right now, and I guess I'm doing well? (mainly because I'm not sure if I provided the user with too many moves...) But the thing about it is that, I'm kind of having ANOTHER styling issue.
As you can see in the image: I've CLEARLY set dimensions up for the headerDisplay class/id, but NO, it goes out of the div's dimensions and even goes on the grid. I'm also aiming for the time and moves text to be stuck right on top of the grid, similarly to how the word bank is stuck to the bottom of the grid.
I was also aiming for a button that says refresh right under the word bank, however no matter what I tried, the button would just be right the score text, which looks like this:
When I am aiming for this:
Code:
<div class="content" id="content">
<div class="headerDisplay" id="headerDisplay">
</div>
<div class="gameArea" id="gameArea">
</div>
<div class="wordBank" id="wordBank">
</div>
<div class="bottomMenu" id="bottomMenu">
</div>
</div>
::before,
::after {
box-sizing: border-box;
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
.content {
display: grid;
grid-template-rows: repeat(3, max-content);
margin-block: 1em;
margin-inline: auto;
width: 512px;
}
.bottomMenu {
font-size: 24px;
text-align: right;
}
.wordBank {
border: 2.5px solid #000;
border-radius: 5px;
display: flex;
font-size: 1.6em;
min-height: 3em;
justify-content: space-between;
padding: 0.25em;
}
.wordBank span:nth-child(even) {
align-self: end;
}
.gameArea {
font-size: 0;
justify-self: center;
max-width: 100%;
}
.cell {
border: 1px solid black;
width: 50px;
font-size: 1rem;
height: 50px;
display: inline-block;
}
.headerDisplay {
width: 100%;
height: 76.8px;
text-align: right;
font-size: 1.6em;
}
let score = 0;
const headerDisplay = document.getElementById("headerDisplay")
const bottomMenu = document.getElementById("bottomMenu");
const wordBank = document.getElementById("wordBank")
const gameArea = document.getElementById("gameArea")
const rows = document.getElementsByClassName("gridRow");
const cells = document.getElementsByClassName("cell");
const words = [ // snippet
"ability",
"able",
"about",
"above",
"abroad",
"absence",
"absent",
"absolute",
"accept",
"accident",
"accord",
"account",
"accuse",
"accustom",
"ache",
"across",
"act"
]
let selectedWords = [];
bottomMenu.innerHTML = "<p>Score: " + score;
bottomMenu.innerHTML += "<button>Refresh"
while (selectedWords.length < 5) {
const selectedWord = words[Math.floor(Math.random() * words.length)];
if (selectedWord.length <= 9) {
wordBank.innerHTML += "<span>" + selectedWord + "</span>"
selectedWords.push(selectedWord);
}
}
let longestWord = selectedWords.reduce((a, b) => a.length < b.length ? b : a, "")
let charCount = longestWord.length
var moves = charCount * 5
headerDisplay.innerHTML += "<p>Time: "
headerDisplay.innerHTML += "<p>Moves: " + moves
function makeRows(rowNum) {
for (let r = 0; r < rowNum; r++) {
let row = document.createElement("div");
gameArea.appendChild(row).className = "gridRow";
}
}
function makeColumns(cellNum) {
for (let i = 0; i < rows.length; i++) {
for (let j = 0; j < cellNum; j++) {
let newCell = document.createElement("div");
rows[j].appendChild(newCell).className = "cell";
}
}
}
function defaultGrid() {
makeRows(charCount);
makeColumns(charCount);
}
defaultGrid();
To fix header you need to set its height to fit content, so it will be over your grid even if you change it later:
.headerDisplay {
width: 100%;
height: content-fit; /* previous: 76.8px */
text-align: right;
font-size: 1.6em;
}
And to fix bottom menu you need to add flexbox:
.bottomMenu {
font-size: 24px;
text-align: right;
display: flex; /* new */
flex-direction: row-reverse; /* new */
justify-content: space-between; /* new */
align-items: center; /* new */
}
For the button, you could try this:
button {
position: relative;
right: 400px;
bottom: 50px;
transform: scale(2,2)
}
Here is a beautiful Number Ticker. the whole day I was wondering and trying to modify the code to make it as I want but no success till now!
if you work with numbers with two or more digits then the code creates separate black squares to hold each digit ( run code snippet to have a look ), but I want only a single square as the container to hold multiple digit numbers. So if we have a two-digit number like 10 the Number Ticker should be something like this:
And the next move should look like :
I don't want those parallel animations that move two digits like this (Only the single animation is required not both):
Here is the code:
let counters = document.getElementsByClassName('number-ticker');
let defaultDigitNode = document.createElement('div');
defaultDigitNode.classList.add('digit');
for (let i = 0; i < 11; i++) {
defaultDigitNode.innerHTML += i + '<br>';
}
[].forEach.call(counters, function(counter) {
let currentValue = 10;
let digits = [];
generateDigits(currentValue.toString().length);
setValue(currentValue);
setTimeout(function() {
setValue(8);
}, 2000);
setTimeout(function() {
setValue(7);
}, 5000);
function setValue(number) {
let s = number.toString().split('').reverse().join('');
let l = s.length;
if (l > digits.length) {
generateDigits(l - digits.length);
}
for (let i = 0; i < digits.length; i++) {
setDigit(i, s[i] || 0);
}
}
function setDigit(digitIndex, number) {
digits[digitIndex].style.marginTop = '-' + number + 'em';
}
function generateDigits(amount) {
for (let i = 0; i < amount; i++) {
let d = defaultDigitNode.cloneNode(true);
counter.appendChild(d);
digits.unshift(d);
}
}
});
:root {
background-color: #555;
color: white;
font-size: 25vh;
font-family: Roboto Light;
}
body,
html {
margin: 0;
height: 100%;
}
.container {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
.number-ticker {
overflow: hidden;
height: 1em;
background-color: #333;
box-shadow: 0 0 0.05em black inset;
}
.number-ticker .digit {
float: left;
line-height: 1;
transition: margin-top 1.75s ease;
border-right: 1px solid #555;
padding: 0 0.075em;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Number Ticker</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="number-ticker.css">
</head>
<body>
<div class="container">
<div class="number-ticker" data-value="0"></div>
</div>
<script src="number-ticker.js"></script>
</body>
</html>
Your css has this
.number-ticker .digit {
float: left;
line-height: 1;
transition: margin-top 1.75s ease;
border-right: 1px solid #555;
padding: 0 0.075em;
}
You need to change it to this
.number-ticker .digit {
float: left;
line-height: 1;
transition: margin-top 1.75s ease;
padding: 0 0.075em;
text-align: center;
}
If you remove border-right: 1px solid #555 you will have it look like 1 box.
Also I added text-align: center to center the numbers.
Hope this solves your problem :)
I think the main issue in your code is the digits variable. It creates an array of HTML elements that holds two blocks.
Also, for this line:
let s = number.toString().split('').reverse().join('');
Why do you need to convert number to a string. You can just pass it as is. Once you add to a string using + it will be converted.
I made few changes to your code and commented out the non-relevant part. Please see below:
let counters = document.getElementsByClassName('number-ticker');
let defaultDigitNode = document.createElement('div');
defaultDigitNode.classList.add('digit');
for (let i = 0; i < 11; i++) {
defaultDigitNode.innerHTML += i + '<br>';
}
[].forEach.call(counters, function(counter) {
// let currentValue = 10;
// let digits = [];
let currentValue = counter.getAttribute("data-value");
let digit = null;
generateDigits(currentValue.toString().length);
setValue(currentValue);
setTimeout(function() {
setValue(8);
}, 2000);
setTimeout(function() {
setValue(7);
}, 5000);
setTimeout(function() {
setValue(10);
}, 8000);
function setValue(number) {
// let s = number.toString().split('').reverse().join('');
// let l = s.length;
/*if (l > digits.length) {
generateDigits(l - digits.length);
}*/
/*for (let i = 0; i < digits.length; i++) {
setDigit(i, s[i] || 0);
}*/
digit.style.marginTop = '-' + number + 'em';
}
/*function setDigit(digitIndex, number) {
console.log(number);
digits[digitIndex].style.marginTop = '-' + number + 'em';
}*/
function generateDigits(amount) {
// console.log("generat", amount);
// for (let i = 0; i < amount; i++) {
let d = defaultDigitNode.cloneNode(true);
digit = counter.appendChild(d);
// digits.unshift(d);
// }
}
});
:root {
background-color: #555;
color: white;
font-size: 25vh;
font-family: Roboto Light;
}
body,
html {
margin: 0;
height: 100%;
}
.container {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
.number-ticker {
overflow: hidden;
height: 1em;
background-color: #333;
box-shadow: 0 0 0.05em black inset;
}
.number-ticker .digit {
float: left;
line-height: 1;
transition: margin-top 1.75s ease;
border-right: 1px solid #555;
padding: 0 0.075em;
text-align: center;
}
<div class="container">
<div class="number-ticker" data-value="0"></div>
</div>
Your final JS could be like this:
let counters = document.getElementsByClassName('number-ticker');
let defaultDigitNode = document.createElement('div');
defaultDigitNode.classList.add('digit');
for (let i = 0; i < 11; i++) {
defaultDigitNode.innerHTML += i + '<br>';
}
[].forEach.call(counters, function(counter) {
let currentValue = counter.getAttribute("data-value");
let d = defaultDigitNode.cloneNode(true);
let digit = counter.appendChild(d);
setValue(currentValue);
function setValue(number) {
digit.style.marginTop = '-' + number + 'em';
}
});
I have a simple image slider, with pagination controls.
I have coded it to add and remove an "active" class on the pagination
buttons on click. I would also like them to have the active class when the corresponding slide is showing.
How can I modify my code to achieve this?
<div id="slideshow">
<ul id="slides">
<li class="slide showing">
<div class="slide-description">
<h1 class="slide-title">All-in-one EV charging solution.</h1>
<p> Easy to use. Connected with smart charging capabilities. Our charging stations can be used at home,
work or in public.</p>
</div>
</li>
<li class="slide">
<div class="slide-description">
<h1 class="slide-title">Charging at work- a case study.</h1>
<p>In this new series of charging case studies, we dive into into the reasons why EV-Box partners are taking the green route.</p>
</div>
</li>
<li class="slide"> <div class="slide-description">
<h1 class="slide-title">Finding the best solution for your charging routine.</h1>
<p>
This whitepaper highlights the key answers that will guide you to acharging solution that best serves your needs.
</p>
</div>
</li>
</ul>
<button class="controls" id="previous"></button>
<button class="controls" id="next"></button>
<div id="pagination"></div>
var slides = document.querySelectorAll('#slides .slide'); // get all the slides
var currentSlide = 0;
var slideInterval = setInterval(nextSlide, 6000);
function nextSlide() {
goToSlide(currentSlide + 1);
}
function previousSlide() {
goToSlide(currentSlide - 1);
}
function goToSlide(n) {
slides[currentSlide].className = 'slide';
currentSlide = (n + slides.length) % slides.length;
slides[currentSlide].className = 'slide showing';
}
//Previous and Next controls
var next = document.getElementById('next');
var previous = document.getElementById('previous');
next.onclick = function() {
nextSlide();
};
previous.onclick = function() {
previousSlide();
};
//Pagination controls
var p = document.getElementById('pagination');
var phtml = '';
for(var i = 0; i < slides.length; i++) {
phtml += '<button></button>'; // create the pagination buttons for each slide
}
p.innerHTML = phtml; //insert the html for the buttons
var pbuttons = p.querySelectorAll('button'); // grab all the buttons
var activeButton = null; // reference to active button
for(var i = 0; i < pbuttons.length; i++) {
pbuttons[i].onclick = (function(n) {
return function() {
if(activeButton)
activeButton.classList.remove('active'); // delete class from old active button
activeButton = this;// change ref, this is current button
activeButton.classList.add('active');// add class for new
goToSlide(n);
};
})(i);
}
#slider {
min-height: 400px;
position: relative;
#slides {
min-height: 400px;
padding: 0;
margin: 0;
list-style-type: none;
.slide {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
opacity: 0;
z-index: 1;
min-height: 400px;
box-sizing: border-box;
background: $black;
color: $white;
display: flex;
align-items: center;
-webkit-justify-content: flex-end;
justify-content: flex-end;
-webkit-transition: opacity 1s;
-moz-transition: opacity 1s;
transition: opacity 1s;
&.showing {
opacity: 1;
z-index: 2;
}
&:nth-of-type(1) {
#include backImage('../images/evbox1.jpg');
}
&:nth-of-type(2){
#include backImage('../images/evbox2.jpg');
}
&:nth-of-type(3) {
#include backImage('../images/evbox3.jpg');
}
}
.slide-description {
width: 500px;
.slide-title {
width: 90%;
font-family: 'Open Sans', sans-serif;
font-size: 44px;
text-shadow: 0 2px 3px rgba($black, .2);
line-height: 1.1em;
margin-bottom: 10px;
}
p {
margin-bottom: 15px;
width: 90%;
font-size: 20px;
font-family: 'Open Sans', sans-serif;
font-weight: 300;
text-shadow: 0 2px 3px rgba($black, .2);
}
.btn {
#include button($blue, $font-color, $shadow-color);
}
}
#include respond-to($mobile) {
#media only screen and (max-width: $mobile) {
.slide:nth-of-type(3) {
background-position: left 0;
}
.slide-description {
height: 100%;
width: 100%;
padding: 8em 5em;
position: static;
text-align: center;
.slide-title {
font-size: 30px;
width: 100%;
}
.btn {
padding: 8px 16px;
}
}
p {
display: none;
}
}
}
}
}
/*Previous and Next Controls*/
.controls {
position: absolute;
top: 42%;
z-index: 10;
background: url('http://www.ev-box.com/Evbox-EN/includes/themes/evbox/assets/images/sprites#2x.png') no-repeat;
height: 50px;
width: 30px;
background-size: 369px 240px;
outline: 0;
border: 0;
cursor: pointer;
}
#previous {
right: 10px;
background-position: -50px -121px;
}
#next {
left: 10px;
background-position: -16px -121px;
}
// Pagination
#pagination {
position: absolute;
bottom: 30px;
right: 50%;
z-index: 10;
button {
border-radius: 50%;
border: 1px solid $white;
background-color: $white;
opacity: .8;
width: 14px;
height: 14px;
min-height: 14px;
border-width: 0;
margin-right: 5px;
&.active {
width: 15px;
height: 15px;
min-height: 15px;
border: 1px solid $white;
background-color: $primary;
opacity: 1;
&:focus {
outline: 0;
}
}
}
}
I updated the javascript as shown below. Use this in your code pen. you can see the diffrence. If you click next and previous button the corresponding pagination will be highlighted by using this javascript
document.addEventListener("DOMContentLoaded", function() {
var slides = document.querySelectorAll('#slides .slide'); // get all the slides
const totalSlides = 2 // Total number of slides count
var currentSlide = 0; // current slide
var previousSlide = totalSlides;
// var slideInterval = setInterval(nextSlide, 1000);
function nextSlide() {
previousSlide = currentSlide
if(totalSlides > currentSlide){
currentSlide += 1
}
else currentSlide = 0
goToSlide();
}
function PreviousSlide() {
if(currentSlide == 0){
previousSlide = currentSlide
currentSlide = totalSlides
}
else{
previousSlide = currentSlide
currentSlide -=1
}
goToSlide();
}
function goToSlide() {
slides[previousSlide].className = 'slide';
slides[currentSlide].className = 'slide showing';
var currentSlideButton = "button"+currentSlide
var previousSlideButton = "button"+previousSlide
document.getElementById(currentSlideButton).classList.add('active');
document.getElementById(previousSlideButton).classList.remove('active');
}
//Previous and Next controls
var next = document.getElementById('next');
var previous = document.getElementById('previous');
next.onclick = function() {
PreviousSlide();
};
previous.onclick = function() {
nextSlide();
};
//Pagination controls
var p = document.getElementById('pagination');
var phtml = '';
for(var i = 0; i < slides.length; i++) {
phtml += '<button id=button'+i+'></button>'; // create the pagination buttons for each slide
}
p.innerHTML = phtml; //insert the html for the buttons
var pbuttons = p.querySelectorAll('button'); // grab all the buttons
var activeButton = null; // reference to active button
for(var i = 0; i < pbuttons.length; i++) {
pbuttons[i].onclick = (function(n) {
return function() {
if(activeButton)
activeButton.classList.remove('active'); // delete class from old active button
activeButton = this;// change ref, this is current button
activeButton.classList.add('active');// add class for new
goToSlide(n);
};
})(i);
}
goToSlide();// Initialising goToSlide method
});