I've made a simple slider that responses the mouseenter event.
The algorithm is when if the user moves its mouse pointer one of Appear menu contents, a div called .slate goes down.
My problem is in Chrome or Opera, when the user zoomed up by using CTRL + Mouse Wheel Up, the .slate is going to spills a bit and goes back up smoothly while Firefox doesn't:
I'm looking for a solution to remove this unwanted re-positioning except not using transition.
I've tried to give the transition more dynamically to resolve the problem. Add the transition when mouse entered to the Appear, remove it when mouse entered to Disappear.
But this one didn't work with an another new issue. The transition is going to ignore when I wag the mouse like this:
Are there any ways to resolve this problem?
CodePen: Original Code / Attempt 2
Snippet (Original):
'use strict';
class Slate {
constructor(header) {
this.header = document.querySelector(header);
this.slate = document.querySelector('.slate');
this.menu = this.header.querySelector('.menu');
this.contents = this.menu.querySelectorAll('.contents');
this.addEvent();
}
addEvent() {
this.contents.forEach((cur, idx) => {
cur.addEventListener('mouseenter', (e) => this.expand(e, idx));
})
}
expand(e, index) {
let lesser = (index < 2),
ternary = {
toggle: (lesser) ? this.slate.classList.add('toggle') : this.slate.classList.remove('toggle')
};
}
}
const proSlate = new Slate('header');
* {
margin: 0;
padding: 0;
font-family: Helvetica;
}
div, section, header {
position: relative;
}
ul, li {
list-style-type: none;
}
header, .slate {
width: 800px;
}
header {
height: 100px;
line-height: 100px;
background-color: rgba(69, 255, 0, .4);
}
.slate {
height: 400px;
line-height: 400px;
text-align: center;
color: white;
background-color: steelblue;
top: -25rem;
transition: top 500ms cubic-bezier(0.455, 0.03, 0.515, 0.955);
z-index: -1;
font-size: 4rem;
}
.menu {
width: 100%;
display: flex;
}
.contents {
margin: 0 20px;
}
.toggle {
top: 0;
}
<header>
<ul class="menu">
<li class="contents">Appear</li>
<li class="contents">Appear</li>
<li class="contents">Disapper</li>
<li class="contents">Disapper</li>
</ul>
</header>
<div class="slate">
CONTEXT OF SLATE
</div>
Instead of using top, go for transform
'use strict';
class Slate {
constructor(header) {
this.header = document.querySelector(header);
this.slate = document.querySelector('.slate');
this.menu = this.header.querySelector('.menu');
this.contents = this.menu.querySelectorAll('.contents');
this.addEvent();
}
addEvent() {
this.contents.forEach((cur, idx) => {
cur.addEventListener('mouseenter', (e) => this.expand(e, idx));
})
}
expand(e, index) {
let lesser = (index < 2),
ternary = {
toggle: (lesser) ? this.slate.classList.add('toggle') : this.slate.classList.remove('toggle')
};
}
}
const proSlate = new Slate('header');
* {
margin: 0;
padding: 0;
font-family: Helvetica;
}
div,
section,
header {
position: relative;
}
ul,
li {
list-style-type: none;
}
header,
.slate {
width: 800px;
}
header {
height: 100px;
line-height: 100px;
background-color: rgba(69, 255, 0, .4);
}
.slate {
height: 400px;
line-height: 400px;
text-align: center;
color: white;
background-color: steelblue;
transform: translateY(-100%);
transition: transform 500ms cubic-bezier(0.455, 0.03, 0.515, 0.955);
z-index: -1;
font-size: 4rem;
}
.menu {
width: 100%;
display: flex;
}
.contents {
margin: 0 20px;
}
.toggle {
transform: translateY(0);
}
<header>
<ul class="menu">
<li class="contents">Appear</li>
<li class="contents">Appear</li>
<li class="contents">Disapper</li>
<li class="contents">Disapper</li>
</ul>
</header>
<div class="slate">
CONTEXT OF SLATE
</div>
Related
I have a mobile menu that includes four list items. When you click on the "Features" list item, another unordered list is supposed to populate below it, and when you click it again, it's supposed to close it.
Here's my issue:
Inside the addEventListener function, I am calling two other functions (displayType and displayTypeCheck) inside the if, and else statement. When I do this and click on the "Features" list item, it opens but does not close when I click it again.
If I don't use the displayType and displayTypeCheck functions in the if and else statement and click on the "Features" list item, the UL will both open and close.
Why does the if and else statement that calls the other two functions not work, and how do I get it to work?
In the provided Javascript code below, the if and else statement that's commented out works, and the block that's not commented out is the code that doesn't entirely work.
const menuIcon = document.querySelector(".mobile-menu-icon");
const mobileMenu = document.querySelector(".mobile-menu");
const closeMenuIcon = document.querySelector(".close-menu-icon");
const featuresMobile = document.querySelector(".features-mobile");
const featuresMobileDropdown = document.querySelector(".features-mobile-dropdown");
const overlay = document.querySelector(".overlay");
function displayType(element, displayValue) {
element.style.display = displayValue;
}
function displayTypeCheck(element, displayValue) {
element.style.display === displayValue;
}
menuIcon.addEventListener("click", function () {
displayType(mobileMenu, 'block');
displayType(overlay, 'block');
});
closeMenuIcon.addEventListener("click", function () {
displayType(mobileMenu, 'none');
displayType(overlay, 'none');
});
featuresMobile.addEventListener("click", function () {
// if (featuresMobileDropdown.style.display === "block") {
// featuresMobileDropdown.style.display = "none";
// } else {
// featuresMobileDropdown.style.display = "block";
// }
if (displayTypeCheck(featuresMobileDropdown, "block")) {
displayType(featuresMobileDropdown, "none");
} else {
displayType(featuresMobileDropdown, "block");
}
});
#import url("https://fonts.googleapis.com/css2?family=Epilogue:wght#500;700&display=swap");
:root {
--almostWhite: hsl(0, 0%, 98%);
--mediumGray: hsl(0, 0%, 41%);
--almostBlack: hsl(0, 0%, 8%);
--navDropDownColor: #e9ecef;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
ul {
list-style: none;
}
body {
min-height: 100vh;
font-family: "Epilogue", sans-serif;
background-color: var(--almostWhite);
}
header {
padding: .9375rem 2.5rem .9375rem 2.5rem;
max-width: 100rem;
margin: auto;
}
header nav {
display: flex;
align-items: center;
justify-content: flex-end;
}
header nav ul li {
cursor: pointer;
}
.register {
border: .125rem solid var(--mediumGray);
padding: .625rem .9375rem;
border-radius: .8125rem;
}
.mobile-menu-icon {
height: 3.125rem;
}
.mobile-menu-icon {
display: block;
cursor: pointer;
}
.mobile-menu .mobile-nav-links {
margin-top: 4.375em;
padding-left: .9375em;
color: var(--mediumGray);
}
.mobile-menu ul li {
padding: .625em;
}
.mobile-menu .mobile-nav-links li ul {
margin-left: .625em;
margin-top: .625em;
display: none;
}
.mobile-menu {
background-color: white;
width: 18.75em;
height: 100vh;
position: absolute;
top: 0;
right: 0;
z-index: 2;
display: none;
}
.close-menu-icon {
margin-left: auto;
margin-right: 1.25em;
margin-top: 1.25em;
display: block;
cursor: pointer;
height: 3.125em;
}
.login-register-mobile-container {
color: var(--mediumGray);
width: 90%;
margin: 3.125em auto;
}
.login-register-mobile-container span {
display: block;
text-align: center;
cursor: pointer;
}
.login-register-mobile-container span:first-child {
margin-bottom: 1.25em;
}
.overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.6);
backdrop-filter: blur(.1875rem);
z-index: 1;
display: none;
}
<header>
<nav>
<img class="mobile-menu-icon" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/b2/Hamburger_icon.svg/2048px-Hamburger_icon.svg.png" alt="" />
<div class="mobile-menu">
<img
class="close-menu-icon"
src="https://cdn4.iconfinder.com/data/icons/user-interface-131/32/close-512.png"
alt=""
/>
<ul class="mobile-nav-links">
<li class="features-mobile">Features
<ul class="features-mobile-dropdown">
<li>Todo List</li>
<li>Calenders</li>
<li>Reminders</li>
<li>Planning</li>
</ul>
</li>
<li class="company-mobile">Company</li>
<li>Careers</li>
<li>About</li>
</ul>
<div class="login-register-mobile-container">
<span class="login">Login</span>
<span class="register">Register</span>
</div>
</div>
</nav>
<div class="overlay"></div>
</header>
You forgot the return statement.
function displayTypeCheck(element, displayValue) {
return element.style.display === displayValue;
}
Otherwise the function will always return undefined which is a falsey value.
Within the displayTypeCheck function, you aren't returning the boolean result of the conditions.
Without the return statement, it is returning void
function displayTypeCheck(element, displayValue) {
return element.style.display === displayValue;
}
I am trying to change the background color of my webpage using a hamburger menu. There are 4 color options on my hamburger menu. I managed to get a change on the background when clicking on the color of my choice. But that change only happens once. When I clicked another color and come back to click that same color from earlier on, it doesn't respond. The color seems to change only once, and not more than that.
The repository to my GitHub code is here: https://github.com/tand100b/Winc_Academy
const changeColorButton1 = document.getElementById("color1");
changeColorButton1.addEventListener("click", function() {
changeClassRedBackground();
});
const changeColorButton2 = document.getElementById("color2");
changeColorButton2.addEventListener("click", function() {
changeClassOrangeBackground();
});
const changeColorButton3 = document.getElementById("color3");
changeColorButton3.addEventListener("click", function() {
changeClassPurpleBackground();
});
const changeColorButton4 = document.getElementById("color4");
changeColorButton4.addEventListener("click", function() {
changeClassGreenBackground();
});
const changeClassRedBackground = function() {
const bodyElement = document.body;
bodyElement.classList.add("red-background");
}
const changeClassOrangeBackground = function() {
const bodyElement = document.body;
bodyElement.classList.add("orange-background");
};
const changeClassPurpleBackground = function() {
const bodyElement = document.body;
bodyElement.classList.add("purple-background");
};
const changeClassGreenBackground = function() {
const bodyElement = document.body;
bodyElement.classList.add("green-background");
};
body {
background-color: pink;
}
.red-background {
background-color: red;
}
.orange-background {
background-color: orange;
}
.purple-background {
background-color: purple;
}
.green-background {
background-color: green;
}
.btn-toggle-nav {
width: 60px;
height: 20%;
background-color: #f98f39;
background-image: url("https://i.stack.imgur.com/tniUv.png");
background-repeat: no-repeat;
background-size: 60%;
background-position: center;
cursor: pointer;
}
.btn-toggle-nav:hover {
opacity: 0.5;
}
.navbar ul {
padding-top: 15px;
/* visibility: hidden; */
}
.navbar ul li {
line-height: 60px;
list-style: none;
background-color: white;
width: 300px;
padding-top: 0px;
padding-top: 0px;
}
.navbar ul li a {
display: block;
height: 60px;
padding: 0 10px;
text-decoration: none;
font-family: arial;
font-size: 16px;
}
.navbar {
background-color: red;
width: 50px;
padding: 0 5px;
height: calc(100vh-60px);
z-index: 1000;
}
.list {
margin-top: 0px;
}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<div class="btn-toggle-nav"></div>
<aside class="navbar">
<ul class="list">
<li><a id="color1" href="#">Red</a></li>
<li><a id="color2" href="#">Orange</a></li>
<li><a id="color3" href="#">Purple</a></li>
<li><a id="color4" href="#">Green</a></li>
</ul>
</aside>
Can someone please look at my code and suggest what I can do?
Firstly, I suggest declaring variable bodyElement only once at the top of the file because each time it would be the same body element:
const bodyElement = document.body
Next, we create function that will check if body has any style classes in its classList. If it's not empty (length more than one) we remove all classes, and do nothing otherwise:
const isBodyHasStyle = () => bodyElement.classList.length ? bodyElement.classList = '' : null
Then, on each button click we going to call our new function:
changeColorButton1.addEventListener("click", function() {
isBodyHasStyle()
changeClassRedBackground();
});
Do the same with other buttons.
You need to make sure that you don't have multiple classes conflicting with each other, also try to DRY your code, here is an alternative I came up with:
const changeColor = (e) => {
const bodyElement = document.querySelector('body');
const colorIdMap = {
"color1": "red-background",
"color2": "orange-background",
"color3": "purple-background",
"color4": "green-background"
}
bodyElement.className = colorIdMap[e.target.id];
}
const btns = document.querySelectorAll('.list li');
btns.forEach(btn => btn.addEventListener('click', changeColor))
An easier way to accomplish this is by setting a data attribute on the background, based on the selected color. Just add a color data value to each of the menu items and set the body background to that color.
const toggleMenu = (event) => {
event.target.closest('.navbar').classList.toggle('open');
};
const changeColor = (event) => {
document.body.dataset.background = event.target.dataset.color;
toggleMenu(event); /* do not call ~ to stay open */
};
document.querySelector('.btn-toggle-nav')
.addEventListener('click', toggleMenu)
document.querySelectorAll('.color-picker')
.forEach(e => e.addEventListener('click', changeColor));
/* CSS reset */
html, body { width: 100%; height: 100%; margin: 0; padding: 0; }
body { display: flex; background-color: #222; }
ul { list-style-type: none; margin: 0; }
body[data-background="red"] { background-color: red }
body[data-background="orange"] { background-color: orange }
body[data-background="purple"] { background-color: purple }
body[data-background="green"] { background-color: green }
body[data-background="default"] { /* Do not set the background-color */ }
a[data-color="red"] { color: red; }
a[data-color="orange"] { color: orange; }
a[data-color="purple"] { color: purple; }
a[data-color="green"] { color: green; }
a[data-color="default"] { color: #222; }
.list {
position: absolute;
display: none; /* hide menu (default) */
flex-direction: column;
gap: 0.5em;
padding: 0.5em;
width: 6em;
left: 2em;
background: #444;
}
.list li a { text-decoration: none; font-weight: bold; }
.list li a:hover { text-decoration: underline; }
.navbar {
position: relative;
width: 2em;
background-color: #444;
}
.navbar.open .list {
display: flex; /* show menu */
}
.btn-toggle-nav {
width: 2em;
height: 2em;
background-image: url("https://i.stack.imgur.com/tniUv.png");
background-repeat: no-repeat;
background-size: 60%;
background-position: center;
cursor: pointer;
}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<aside class="navbar">
<div class="btn-toggle-nav"></div>
<ul class="list">
<li><a class="color-picker" href="#" data-color="red">Red</a></li>
<li><a class="color-picker" href="#" data-color="orange">Orange</a></li>
<li><a class="color-picker" href="#" data-color="purple">Purple</a></li>
<li><a class="color-picker" href="#" data-color="green">Green</a></li>
<li><a class="color-picker" href="#" data-color="default">Default</a></li>
</ul>
</aside>
I've been trying to make a dropdown navigation bar (having the links centered) for the mobile view, with only html and css (separate javascript file isn't needed, as the project isn't that dense).
I think I missed something earlier on, but I can't find the problem anymore. Can someone make it work? Doesn't matter what method you use. If more parts of the code is needed, please inform me.
html navbar section:
<!-- Navigation bar section -->
<header class="navbar">
<div class='nav_container'>
<ion-icon class="mobile-menu-icon" id="mobile-cta" name="menu-outline"></ion-icon>
<nav>
<ion-icon class="mobile-close-icon" id="mobile-exit" name="close-outline"></ion-icon>
<ul class="primary_nav">
<li>Home</li>
<li>About</li>
<li>Portfolio</li>
<li>Contact</li>
</ul>
</nav>
</div>
</header>
script inside html:
<script>
const mobileBtn = document.getElementById('mobile-cta')
nav = document.querySelector('nav')
mobileBtnExit = document.getElementById('mobile-exit');
mobileBtn.addEventListener('click', () => {
nav.classList.toggle('menu-btn');
})
mobileBtnExit.addEventListener('click', () => {
nav.classList.toggle('menu-btn');
})
</script>
scss:
.navbar {
background: black;
.navbar_container {
display: flex;
place-content: space-between;
}
nav{
display: none;
position: fixed;
width: 100%;
height: 58vh;
padding: 1em;
top: 0;
z-index: 999;
background: var(--primary-blue);
ul {
margin-top: 2.1em;
}
li {
a {
display: block;
padding: .9em;
font-size: 2em;
font-weight: 500;
text-align: center;
opacity: 0.85;
&:hover {
opacity: 1;
transition: all 0.4 ease;
}
}
}
}
}
.mobile-close-icon {
position: absolute;
right: 0px;
margin-right: 1em;
cursor: pointer;
font-size: 3em;
color: white;
opacity: 0.85;
&:hover {
opacity: 1;
}
}
.mobile-menu-icon {
cursor: pointer;
color: white;
position: absolute;
right: 0px;
margin-right: 1em;
top: 15px;
width: 40px;
height: 40px;
}
It looks like you haven't defined your const declarations correctly. Try something like below:
<!-- Option 1: Explictly defined `const` definitions -->
<script>
const mobileBtn = document.getElementById('mobile-cta');
const nav = document.querySelector('nav');
const mobileBtnExit = document.getElementById('mobile-exit');
mobileBtn.addEventListener('click', () => {
nav.classList.toggle('menu-btn');
})
mobileBtnExit.addEventListener('click', () => {
nav.classList.toggle('menu-btn');
})
</script>
<!-- Option 2: "Inlined" const definitions -->
<script>
const mobileBtn = document.getElementById('mobile-cta'),
nav = document.querySelector('nav'),
mobileBtnExit = document.getElementById('mobile-exit');
mobileBtn.addEventListener('click', () => {
nav.classList.toggle('menu-btn');
})
mobileBtnExit.addEventListener('click', () => {
nav.classList.toggle('menu-btn');
})
</script>
I am making a hamburger menu that when clicked will show up on the entire screen it works just fine but now I am trying to make it when i click on option in the menu it takes me to the section i want but them it closes i have written this code but it only works on the first option the others don't do anything
const hamburger = document.querySelector(".hamburger");
const navMenu = document.querySelector(".nav_options");
const navMargin = document.querySelector(".sec_about");
const onClick = document.querySelector(".nav_item")
hamburger.addEventListener("click", mobileMenu);
function mobileMenu() {
hamburger.classList.toggle("active");
navMenu.classList.toggle("active");
navMargin.classList.toggle("active");
}
onClick.addEventListener("click", closeham);
function closeham() {
navMenu.classList.toggle("active");
hamburger.classList.toggle("active");
}
/* making the navbar responsive */
.hamburger {
display: none;
margin-right: 20px;
}
.bar {
display: block;
width: 30px;
height: 3px;
margin: 5px auto;
-webkit-transition: all 0.3s ease-in-out;
transition: all 0.3s ease-in-out;
background-color: #fa900f;
}
#media only screen and (max-width: 1000px) {
.nav_options {
position: absolute;
left: -100%;
top: 4rem;
flex-direction: column;
background-color: #000000;
border: solid 15px #fff;
width: 100%;
height: 1000px;
text-align: center;
transition: 0.3s;
box-shadow: 0 10px 27px rgba(0, 0, 0, 0.05);
}
nav ul li a {
color: #fa900f;
}
.nav_options.active {
left: 0;
}
.nav_item {
margin: 3rem 0;
}
.hamburger {
display: block;
cursor: pointer;
}
.hamburger.active .bar:nth-child(2) {
opacity: 0;
}
.hamburger.active .bar:nth-child(1) {
transform: translateY(8px) rotate(45deg);
}
.hamburger.active .bar:nth-child(3) {
transform: translateY(-8px) rotate(-45deg);
}
.sec_about.active {
margin-top: 35rem;
}
}
<header>
<nav>
<img src="/images/Logo.png" alt="Logo">
<ul class="nav_options">
<li class="nav_item"><a class="nav_item" href="#About"><About></a></li>
<li class="nav_item"><a class="nav_item" href="#Skills"><Skill></a></li>
<li class="nav_item"><a class="nav_item" href="#ResumeWork"><Work></a></li>
<li class="nav_item"><a class="nav_item" href="#ResumeWork"><Resume></a></li>
<li class="nav_item"><a class="nav_item" href="#Contact"><Contact></a></li>
</ul>
<div class="hamburger">
<span class="bar"></span>
<span class="bar"></span>
<span class="bar"></span>
</div>
</nav>
</header>
You have a tiny error in your code.
The function querySelector() captures only one item that pass the requirements. You need to use querySelctorAll() to assign a click event. Based on your posted code here your new javascript:
const hamburger = document.querySelector(".hamburger");
const navMenu = document.querySelector(".nav_options");
const navMargin = document.querySelector(".sec_about");
//Here was a mistake
const onClick = document.querySelectorAll(".nav_options li.nav_item");
hamburger.addEventListener("click", mobileMenu);
function mobileMenu() {
hamburger.classList.toggle("active");
navMenu.classList.toggle("active");
navMargin.classList.toggle("active");
}
//Addational change, because querySelectorAll returns an array of elements
for (i = 0; i < onClick.length;i++) {
onClick[i].addEventListener("click", closeham);
}
function closeham() {
navMenu.classList.toggle("active");
hamburger.classList.toggle("active");
}
I am trying to a make carousel using pure Javascript. I successfully manage to slide the carousel and have created left and right buttons.
I took my slide functions and added them to the button on-click event-listener, but I have problems when I implement the function on my buttons. It does not behave as expected. My code is below, how can I fix this?
const images = document.getElementById('imgs'); //here
const allImages = document.querySelectorAll('#imgs img');
const leftBtn = document.getElementById('left');
const rightBtn = document.getElementById('right');
let index = 0;
function changeSliderPage() {
const dot = [...document.getElementsByClassName('star')];
index++;
if (index > allImages.length - 1) {
index = 0
}
imgs.style.transform = `translateX(${-index * 500}px)`;
dot.forEach((dot, i) => {
if (i === index) {
dot.classList.add('active')
} else {
dot.classList.remove('active')
}
});
};
allImages.forEach(i => {
const elem = document.createElement('div');
elem.classList.add('star');
document.body.appendChild(elem)
});
rightBtn.onclick = () => {
changeSliderPage(index + 1);
}
leftBtn.onclick = () => {
changeSliderPage(index - 1);
}
let x = setInterval(changeSliderPage, 100000);
images.onmouseover = () => {
clearInterval(x)
}
images.onmouseout = () => {
x = setInterval(changeSliderPage, 2000);
}
*{
box-sizing: border-box;
}
body {
margin: 0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
.carousel {
overflow: hidden;
width: 500px;
height: 500px;
box-shadow: 2px 2px 5px rgba(0, 0, 0, .3);
border-radius: 5px;
}
.image-container {
display: flex;
transition: transform 300ms linear;
transform: translateX(0);
}
img {
width:500px;
height: 500px;
object-fit: cover;
}
.star{
cursor: pointer;
height: 15px;
width: 15px;
margin: 0 10px;
border-radius: 50%;
display: inline-block;
transition: background-color 0.6s ease;
background-color: #eeeeee;
}
.star.active{
background-color: red;
}
button{
cursor: pointer;
position: relative;
font-size: 18px;
transition: 0.6s ease;
user-select: none;
height: 50px;
width: 40px;
display: flex;
justify-content: center;
align-items: center;
align-content: center;
top: calc(50% - 25px);
}
button:hover {
background-color: rgba(0,0,0,0.8);
};
button.left {
border-radius: 3px 0 0 3px;
right: 0;
}
button.left {
border-radius: 3px 0 0 3px;
left: 0;
}
<button id="left">❮</button>
<button id="right">❯</button>
<div class="carousel">
<div class="image-container" id="imgs" >
<img src="https://images.unsplash.com/photo-1599736375341-51b0a848f3c7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
<img src="https://images.unsplash.com/photo-1516026672322-bc52d61a55d5?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
<img src="https://images.unsplash.com/photo-1573081586928-127ecc7948b0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
<img src="https://images.unsplash.com/flagged/photo-1572850005109-f4ac7529bf9f?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
</div>
</div>
Logic that I use with carousels:
for example you have 4 images:
[1][2][3][4]
I have an animation for sliding every image, I add 5th image which is same as image no 1:
[1][2][3][4][1]
Imagine cursor which shows what image is currently displayed, Ill mark cursor as ! !
So at begin:
[!1!][2][3][4][1]
Now the slider moves on...
[1][!2!][3][4][1]
etc...
It moves to last image:
[1][2][3][4][!1!]
And now it has to move under the hood from last image to first image, but without any animation so the whole change is not visible by user:
[!1!][2][3][4][5]
This way you can get inifinite carousel, just need to check in javascript if current image is last one and you want to slide right -> no animation. Same if you are on 1st image and want to slide left.