I'm struggling with infinite carousel below:
let $carousel = document.querySelector('.carousel');
let $ref_ribbon = document.querySelector('.carousel__ribbon');
let $ref_right = document.querySelector('.carousel__button--right');
let $ref_left = document.querySelector('.carousel__button--left');
let $ref_counter = 0;
let $direction;
const transfer = () => {
if ($direction === -1) {
$ref_ribbon.appendChild($ref_ribbon.firstElementChild);
} else if ($direction === 1) {
$ref_ribbon.prepend($ref_ribbon.lastElementChild);
}
$ref_ribbon.style.transition = "none";
$ref_ribbon.style.transform = "translateX(0px)";
setTimeout(function() {
$ref_ribbon.style.transition = "transform .7s ease-in-out";
})
}
const right_button = () => {
if ($direction === 1) {
$ref_ribbon.prepend($ref_ribbon.lastElementChild);
$direction = -1;
}
$direction = -1;
$carousel.style.justifyContent = 'flex-start';
$ref_ribbon.style.transform = `translateX(-${300}px)`;
}
const left_button = () => {
$ref_counter--;
if ($direction === -1) {
$ref_ribbon.appendChild($ref_ribbon.firstElementChild);
$direction = 1;
}
$direction = 1;
$carousel.style.justifyContent = 'flex-end';
$ref_ribbon.style.transform = `translateX(${300}px)`;
}
$ref_right.addEventListener('click', right_button);
$ref_left.addEventListener('click', left_button);
$ref_ribbon.addEventListener('transitionend', transfer)
.carousel {
display: flex;
margin: auto;
position: relative;
height: 200px;
width: 300px;
background-color: red;
justify-content: flex-start;
}
.carousel__button {
position: absolute;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
z-index: 100;
}
.carousel__button--left {
left: 0;
}
.carousel__button--right {
right: 0;
}
.carousel__ribbon {
display: flex;
flex-direction: row;
outline: 3px solid black;
height: 100%;
transition: transform .7s ease-in-out;
}
.carousel__pane {
display: flex;
background-color: skyblue;
height: 100%;
width: 300px;
flex-shrink: 0;
outline: 1px dashed navy;
}
.carousel__content {
text-align: center;
margin: auto;
}
.carousel__indicator {
display: flex;
gap: 10px;
left: 50%;
transform: translateX(-50%);
height: 30px;
position: absolute;
bottom: 0;
}
.carousel__circle {
height: 10px;
width: 10px;
background-color: gray;
border-radius: 50%;
cursor: pointer;
}
.carousel__circle--active {
background-color: black;
}
<div class="carousel">
<button class="carousel__button carousel__button--left"><</button>
<button class="carousel__button carousel__button--right">></button>
<div class="carousel__ribbon">
<div class="carousel__pane">
<p class="carousel__content">Pane 1</p>
</div>
<div class="carousel__pane">
<p class="carousel__content">Pane 2</p>
</div>
<div class="carousel__pane">
<p class="carousel__content">Pane 3</p>
</div>
<div class="carousel__pane">
<p class="carousel__content">Pane 4</p>
</div>
<div class="carousel__pane">
<p class="carousel__content">Pane 5</p>
</div>
</div>
<div class="carousel__indicator">
<div class="carousel__circle carousel__circle--active"></div>
<div class="carousel__circle"></div>
<div class="carousel__circle"></div>
<div class="carousel__circle"></div>
<div class="carousel__circle"></div>
</div>
</div>
I would like to connect indicator so when somebody click on proper circle then carousel will automatically slide to this particular panel. Also, I would like to set this circles that they will show which panel is currently active.
In addition, I would like to get such effect that carousel will jump to this particular panel immediately, ommiting other panels between.
So, if active one is first panel and I click fifth circle, then carousel will smoothly change panel like to the panel number two, but instead of number two I will see number five.
Sadly I always fail to get this effect. I would appriciate if somebody more experienced direct me how to deal with this problem.
I came across this website's work page and would like to recreate the xray effect of each of the card element.
Here's my code for the xray effect: https://codepen.io/carljustineoyales/pen/yLMEVYd
HTML
<section class="banner">
<h1>this is a banner page</h1>
</section>
<section class="projects" id="projects">
<div class="cardlist" >
<div class="cardlist__grid" >
<div class="card" id="card" onmouseover="setSize()" onmouseout="resetSize()">
<div class="card__category">
category
</div>
<div class="card__thumbnail">
</div>
<div class="card__info">
<div class="card__title">title</div>
<div class="card__date">date</div>
</div>
</div>
<div class="card" id="card">
<div class="card__category">
category
</div>
<div class="card__thumbnail">
</div>
<div class="card__info">
<div class="card__title">title</div>
<div class="card__date">date</div>
</div>
</div>
</div>
</div>
<div class="cardlist--skeleton" id="skeleton">
<div class="cardlist--skeleton--bg"></div>
<div class="cardlist__grid">
<div class="card">
<div class="card__category">
category
</div>
<div class="card__thumbnail card__thumbnail--black">
</div>
<div class="card__info">
<div class="card__title">title</div>
<div class="card__date">date</div>
</div>
</div>
<div class="card">
<div class="card__category">
category
</div>
<div class="card__thumbnail card__thumbnail--black">
</div>
<div class="card__info">
<div class="card__title">title</div>
<div class="card__date">date</div>
</div>
</div>
</div>
</div>
</section>
</body>
SCSS
* {
margin: 0;
padding: 0;
}
.banner {
height: 100vh;
}
.projects {
max-width: 1440px;
width: 100%;
margin: 100px auto;
// padding: 100px 0;
position: relative;
}
.cardlist {
width: 100%;
color: #000;
&__grid {
display: flex;
flex-direction: row;
justify-content: space-between;
}
&--skeleton {
--x: 0;
--y: 0;
--size: 0px;
clip-path: circle(var(--size) at var(--x) var(--y));
user-select: none;
pointer-events: none;
// clip-path: circle(100px at 0 0);
// clip-path: circle(300px at 0% 0%);
transition: clip-path 0.1s ease;
&--bg {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: #838383;
z-index: -1;
}
width: 100%;
position: absolute;
top: 0;
left: 0;
color: #fff;
z-index: 1;
background-color: #838383;
}
}
.card {
padding: 50px;
&__thumbnail {
width: 500px;
height: 644px;
background-color: #838383;
&--black {
background-color: #000;
}
}
}
JS
let mouseX=0
let mouseY=0
let size = 0;
const projects = document.querySelector('#projects');
function setSize() {
size = 200
skeleton.style.setProperty('--size', size + "px");
}
function resetSize() {
size = 0
skeleton.style.setProperty('--size', size + "px");
}
function updateCoordinates(event) {
mouseX = event.pageX - projects.offsetLeft ;
mouseY = event.pageY - projects.offsetTop ;
skeleton.style.setProperty('--x', mouseX + "px");
skeleton.style.setProperty('--y', mouseY+ "px");
}
The problem is that I can't seem to find a solution for the updating cursor position while scrolling, also the hover animation became laggy when you open the console. Is there a way to update the cursor position on scroll and why the animation became laggy when the console is open.
I've got some section with infinite carousel using vanilla js.
My logic is based on using justify-content:flex-end for previous slide and justify-content:flex-start for next one.
My carousel has default justify-content:flex-start and it works fine when slides to next, but there is some render delay if I'm using slide to prev.
It's because of using justify-content:flex-end for prev, but how to get rid of delay?
This is my code
const slider = document.querySelector('.slider')
const carousel = document.querySelector('.carousel')
const prev = document.querySelector('.prev')
const next = document.querySelector('.next')
let direction
prev.addEventListener('click', () => {
if (direction === -1) {
slider.appendChild(slider.lastElementChild)
direction = 1
}
direction = 1
carousel.style.justifyContent = 'flex-end'
slider.style.transform = 'translate(20%)'
})
next.addEventListener('click', () => {
direction = -1
carousel.style.justifyContent = 'flex-start'
slider.style.transform = 'translate(-20%)'
})
slider.addEventListener('transitionend', () => {
if (direction === -1) {
slider.appendChild(slider.firstElementChild)
} else if (direction === 1) {
slider.prepend(slider.lastElementChild)
}
slider.style.transition = 'none'
slider.style.transform = 'translate(0)'
setTimeout(() => {
slider.style.transition = 'transform 0.5s'
})
})
.section {
display: flex;
justify-content: center;
align-items: center;
padding: 80px 0;
background-color: green;
position: relative;
}
.carousel {
display: flex;
width: 70%;
height: 100%;
justify-content: flex-start;
position: relative;
overflow: hidden;
}
.slider {
display: flex;
width: 100%;
height: 100%;
transition: all 0.5s;
}
.item {
display: flex;
width: 20%;
flex: 1;
flex-shrink: 0;
flex-basis: 20%;
height: 70px;
}
.prev,
.next {
position: absolute;
height: 70px;
width: 70px;
border-radius: 50%;
border: 1px solid green;
cursor: pointer;
z-index: 3;
}
.prev {
left: 20px;
}
.next {
right: 20px;
}
<section class="section">
<div class="prev">Prev</div>
<div class="next">Next</div>
<div class="carousel">
<div class="slider">
<div class="item"> Item 1</div>
<div class="item"> Item 2</div>
<div class="item"> Item 3</div>
<div class="item"> Item 4</div>
<div class="item"> Item 5</div>
<div class="item"> Item 1</div>
<div class="item"> Item 2</div>
<div class="item"> Item 3</div>
<div class="item"> Item 4</div>
<div class="item"> Item 5</div>
</div>
</div>
</section>
Not sure if this is the best approach. Your code is appending (and prepending) elements after the slider has transitioned. Because of the overflow:hidden you don't notice it happen when it appends to the end of the slider but you notice when it prepends to the start which is why you see it render after the translation.
So you could move the slider 20% to the left so you don't see when the element is prepended and not change most of your code.
const slider = document.querySelector('.slider')
const carousel = document.querySelector('.carousel')
const prev = document.querySelector('.prev')
const next = document.querySelector('.next')
let direction
prev.addEventListener('click', () => {
if (direction === -1) {
slider.appendChild(slider.lastElementChild)
direction = 1
}
direction = 1
// removed - carousel.style.justifyContent = 'flex-end'
slider.style.transform = 'translate(20%)'
})
next.addEventListener('click', () => {
direction = -1
// removed - carousel.style.justifyContent = 'flex-start'
slider.style.transform = 'translate(-20%)'
})
slider.addEventListener('transitionend', () => {
if (direction === -1) {
slider.appendChild(slider.firstElementChild)
} else if (direction === 1) {
slider.prepend(slider.lastElementChild)
}
slider.style.transition = 'none'
slider.style.transform = 'translate(0)'
setTimeout(() => {
slider.style.transition = 'transform 0.5s'
})
})
.section {
display: flex;
justify-content: center;
align-items: center;
padding: 80px 0;
background-color: green;
position: relative;
}
.carousel {
display: flex;
width: 70%;
height: 100%;
justify-content: flex-start;
position: relative;
overflow: hidden;
}
.slider {
display: flex;
width: 100%;
height: 100%;
transition: all 0.5s;
/* Only change */ margin-left: -20%;
}
.item {
display: flex;
width: 20%;
flex: 1;
flex-shrink: 0;
flex-basis: 20%;
height: 70px;
}
.prev,
.next {
position: absolute;
height: 70px;
width: 70px;
border-radius: 50%;
border: 1px solid green;
cursor: pointer;
z-index: 3;
}
.prev {
left: 20px;
}
.next {
right: 20px;
}
<section class="section">
<div class="prev">Prev</div>
<div class="next">Next</div>
<div class="carousel">
<div class="slider">
<div class="item"> Item 1</div>
<div class="item"> Item 2</div>
<div class="item"> Item 3</div>
<div class="item"> Item 4</div>
<div class="item"> Item 5</div>
<div class="item"> Item 6</div>
<div class="item"> Item 7</div>
<div class="item"> Item 9</div>
<div class="item"> Item 0</div>
</div>
</div>
</section>
Here I have six different div on hover blue color div should appear and by default hidden. I have written code for this but it works only for the first div I merge all div's in a single variable. Can anyone suggest to me what I'm missing here
var tcpTooltip = $('.tp-cont-tech, tp-cont-b, tp-cont-m, tp-cont-t, tp-cont-i, tp-cont-e');
var tcpTooltipDiv = $('.tpc-tooltip-tech, tpc-tooltip-b, tpc-tooltip-m, tpc-tooltip-t, tpc-tooltip-i, tpc-tooltip-e');
tcpTooltipDiv.hide();
$(tcpTooltip).each(function() {
$(tcpTooltip).hover(function() {
$(tcpTooltipDiv).show();
}, function() {
$(tcpTooltipDiv).hide();
});
});
/* Tooltip */
.tp-cont-tech,
.tp-cont-e,
.tp-cont-t,
.tp-cont-m,
.tp-cont-i,
.tp-cont-b {
position: relative;
width: 200px;
height: 200px;
background-color: red;
margin-bottom: 20px;
}
.tpc-tooltip-tech,
.tpc-tooltip-e,
.tpc-tooltip-t,
.tpc-tooltip-m,
.tpc-tooltip-i,
.tpc-tooltip-b {
position: absolute;
top: 2%;
left: 5%;
z-index: 10;
width: 100px;
height: 100px;
background-color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<div class="tpc-info">
<div class="tp-cont-tech">
<div class="tpc-tooltip-tech"></div>
</div>
<div class="tp-cont-b">
<div class="tpc-tooltip-b"></div>
</div>
<div class="tp-cont-m">
<div class="tpc-tooltip-m"></div>
</div>
<div class="tp-cont-t">
<div class="tpc-tooltip-t"></div>
</div>
<div class="tp-cont-e">
<div class="tpc-tooltip-e"></div>
</div>
</div>
As suggested already, I'd go by using pure CSS and the :hover pseudo.
If you really want jQuery for some reason this would be a remake of your code.
Basically (beside adding common classes to your elements [see code below]) you need the $(this) reference of the currently hovered element:
var $tpCont = $('.tp-cont');
var $tcpTooltip = $('.tcp-tooltip');
$tcpTooltip.hide();
$tpCont.hover(function() {
$(this).find($tcpTooltip).toggle();
});
.tp-cont {
position: relative;
width: 200px;
height: 200px;
background-color: red;
margin-bottom: 20px;
}
.tcp-tooltip {
position: absolute;
top: 2%;
left: 5%;
z-index: 10;
width: 100px;
height: 100px;
background-color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<div class="tpc-info">
<div class="tp-cont tp-cont-tech">
<div class="tcp-tooltip tpc-tooltip-tech"></div>
</div>
<div class="tp-cont tp-cont-b">
<div class="tcp-tooltip tpc-tooltip-b"></div>
</div>
<div class="tp-cont tp-cont-m">
<div class="tcp-tooltip tpc-tooltip-m"></div>
</div>
<div class="tp-cont tp-cont-t">
<div class="tcp-tooltip tpc-tooltip-t"></div>
</div>
<div class="tp-cont tp-cont-e">
<div class="tcp-tooltip tpc-tooltip-e"></div>
</div>
</div>
You can achieve this far more effectively with CSS. If you add some common classes to the tp-cont-X and tpc-tooltip-X elements, then you can use the :hover pseudo-selector, like this:
.tp-cont {
position: relative;
width: 200px;
height: 200px;
background-color: red;
margin-bottom: 20px;
}
.tpc-tooltip {
position: absolute;
top: 2%;
left: 5%;
z-index: 10;
width: 100px;
height: 100px;
background-color: blue;
display: none;
}
.tp-cont:hover .tpc-tooltip {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<div class="tpc-info">
<div class="tp-cont tp-cont-tech">
<div class="tpc-tooltip tpc-tooltip-tech"></div>
</div>
<div class="tp-cont tp-cont-b">
<div class="tpc-tooltip tpc-tooltip-b"></div>
</div>
<div class="tp-cont tp-cont-m">
<div class="tpc-tooltip tpc-tooltip-m"></div>
</div>
<div class="tp-cont tp-cont-t">
<div class="tpc-tooltip tpc-tooltip-t"></div>
</div>
<div class="tp-cont tp-cont-e">
<div class="tpc-tooltip tpc-tooltip-e"></div>
</div>
</div>
Try using index inside hover.
var tcpTooltip = $('.tp-cont-tech, .tp-cont-b, .tp-cont-m, .tp-cont-t, .tp-cont-i, .tp-cont-e');
var tcpTooltipDiv = $('.tpc-tooltip-tech, .tpc-tooltip-b, .tpc-tooltip-m, .tpc-tooltip-t, .tpc-tooltip-i, .tpc-tooltip-e');
tcpTooltipDiv.hide();
$(tcpTooltip).each(function() {
$(tcpTooltip).hover(function(index, item) {
$(tcpTooltipDiv).eq($(this).index()).show();
}, function() {
$(tcpTooltipDiv).hide();
});
});
/* Tooltip */
.tp-cont-tech,
.tp-cont-e,
.tp-cont-t,
.tp-cont-m,
.tp-cont-i,
.tp-cont-b {
position: relative;
width: 200px;
height: 200px;
background-color: red;
margin-bottom: 20px;
}
.tpc-tooltip-tech,
.tpc-tooltip-e,
.tpc-tooltip-t,
.tpc-tooltip-m,
.tpc-tooltip-i,
.tpc-tooltip-b {
position: absolute;
top: 2%;
left: 5%;
z-index: 10;
width: 100px;
height: 100px;
background-color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<div class="tpc-info">
<div class="tp-cont-tech">
<div class="tpc-tooltip-tech"></div>
</div>
<div class="tp-cont-b">
<div class="tpc-tooltip-b"></div>
</div>
<div class="tp-cont-m">
<div class="tpc-tooltip-m"></div>
</div>
<div class="tp-cont-t">
<div class="tpc-tooltip-t"></div>
</div>
<div class="tp-cont-e">
<div class="tpc-tooltip-e"></div>
</div>
</div>
I just want the ability to be able to pause the animation on mouse hover. I trying to looking good way to do that, but there was some issues. I tested some hover/stop functions, but I can't get these working correctly.
jQuery(document).ready(function() {
setInterval(function() {
jQuery('#testimonials .slide').filter(':visible').fadeOut(1000, function() {
if (jQuery(this).next('.slide').size()) {
jQuery(this).next().fadeIn(1000);
} else {
jQuery('#testimonials .slide').eq(0).fadeIn(1000);
}
});
}, 5000);
});
#quote {
width: 100%;
height: 130px;
background-position: center bottom;
background-repeat: no-repeat;
margin-bottom: 65px;
overflow: hidden;
}
#testimonials .slide {
color: #555555;
}
#testimonials .testimonial-quote {
display: inline;
width: 600px;
height: 170px;
margin: 0;
padding: 0;
float: left;
position: relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="quote">
<div id="testimonials">
<div class="slide">
<div class="testimonial-quote">
<p>Text 1</p>
<h4 class="title">Title 1</h4>
</div>
</div>
</div>
</div>
You can achieve this by calling clearInterval() when the slide is hovered, then re-creating the interval again when the mouse leaves the slide, something like this:
jQuery(document).ready(function($) {
var $slides = $('#testimonials .slide');
function beginSlideInterval() {
return setInterval(function() {
$slides.filter(':visible').fadeOut(1000, function() {
var $next = $(this).next().length ? $(this).next() : $slides.first();
$next.fadeIn(1000);
});
}, 3000);
}
var slideInterval = beginSlideInterval();
$slides.on('mouseenter', function() {
clearInterval(slideInterval);
}).on('mouseleave', function() {
slideInterval = beginSlideInterval();
});
});
#quote {
width: 100%;
height: 130px;
background-position: center bottom;
background-repeat: no-repeat;
margin-bottom: 65px;
overflow: hidden;
}
#testimonials .slide {
color: #555555;
}
#testimonials .testimonial-quote {
display: inline;
width: 600px;
height: 170px;
margin: 0;
padding: 0;
float: left;
position: relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="quote">
<div id="testimonials">
<div class="slide">
<div class="testimonial-quote">
<p>Text 1</p>
<h4 class="title">Title 1</h4>
</div>
</div>
</div>
</div>
Note that I shortened the interval to make the effect more obvious.