I want to add a transition animation while image is changing. But transition doesn't work. As if no transition animation has been added
How transition style does work in this case?
( If there is way to from left to right animation like image strip, it will be better than ease animation )
Js, Css, Html codes :
var slides = document.querySelectorAll('.slide');
var next = document.getElementById('next');
var back = document.getElementById('back');
let currentSlide = 0;
var manualNav = function(manual) {
slides.forEach((slide) => {
slide.classList.remove('active');
});
slides[manual].classList.add('active');
}
next.addEventListener('click', function() {
if (currentSlide != slides.length - 1) {
currentSlide++;
manualNav(currentSlide);
}
})
back.addEventListener('click', function() {
if (currentSlide != 0) {
currentSlide--;
manualNav(currentSlide);
}
})
var repeat = function(activeClass) {
let active = document.getElementsByClassName('active');
let i = 1;
var repeater = () => {
setTimeout(function() {
[...active].forEach((activeSlide) => {
activeSlide.classList.remove('active');
});
slides[i].classList.add('active');
i++;
if (slides.length == i) {
i = 0;
}
if (i >= slides.length) {
return;
}
repeater();
}, 10000);
}
repeater();
}
repeat();
.gallery {
width: 50%;
height: 340px;
display: flex;
align-items: center;
flex-direction: column;
}
.gallery .content {
position: relative;
width: 564px;
height: 297px;
}
.gallery .content .slide {
display: none;
transition: all 1s ease-in;
}
.gallery .content .slide img {
width: 100%;
height: 297px;
object-fit: cover;
}
.gallery .content .slide.active {
display: block;
}
.gallery .content .firstSvg {
position: absolute;
right: 80px;
bottom: 24px;
cursor: pointer;
height: 50px;
width: 50px;
background-color: orange;
}
.gallery .content .lastSvg {
cursor: pointer;
position: absolute;
right: 24px;
bottom: 24px;
height: 50px;
width: 50px;
background-color: wheat;
}
<div class="gallery" id="gallery">
<div class="content">
<div class="slide active">
<img src="https://i.picsum.photos/id/250/536/354.jpg?hmac=qb3khzryKWU1ECPob2_1mYZLumW5eJTLSmhJzi1VVSI" alt="gallery">
</div>
<div class="slide">
<img src="https://i.picsum.photos/id/868/536/354.jpg?hmac=ZcbB7ABIgl6LS5B1wxkzJ_dxJFgNmCsODUTfxM5GdRk" alt="gallery">
</div>
<div class="slide">
<img src="https://i.picsum.photos/id/441/536/354.jpg?hmac=qHaUqO3vqlz-C811TXJPtRw-FV4ciRCazlDZb1gdodg" alt="gallery">
</div>
<div class="firstSvg" id="back">back</div>
<div class="lastSvg" id="next">next</div>
</div>
</div>
var slides = document.querySelectorAll('.slide');
var next = document.getElementById('next');
var back = document.getElementById('back');
let currentSlide = 0;
var manualNav = function(manual) {
slides.forEach((slide) => {
slide.classList.remove('active');
});
slides[manual].classList.add('active');
}
next.addEventListener('click', function() {
if (currentSlide != slides.length - 1) {
currentSlide++;
manualNav(currentSlide);
}
})
back.addEventListener('click', function() {
if (currentSlide != 0) {
currentSlide--;
manualNav(currentSlide);
}
})
var repeat = function(activeClass) {
let active = document.getElementsByClassName('active');
let i = 1;
var repeater = () => {
setTimeout(function() {
[...active].forEach((activeSlide) => {
activeSlide.classList.remove('active');
});
slides[i].classList.add('active');
i++;
if (slides.length == i) {
i = 0;
}
if (i >= slides.length) {
return;
}
repeater();
}, 10000);
}
repeater();
}
repeat();
.gallery {
width: 50%;
height: 340px;
display: flex;
align-items: center;
flex-direction: column;
}
.gallery .content {
position: relative;
width: 564px;
height: 297px;
}
.gallery .content .slide {
height: 0;
width: 0;
opacity: 0;
transition: all 1s ease-in;
}
.gallery .content .slide img {
width: 100%;
height: 297px;
object-fit: cover;
}
.gallery .content .slide.active {
height: 100%;
width: 100%;
opacity: 1;
}
.gallery .content .firstSvg {
position: absolute;
right: 80px;
bottom: 24px;
cursor: pointer;
height: 50px;
width: 50px;
background-color: orange;
}
.gallery .content .lastSvg {
cursor: pointer;
position: absolute;
right: 24px;
bottom: 24px;
height: 50px;
width: 50px;
background-color: wheat;
}
<div class="gallery" id="gallery">
<div class="content">
<div class="slide active">
<img src="https://i.picsum.photos/id/250/536/354.jpg?hmac=qb3khzryKWU1ECPob2_1mYZLumW5eJTLSmhJzi1VVSI" alt="gallery">
</div>
<div class="slide">
<img src="https://i.picsum.photos/id/868/536/354.jpg?hmac=ZcbB7ABIgl6LS5B1wxkzJ_dxJFgNmCsODUTfxM5GdRk" alt="gallery">
</div>
<div class="slide">
<img src="https://i.picsum.photos/id/441/536/354.jpg?hmac=qHaUqO3vqlz-C811TXJPtRw-FV4ciRCazlDZb1gdodg" alt="gallery">
</div>
<div class="firstSvg" id="back">back</div>
<div class="lastSvg" id="next">next</div>
</div>
</div>
Animations don't work with display property
When you are trying to change display: none; to display:block when a silde is active, browser won't recognise this as a transition event hence nothing happens.
Instead you can try using the changes below to create a fade in animation
Changes
.gallery .content .slide {
height: 0;
width: 0;
opacity: 0;
transition: all 1s ease-in;
}
.gallery .content .slide.active {
height: 100%;
width: 100%;
opacity: 1;
}
Initially silde do not have height,width,opacity which makes them 'invisible'.
But when silde is set toactive the above 3 properties are changed and that triggers an animation which in this case is transition: all 1s ease-in;
Related
I created a simple gallery with images resized on click and added "x" to image containers which remove the class (.bigger). However, I'm trying to figure out how to add another class (.invisible) that will remove "x" when the selected image has no class (.bigger). Can you help out a beginner coder?
How to make a condition: if an image DOES NOT have class .bigger, add class .invisible (to the cross)? I'm really grateful for any help.
const imgList = document.querySelectorAll("img");
const crosses = document.querySelectorAll(".imgContainer span");
for (let i = 0; i < imgList.length; i++) {
imgList[i].addEventListener("click", function() {
imgList.forEach((el) => el.classList.remove("bigger"));
imgList[i].classList.add("bigger");
});
}
for (let x = 0; x < crosses.length; x++) {
crosses[x].addEventListener("click", function() {
imgList.forEach((el) => el.classList.remove("bigger"));
crosses[x].classList.remove("invisible");
});
}
if (imgList[i].classList.contains("")) {
crosses[x].classList.add("invisible");
}
img {
width: 150px;
height: 120px;
object-fit: cover;
margin: 0 1rem;
opacity: 0.5;
transition: all 0.2s;
}
img:hover {
opacity: 1;
}
.imgContainer {
position: relative;
}
.imgContainer span {
position: absolute;
top: -5px;
right: 0;
cursor: pointer;
display: block;
width: 15px;
height: 15px;
background-color: transparent;
text-align: center;
line-height: 15px;
font-size: 30px;
}
.bigger {
width: 500px;
height: auto;
opacity: 1;
}
.invisible {
display: none;
}
<div class="imgContainer">
<span>×</span>
<img src="img1.jpg" alt="Tokyo1" />
</div>
<div class="imgContainer">
<span>×</span>
<img src="img2.jpg" alt="Tokyo2" />
</div>
<div class="imgContainer">
<span>×</span>
<img src="img3.jpg" alt="Tokyo3" />
</div>
If you iterate over the .imgContainer, you can more easily access the corresponding img and span.
Additionally, you can change the invisiblecss class to more specific .imgContainer span.invisible because .imgContainer span {display: block} would overwrite it.
const imgList = document.querySelectorAll(".imgContainer img");
const crossList = document.querySelectorAll(".imgContainer span");
document.querySelectorAll(".imgContainer").forEach((container) => {
const img = container.querySelector("img");
const cross = container.querySelector("span");
img.addEventListener("click", function () {
// Reset the classes of all images and spans.
imgList.forEach((el) => el.classList.remove("bigger"));
crossList.forEach((el) => el.classList.add("invisible"));
// make the image bigger and show the cross.
img.classList.add("bigger");
cross.classList.remove("invisible");
});
cross.addEventListener("click", function () {
img.classList.remove("bigger");
cross.classList.add("invisible");
});
});
img {
width: 150px;
height: 120px;
object-fit: cover;
margin: 0 1rem;
opacity: 0.5;
transition: all 0.2s;
}
img:hover {
opacity: 1;
}
.imgContainer {
position: relative;
}
.imgContainer span {
position: absolute;
top: -5px;
right: 0;
cursor: pointer;
display: block;
width: 15px;
height: 15px;
background-color: transparent;
text-align: center;
line-height: 15px;
font-size: 30px;
}
.imgContainer span.invisible {
display: none;
}
.bigger {
width: 500px;
height: auto;
opacity: 1;
}
<div class="imgContainer">
<span class="invisible">×</span>
<img src="https://via.placeholder.com/300" alt="Tokyo1" />
</div>
<div class="imgContainer">
<span class="invisible">×</span>
<img src="https://via.placeholder.com/300" alt="Tokyo2" />
</div>
<div class="imgContainer">
<span class="invisible">×</span>
<img src="https://via.placeholder.com/300" alt="Tokyo3" />
</div>
const imgList = document.querySelectorAll("img");
const crosses = document.querySelectorAll(".imgContainer span");
for (let i = 0; i < imgList.length; i++) {
imgList[i].addEventListener("click", function() {
imgList.forEach((el) => el.classList.remove("bigger"));
this.classList.add("bigger");
changeAction();
});
}
for (let x = 0; x < crosses.length; x++) {
crosses[x].addEventListener("click", function() {
imgList.forEach((el) => el.classList.remove("bigger"));
this.classList.remove("invisible");
});
}
function changeAction() {
for (let i = 0; i < imgList.length; i++) {
if (imgList[i].classList.contains("")) {
crosses[x].classList.add("invisible");
}
}
}
img {
width: 150px;
height: 120px;
object-fit: cover;
margin: 0 1rem;
opacity: 0.5;
transition: all 0.2s;
}
img:hover {
opacity: 1;
}
.imgContainer {
position: relative;
}
.imgContainer span {
position: absolute;
top: -5px;
right: 0;
cursor: pointer;
display: block;
width: 15px;
height: 15px;
background-color: transparent;
text-align: center;
line-height: 15px;
font-size: 30px;
}
.bigger {
width: 500px;
height: auto;
opacity: 1;
}
.invisible {
display: none;
}
<div class="imgContainer">
<span>×</span>
<img src="img1.jpg" alt="Tokyo1" />
</div>
<div class="imgContainer">
<span>×</span>
<img src="img2.jpg" alt="Tokyo2" />
</div>
<div class="imgContainer">
<span>×</span>
<img src="img3.jpg" alt="Tokyo3" />
</div>
In the code below I want to add 1 to the page variable but every time I click on next button it adds 2 to the variable.
Code in Codepen
var slides = document.querySelectorAll('.slides');
var dots = document.querySelectorAll('.dot');
var page = 0;
function Swiper(page) {
if (page > slides.length) page = 0;
if (page < 0) page = slides.length;
for (let i = 0; i < slides.length; i++) {
slides[i].classList.remove('active');
}
slides[page].classList.add('active');
for (let i = 0; i < dots.length; i++) {
dots[i].classList.remove('active-dot');
}
dots[page].classList.add('active-dot');
for (let i = 0; i < dots.length; i++) {
dots[i].classList.remove('active-dot');
}
dots[page].classList.add('active-dot');
}
function Slider(slider) {
console.log(page)
console.log(slider)
Swiper(page += slider);
console.log(page += slider)
}
function currentSlide(pagination) {
Swiper(page = pagination);
}
* {
font-family: Raleway;
box-sizing: border-box;
outline: none;
}
body {
min-height: 100vh;
margin: 0;
padding: 16px;
}
/* body>h1,body>h2,body>h3,body>h4,body>h5,body>h6,body>p{
padding-left: 16px;
.btnload:hover{
background-color: #4169E1;
} */
.flexbox {
display: flex;
flex-wrap: wrap;
}
.col-25 {
flex: 25%;
}
.col-50 {
flex: 50%;
}
.col-75 {
flex: 75%;
}
.col-100 {
flex: 100%;
}
button,
input {
outline: none;
}
.container {
max-width: 1000px;
position: relative;
margin-left: auto;
margin-right: auto;
}
.slides {
width: 100%;
height: 100%;
position: absolute;
display: none;
animation: slide 0.4s ease;
}
#keyframes slide {
0% {
opacity: 0.2
}
100% {
opacity: 1
}
}
.active {
display: block;
}
.slides .page-number {
position: absolute;
top: 0;
left: 0;
padding: 12px 8px;
color: white;
}
.slides .desc {
color: white;
position: absolute;
top: 310px;
left: 50%;
}
img {
width: 100%;
height: auto;
}
.container a {
padding: 16px;
color: white;
text-decoration: none;
transition: 0.4s;
font-size: 20px;
top: 150px;
position: absolute;
}
img {
width: 100%;
height: auto;
}
.container a:hover {
background-color: rgba(0, 0, 0, 0.616);
}
.container #right-slide {
right: 0px;
}
.container #left-slide {
left: 0px;
}
.pagination {
display: flex;
max-width: 1000px;
height: 100px;
position: relative;
top: 380px;
justify-content: center;
margin-left: auto;
margin-right: auto;
}
.pagination .dot {
border-radius: 50%;
height: 15px;
width: 15px;
cursor: pointer;
margin: 2px;
transition: 0.6s;
}
.pagination .dot:hover {
background-color: rgb(138, 138, 138);
}
.dot {
background-color: #ddd;
}
.active-dot {
background-color: rgb(138, 138, 138);
}
.no-active {
background-color: #ddd;
}
<div class="container">
<div class="slides active">
<div class="page-number">1/4</div>
<img src="https://www.w3schools.com/howto/img_nature_wide.jpg" alt="">
<div class="desc">Caption One</div>
</div>
<div class="slides">
<div class="page-number">2/4</div>
<img src="https://www.w3schools.com/howto/img_snow_wide.jpg" alt="">
<div class="desc">Caption Two</div>
</div>
<div class="slides">
<div class="page-number">3/4</div>
<img src="https://www.w3schools.com/howto/img_mountains_wide.jpg" alt="">
<div class="desc">Caption Three</div>
</div>
<div class="slides">
<div class="page-number">4/4</div>
<img src="Images/img_mountains_wide.jpg" alt="">
<div class="desc">Caption Four</div>
</div>
<a onclick="Slider(-1)" id="left-slide" href="#">❮</a>
<a onclick="Slider(+1)" id="right-slide" href="#">❯</a>
</div>
<div class="pagination">
<span class="dot dot-color active-dot" onclick="currentSlide(0, event)"></span>
<span class="dot dot-color" onclick="currentSlide(1, event)"></span>
<span class="dot dot-color" onclick="currentSlide(2, event)"></span>
<span class="dot dot-color" onclick="currentSlide(3, event)"></span>
</div>
Swiper(page += slider);
console.log(page += slider)
First you add slider to page (updating the value of page) and pass the result to Swiper.
Then you add slider to (the new value of) page (updating the value of page again) and pass the result to console.log.
As a rule of thumb, combining operations that modify variables with operations that pass them to functions is a good way to confuse yourself.
You might want to split out the actions for clarity.
page += slider;
Swiper(page);
console.log(page);
I think because of this line console.log(page += slider)
It makes the page increase 2 times
function Slider(slider) {
console.log(page)
console.log(slider)
Swiper(page += slider);
console.log(page += slider) // <<<--------------- This line
}
I have a small problem. Div slides and reaching end it's quickly show div 1 without pause. Div 5 cannot see.
$(function(){
var width = '100vw';
var speed = 1500;
var pause = 3000;
var current = 1;
var $slider = $('.slider');
var $slides = $slider.find('.slides');
var $slide = $slides.find('.slide');
setInterval(function(){
$slides.animate({'margin-left': '-='+width}, speed, function(){
current++;
if(current == $slide.length){
$slides.css('margin-left', 0);
current = 1;
}
});
}, pause);
});
But if I add delay
if(current == $slide.length){
$(this).delay(pause).queue(function(){
$slides.css('margin-left', 0);
});
current = 1;
}
$(function(){
var width = '100vw';
var speed = 1500;
var pause = 3000;
var current = 1;
var $slider = $('.slider');
var $slides = $slider.find('.slides');
var $slide = $slides.find('.slide');
setInterval(function(){
$slides.animate({'margin-left': '-='+width}, speed, function(){
current++;
if(current == $slide.length){
$(this).delay(pause).queue(function(){
$slides.css('margin-left', 0);
});
current = 1;
}
});
}, pause);
});
.slider {
width: 100%;
height:auto;
text-align: center;
overflow: hidden;
}
.slides {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
-webkit-overflow-scrolling: touch;
/*
scroll-snap-points-x: repeat(300px);
scroll-snap-type: mandatory;
*/
}
.slides::-webkit-scrollbar {
width: 1px;
height: 10px;
}
.slides::-webkit-scrollbar-thumb {
background: #bbb;
}
.slides::-webkit-scrollbar-track {
background: transparent;
}
.slides > div {
scroll-snap-align: start;
flex-shrink: 0;
width: 100vw;
height: 100vh;
background: #eee;
transform-origin: center center;
transform: scale(1);
transition: transform 0.5s;
position: relative;
display: flex;
justify-content: center;
align-items: center;
font-size: 100px;
}
.slides > div:target {
/* transform: scale(0.8); */
}
.author-info {
background: rgba(0, 0, 0, 0.75);
color: white;
padding: 0.75rem;
text-align: center;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
margin: 0;
}
.author-info a {
color: white;
}
img {
object-fit: cover;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.slider > a {
display: inline-flex;
width: 1.5rem;
height: 1.5rem;
background: white;
text-decoration: none;
align-items: center;
justify-content: center;
margin: 0 0 0.5rem 0;
position: relative;
border:1px solid green;
}
.slider > a:active {
top: 1px;
}
.slider > a:focus {
background: #666;
}
/* Don't need button navigation */
#supports (scroll-snap-type) {
.slider > a {
display: none;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="slider">
<div class="slides">
<div id="slide-1" class="slide">Slide 1</div>
<div id="slide-2" class="slide">Slide 2</div>
<div id="slide-3" class="slide">Slide 3</div>
<div id="slide-4" class="slide">Slide 4</div>
<div id="slide-5" class="slide">Slide 5</div>
</div>
</div>
It's show Div 5 like it needed, but after showing div 1 it's not sliding anymore.
So what can I do to keep looping and shows each div given time?
Maybe someone can show how can make slider slide backwards after reaching last div and slides back to div one?
First : BAD solution for your problem : ( go to Second)
Your animation code stucks in a queue once the current == $slide.length , you should pass the next function as argument in the queue calback then use next() to trigger other function . as below :
if(current == $slide.length){
$(this).delay(pause).queue(function(next){ //<--- here next argument
$slides.css('margin-left', 0);
next(); // <----- next call
});
current = 1;
}
but this will not make the annimation work as expected
Second : proper simple solution
What I suggest is, set the animation left value as variable, then check if it's the last so slide to 0 other wise continue left view-width sliding
See working snippet :
$(function(){
var width = '100vw';
var speed = 1500;
var pause = 3000;
var current = 1;
var $slider = $('.slider');
var $slides = $slider.find('.slides');
var $slide = $slides.find('.slide');
var leftAnnime = '-='+width;
setInterval(function(){
$slides.animate({'margin-left': leftAnnime }, speed, function(){
current++;
if( current == $slide.length ) {
leftAnnime = 0;
current = 0;
} else {
leftAnnime = '-='+width;
}
});
}, pause);
});
.slider {
width: 100%;
height:auto;
text-align: center;
overflow: hidden;
}
.slides {
display: flex;
overflow-x: hidden;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
-webkit-overflow-scrolling: touch;
/*
scroll-snap-points-x: repeat(300px);
scroll-snap-type: mandatory;
*/
}
.slides::-webkit-scrollbar {
width: 1px;
height: 10px;
}
.slides::-webkit-scrollbar-thumb {
background: #bbb;
}
.slides::-webkit-scrollbar-track {
background: transparent;
}
.slides > div {
scroll-snap-align: start;
flex-shrink: 0;
width: 100vw;
height: 100vh;
background: #eee;
transform-origin: center center;
transform: scale(1);
transition: transform 0.5s;
position: relative;
display: flex;
justify-content: center;
align-items: center;
font-size: 100px;
}
.slides > div:target {
/* transform: scale(0.8); */
}
.author-info {
background: rgba(0, 0, 0, 0.75);
color: white;
padding: 0.75rem;
text-align: center;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
margin: 0;
}
.author-info a {
color: white;
}
img {
object-fit: cover;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.slider > a {
display: inline-flex;
width: 1.5rem;
height: 1.5rem;
background: white;
text-decoration: none;
align-items: center;
justify-content: center;
margin: 0 0 0.5rem 0;
position: relative;
border:1px solid green;
}
.slider > a:active {
top: 1px;
}
.slider > a:focus {
background: #666;
}
/* Don't need button navigation */
#supports (scroll-snap-type) {
.slider > a {
display: none;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="slider">
<div class="slides">
<div id="slide-1" class="slide">Slide 1</div>
<div id="slide-2" class="slide">Slide 2</div>
<div id="slide-3" class="slide">Slide 3</div>
<div id="slide-4" class="slide">Slide 4</div>
<div id="slide-5" class="slide">Slide 5</div>
</div>
</div>
I have used this tutorial to create a cube of images that move as a slideshow.
https://webdevtrick.com/css-3d-cube-carousel/?unapproved=16788&moderation-hash=ec78aa2bd99b49552d07f0ec60049b18#comment-16788
see what is doing https://files.fm/u/s2ywz7my
I have managed this to be automatically moved using setInterval. When the cube reached the fourth image. It moved back to the first one.
jQuery file
<script>
/** Code By Webdevtrick ( https://webdevtrick.com ) **/
var $carousel = $('.carousel'),currentSlide, nextSlide;
setInterval( function ()
{
currentSlide = $carousel.attr('data-slide');
nextSlide = +currentSlide === 4 ? 1 : +currentSlide + 1;
$carousel.attr('data-slide', nextSlide);
}
, 2000);
</script>
I want the cube to continue sliding to the left and also as it is moving around itself.
By adding some CSS and modify in JS, you can loop this cube slider. But it's animating by changing data-slide value and apply CSS to rotate cube. It's not dynamic slider.
Here is working Demo
$(document).ready(function() {
var $carousel = $('.carousel'),
currentSlide, nextSlide;
$('.next').click(function() {
if(!$carousel.hasClass('sliding')){
currentSlide = $carousel.attr('data-slide');
nextSlide = +currentSlide === 5 ? 0 : +currentSlide + 1;
$carousel.attr('data-slide', nextSlide);
$carousel.addClass('sliding');
}
$carousel.on('transitionend', function(){
if(nextSlide == 5){
$carousel.css('transition', 'none');
$carousel.attr('data-slide', 1);
setTimeout(function(){
$carousel.removeAttr('style');
},10);
}
$carousel.removeClass('sliding');
});
});
$('.prev').click(function() {
if(!$carousel.hasClass('sliding')){
currentSlide = $carousel.attr('data-slide');
nextSlide = +currentSlide === 0 ? 5 : +currentSlide - 1;
$carousel.attr('data-slide', nextSlide);
$carousel.addClass('sliding');
}
$carousel.on('transitionend', function(){
if(nextSlide == 0){
$carousel.css('transition', 'none');
$carousel.attr('data-slide', 4);
setTimeout(function(){
$carousel.removeAttr('style');
},10);
}
$carousel.removeClass('sliding');
});
});
});
/** Code By Webdevtrick ( https://webdevtrick.com ) **/
*, *:before, *:after {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
html, body {
width: 100%;
height: 100%;
}
body {
margin-top: 200px;
background: #333;
font-family: 'Staatliches', cursive;
font-size: 2em;
line-height: 1.5;
}
.container {
width: 90%;
max-width: 1200px;
margin: 0 auto;
padding-bottom: 5em;
perspective: 100em;
}
.carousel {
position: relative;
width: 15em;
height: 15em;
margin: 0 auto;
transform-style: preserve-3d;
transition: transform 0.5s ease;
}
.carousel[data-slide="0"] {
transform: rotateY(90deg);
}
.carousel[data-slide="1"] {
transform: rotateY(0deg);
}
.carousel[data-slide="2"] {
transform: rotateY(-90deg);
}
.carousel[data-slide="3"] {
transform: rotateY(-180deg);
}
.carousel[data-slide="4"] {
transform: rotateY(-270deg);
}
.carousel[data-slide="5"] {
transform: rotateY(-360deg);
}
.slides {
position: absolute;
width: 15em;
height: 15em;
background: white;
}
.slides img {
width: 100%;
}
.back, .slides:nth-child(3) {
transform: translateZ(-7.5em) rotateY(180deg);
}
.right, .slides:nth-child(2) {
transform: rotateY(-270deg) translateX(7.5em);
transform-origin: top right;
}
.left, .slides:nth-child(4) {
transform: rotateY(270deg) translateX(-7.5em);
transform-origin: center left;
}
.front, .slides:nth-child(1) {
transform: translateZ(7.5em);
}
.next, .prev {
position: absolute;
top: 50%;
right: 0;
width: 6em;
margin-top: -2.5em;
border-radius: 3px;
background: #212121;
text-align: center;
line-height: 3;
letter-spacing: 5px;
color: white;
transform: translateY(-50%);
cursor: pointer;
}
.prev:hover {
background: #e60023;
}
.prev {
left: 0;
}
.next:hover {
background: #e60023;
}
.cf:before, .slides:before,
.cf:after,
.slides:after {
content: " ";
display: table;
}
.cf:after, .slides:after {
clear: both;
}
.cf, .slides {
*zoom: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="carousel" data-slide="1">
<div class="slides">
<img src="https://picsum.photos/700/700?random=1" />
</div>
<div class="slides">
<img src="https://picsum.photos/700/700?random=2" />
</div>
<div class="slides">
<img src="https://picsum.photos/700/700?random=3" />
</div>
<div class="slides">
<img src="https://picsum.photos/700/700?random=4" />
</div>
</div>
<div class="next">NEXT ⇨</div>
<div class="prev">⇦ PREV</div>
</div>
You can trigger next button in setInterval function to slide cube automatically. by adding.
setInterval( function () {
$('.next').trigger('click');
},2000);
I am just playing around trying to get a simple 3 slide slider working but run into some issues with the javascript. All i want to happen is on click of the slider colour i would like the current slider to slide out and the selected one to slide in. I am trying to do it by adding an active class to the slider number that I have clicked to show. I just cant quite work out where I have gone wrong. I don't want to use jQuery as I am trying to learn vanilla javascript.
Thanks as always
window.onload = onPageLoad();
function onPageLoad() {
document.querySelector('.red').classList.add('active');
};
document.querySelector('.box').addEventListener('click', function() {
document.querySelector('.red').classList.toggle('active');
document.querySelector('.green').classList.toggle('active');
document.querySelector('.yellow').classList.toggle('active');
});
* {
padding: 0;
margin: 0;
}
.main__wrapper {
position: relative;
width: 100%;
height: 100vh;
overflow: hidden;
}
.red,
.green,
.yellow {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 2;
transform: translateX(-100%);
transition: transform 1.2s;
}
.red {
background-color: red;
}
.green {
background-color: green;
}
.yellow {
background-color: yellow;
}
.active {
transform: translateX(0) !important;
transition: transform 1s !important;
}
.slide__select {
position: absolute;
bottom: 0;
right: 0;
width: 60%;
height: 20%;
z-index: 10;
display: flex;
}
.box {
position: relative;
flex: 1 0 0;
color: $color-white;
display: flex;
align-items: center;
cursor: pointer;
background-color: #A68D71;
}
.box span {
display: block;
position: relative;
z-index: 11;
}
.box::after {
content: "";
position: absolute;
top: 0;
left: 0;
background-color: yellow;
width: 100%;
height: 0;
transition: height .3s;
}
.box:hover::after {
height: 100%;
transition: height .3s;
}
<div class="main__wrapper">
<section class="red">
</section>
<section class="green">
</section>
<section class="yellow">
</section>
<div class="slide__select">
<div class="box">
<span>red</span>
</div>
<div class="box">
<span>green</span>
</div>
<div class="box">
<span>yellow</span>
</div>
</div>
</div>
You're only adding an event listener to the first box and you're toggling every box's active class in order, and the last one is yellow, so you result with a yellow background.
querySelector returns the first DOM element it finds, which is the red box.
For the functionality that you want, you have to add event listeners to each box (querySelectorAll)
window.onload = onPageLoad();
function onPageLoad() {
document.querySelector('.red').classList.add('active');
};
document.querySelector('.redbox').addEventListener('click', function() {
document.querySelector('.red').classList.add('active');
document.querySelector('.green').classList.remove('active');
document.querySelector('.yellow').classList.remove('active');
});
document.querySelector('.greenbox').addEventListener('click', function() {
document.querySelector('.red').classList.remove('active');
document.querySelector('.green').classList.add('active');
document.querySelector('.yellow').classList.remove('active');
});
document.querySelector('.yellowbox').addEventListener('click', function() {
document.querySelector('.red').classList.remove('active');
document.querySelector('.green').classList.remove('active');
document.querySelector('.yellow').classList.add('active');
});
* {
padding: 0;
margin: 0;
}
.main__wrapper {
position: relative;
width: 100%;
height: 100vh;
overflow: hidden;
}
.red,
.green,
.yellow {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 2;
transform: translateX(-100%);
transition: transform 1.2s;
}
.red {
background-color: red;
}
.green {
background-color: green;
}
.yellow {
background-color: yellow;
}
.active {
transform: translateX(0) !important;
transition: transform 1s !important;
}
.slide__select {
position: absolute;
bottom: 0;
right: 0;
width: 60%;
height: 20%;
z-index: 10;
display: flex;
}
.box {
position: relative;
flex: 1 0 0;
color: $color-white;
display: flex;
align-items: center;
cursor: pointer;
background-color: #A68D71;
}
.box span {
display: block;
position: relative;
z-index: 11;
}
.box::after {
content: "";
position: absolute;
top: 0;
left: 0;
background-color: yellow;
width: 100%;
height: 0;
transition: height .3s;
}
.box:hover::after {
height: 100%;
transition: height .3s;
}
<div class="main__wrapper">
<section class="red">
</section>
<section class="green">
</section>
<section class="yellow">
</section>
<div class="slide__select">
<div class="redbox box">
<span>red</span>
</div>
<div class="greenbox box">
<span>green</span>
</div>
<div class="yellowbox box">
<span>yellow</span>
</div>
</div>
</div>
Here is a primitive example solution. It's overly verbose but shows you what is needed. This can be condensed.
To get an idea of how it can be condensed, all three listeners CAN be condensed into a single listener how you had it, listen just to the .box selector. But if you do that, you need a way to identify which box was clicked. This can be done via a data attribute or by looking at the html text. A data attribute would be my preferred method, as it separates the content from the logic a bit, but either would work.
Another less verbose solution:
window.onload = onPageLoad();
function onPageLoad() {
document.querySelector('.red').classList.add('active');
};
var boxes = document.querySelectorAll('.box');
for (var i = 0; i < boxes.length; i++) {
boxes[i].addEventListener('click', toggleSections);
}
var colors = ['red', 'green', 'yellow'];
function toggleSections(ev) {
var color = ev.currentTarget.innerText;
for (var c = 0; c < colors.length; c++) {
var colorElem = document.querySelector('.' + colors[c]);
if (colors[c] != color) {
colorElem.classList.remove('active');
} else {
colorElem.classList.add('active');
}
}
}
* {
padding: 0;
margin: 0;
}
.main__wrapper {
position: relative;
width: 100%;
height: 100vh;
overflow: hidden;
}
.red,
.green,
.yellow {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 2;
transform: translateX(-100%);
transition: transform 1.2s;
}
.red {
background-color: red;
}
.green {
background-color: green;
}
.yellow {
background-color: yellow;
}
.active {
transform: translateX(0) !important;
transition: transform 1s !important;
}
.slide__select {
position: absolute;
bottom: 0;
right: 0;
width: 60%;
height: 20%;
z-index: 10;
display: flex;
}
.box {
position: relative;
flex: 1 0 0;
color: $color-white;
display: flex;
align-items: center;
cursor: pointer;
background-color: #A68D71;
}
.box span {
display: block;
position: relative;
z-index: 11;
}
.box::after {
content: "";
position: absolute;
top: 0;
left: 0;
background-color: yellow;
width: 100%;
height: 0;
transition: height .3s;
}
.box:hover::after {
height: 100%;
transition: height .3s;
}
<div class="main__wrapper">
<section class="red">
</section>
<section class="green">
</section>
<section class="yellow">
</section>
<div class="slide__select">
<div class="box">
<span>red</span>
</div>
<div class="box">
<span>green</span>
</div>
<div class="box">
<span>yellow</span>
</div>
</div>
</div>
To achieve expected result, use below option
Use one section to avoid looping of section elements
Use querySelectorAll or elementsByClassName instead of querySelector to fetch all elements in array
Use forEach to loop through all elements of class- box and add addEventListener and run another loop with forEach for span elements
Use classList to add or remove
window.onload = onPageLoad();
function onPageLoad() {
document.querySelector('.red').classList.add('active');
};
// use querySelectorAll to get all elements of class-box and forEach to loop through
document.querySelectorAll('.box').forEach(function(ele){
//Add clici event through addEventListener
ele.addEventListener('click', function() {
// use another querySelectorAll to get all elements of tag span and forEach to loop through
document.querySelectorAll('span').forEach(function(e){
e.classList.remove('active');
//use querySelector for section element and empty classList to remove active and red/green/yellow class names
document.querySelector('section').className ='';
});
//toggle active class for clicked element
ele.children[0].classList.toggle("active");
//add active class for section
document.querySelector('section').classList.add('active');
//add class red/yellow/green using span innerHTML
document.querySelector('section').classList.add(ele.children[0].innerHTML);
});
});
* {
padding: 0;
margin: 0;
}
.main__wrapper {
position: relative;
width: 100%;
height: 100vh;
overflow: hidden;
}
.red,
.green,
.yellow {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 2;
transform: translateX(-100%);
transition: transform 1.2s;
}
.red {
background-color: red;
}
.green {
background-color: green;
}
.yellow {
background-color: yellow;
}
.active {
transform: translateX(0) !important;
transition: transform 1s !important;
}
.slide__select {
position: absolute;
bottom: 0;
right: 0;
width: 60%;
height: 20%;
z-index: 10;
display: flex;
}
.box {
position: relative;
flex: 1 0 0;
color: $color-white;
display: flex;
align-items: center;
cursor: pointer;
background-color: #A68D71;
}
.box span {
display: block;
position: relative;
z-index: 11;
}
.box::after {
content: "";
position: absolute;
top: 0;
left: 0;
background-color: yellow;
width: 100%;
height: 0;
transition: height .3s;
}
.box:hover::after {
height: 100%;
transition: height .3s;
}
<div class="main__wrapper">
<section class="red">
</section>
<div class="slide__select">
<div class="box">
<span>red</span>
</div>
<div class="box">
<span>green</span>
</div>
<div class="box">
<span>yellow</span>
</div>
</div>
</div>
code sample - https://codepen.io/nagasai/pen/vRoPwp