I am trying to create a similar carousel like the one on https://ueno.co/about/ (under the "value" section), that scrolls as the user continue to scroll down the page and then displays more information beneath it by adding the class .show to the hidden divs that will be below.
So far I have been using the flickity API and have created most of the setup necessary.
The only thing that is missing is being able to scroll through the carousel using the mouse wheel once it is in focus (which is setup once the user scrolls to it).
My guess was that I could simulate a left and right arrow key press when it is in focus which will change each slide, but if there is a cleaner way I would gladly use that.
jQuery(document).ready(function( $ ) {
var $carousel = $('.js-carousel');
$carousel.flickity({
prevNextButtons: false,
pageDots: false
});
// Split each word in the cell title into a span.
var $cellTitle = $('.js-cell-title');
// Wrap every letter in the cell title
$cellTitle.each(function() {
var $this = $(this);
var letters = $this.text().split('');
$this = $(this);
$this.empty();
$.each(letters, function(i, el) {
$this.append($('<span class="text-split">')
.append($('<span class="text-split__inner">')
.text(el)));
});
// Dirty way of getting the whitespace
var emptySplits = $this.find('.text-split__inner:contains( )');
emptySplits.addClass('whitespace');
emptySplits.parent().addClass('whitespace');
});
//focus the carousel when it is scrolled to
$(window).scroll(function() {
var carousel = $(".carousel");
var carouselTop = $('.carousel').offset().top;
var carouselHeight = $('.carousel').outerHeight();
var windowHeight = $(window).height();
var scrollTop = $(this).scrollTop();
var isScrollMode = carousel.hasClass('scrollMode');
var isInView = scrollTop > (carouselTop+carouselHeight-windowHeight) &&
(carouselTop > scrollTop) && (scrollTop+windowHeight > carouselTop+carouselHeight);
if(!isInView && isScrollMode){
carousel.removeClass('scrollMode');
carousel.blur();
console.log('EXIT');
} else if (!carousel.hasClass('scrollMode') && isInView){
carousel.addClass('scrollMode');
carousel.focus();
//NEEDS FUNCTION TO SCROLL THE CAROUSEL
console.log('ENTER');
}
});
//end of carousel event
function carouselEnd() {
var cells = $(".carousel-cell");
var numberOfCells = cells.length;
var lastCell = cells[numberOfCells - 1];
if( lastCell.classList.contains('is-selected') ){
//will add .show class to the hidden content
}
}
$carousel.on( 'settle.flickity', function( event, pointer ) {
carouselEnd();
});
});
.carousel{
.row{
margin:0;
}
.carousel-cell {
width: 66%;
margin-right: 3rem;
}
.cell__wrap {
width: 100%;
margin: 0 auto;
}
.cell__inner {
position: relative;
width: 100%;
height: 0;
padding-bottom: 56.25%;
}
.cell__title {
position: absolute;
z-index: 1;
top: 50%;
left: 0;
margin: 0;
transform: translateY(-50%) translateX(-20%);
}
.text-split {
overflow: hidden;
display: inline-block;
&.whitespace {
display: initial;
}
#for $i from 1 through 100 {
&:nth-child(#{$i}) .text-split__inner {
transition-delay: 0.02s * $i;
}
}
}
.text-split__inner {
transform: translateY(100%);
display: inline-block;
transition: transform 0.3s ease;
.is-selected & {
transform: translateY(0);
}
&.whitespace {
display: initial;
}
}
.cell__thumb {
position: absolute;
width: 100%;
height: 100%;
z-index: 0;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
// Base styles
html,
body {
width: 100%;
height: 100%;
font-family: 'Work Sans', sans-serif;
}
body {
display: flex;
align-items: center;
justify-content: center;
margin: 0;
/* background-color: #00011D;
color: #FFF; */
}
.container {
width: 100%;
}
}
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://unpkg.com/flickity#2.0/dist/flickity.pkgd.min.js"></script>
</head>
<section class="carousel">
<div class="container a">
<div class="carousel js-carousel">
<div class="carousel-cell">
<div class="cell__wrap">
<div class="cell__inner">
<img class="cell__thumb shadow-green" src='https://via.placeholder.com/1036x274.png'>
</div>
<div class="row">
<h2>Title</h2>
</div>
<div class="row">
<p> Here is the content</p>
</div>
</div>
</div>
<div class="carousel-cell">
<div class="cell__wrap">
<div class="cell__inner">
<img class="cell__thumb shadow-green" src='https://via.placeholder.com/1036x274.png'>
</div>
<div class="row">
<h2>Title</h2>
</div>
<div class="row">
<p> Here is the content</p>
</div>
</div>
</div>
<div class="carousel-cell">
<div class="cell__wrap">
<div class="cell__inner">
<img class="cell__thumb shadow-green" src='https://via.placeholder.com/1036x274.png'>
</div>
<div class="row">
<h2>Title</h2>
</div>
<div class="row">
<p> Here is the content</p>
</div>
</div>
</div>
<div class="carousel-cell">
<div class="cell__wrap">
<div class="cell__inner">
<img class="cell__thumb shadow-green" src='https://via.placeholder.com/1036x274.png'>
</div>
<div class="row">
<h2>Title</h2>
</div>
<div class="row">
<p> Here is the content</p>
</div>
</div>
</div>
<div class="carousel-cell">
<div class="cell__wrap">
<div class="cell__inner">
<img class="cell__thumb shadow-green" src='https://via.placeholder.com/1036x274.png'>
</div>
<div class="row">
<h2>Title</h2>
</div>
<div class="row">
<p> Here is the content</p>
</div>
</div>
</div>
</div>
</div>
</section>
Related
I have a container that has a list of items, each item has an image and some information.
I made a slide function using JavaScript and I got into a little problem, because I'm using translateX, I want the items to be displayed inline.
I made some research and found that I must use display: flex when making a sliding image, and after that, the items are not showing correctly.
If I remove the flex and I put translateY (instead of X) the slide is working (from up/down) but I want from left-right.
Can someone help me?
This is the code that is not work (with display: flex and translateX)
var count = 1;
var next = document.querySelector('button.next');
var items = document.querySelectorAll('div.item');
var size = items[0].clientWidth;
next.addEventListener("click", function(e)
{
if(count == 2) {
return;
}
count++;
document.querySelector('div.main').style.transition = 'transform 1.0s ease-in-out';
document.querySelector('div.main').style.transform = 'translateX(' + ((-size * count)) + 'px)';
});
var prev = document.querySelector('button.prev');
prev.addEventListener("click", function(e)
{
if(count == 1) {
return;
}
count--;
document.querySelector('div.main').style.transition = 'transform 1.0s ease-in-out';
document.querySelector('div.main').style.transform = 'translateX(' + ((-size * count)) + 'px)';
});
.content {
margin-left: 50px;
}
.container {
width: 100%;
height: 600px;
}
.main {
display: flex;
width: 100%;
}
.container-slide {
width: 100%;
overflow: hidden;
position: relative;
}
.image {
width: 100%;
min-height: 600px;
max-height: 600px;
background-clip: padding-box;
float: left;
background-size: cover;
background-position: center center;
position: relative;
}
.info {
position: absolute;
bottom: 0;
left: 0;
width: 70%;
color: white;
background: green;
padding: 20px;
display: inline-flex;
align-items: center;
justify-content: center;
}
.buttons-info {
margin-left: 30px;
}
button.prev, button.next {
margin-top: 50px;
}
.show-list-pages {
position: absolute;
bottom: 20px;
right: 10px;
display: inline-flex;
align-items: center;
justify-content: center;
color: white;
}
<div class="content">
<div class="container container-slide">
<div class="main">
<div class="item">
<div class="image" style="background-image: url('https://i.redd.it/7nk7p8gl90371.jpg')">
<div class="info">
<div class="buttons-info">
<div class="show-main-text">
<span>title item 2</span>
</div>
</div>
<div class="buttons-item">
<a href="#">
<button><span>button 1</span></button>
</a>
</div>
</div>
<div class="show-list-pages">
<div class="show-current-page">
<span>1</span>
</div>
<div class="show-count-pages">
<span>/ 2</span>
</div>
</div>
</div>
</div>
<div class="item">
<div class="image" style="background-image: url('https://assets.hongkiat.com/uploads/minimalist-dekstop-wallpapers/4k/original/14.jpg')">
<div class="info">
<div class="buttons-info">
<div class="show-main-text">
<span>title item 1</span>
</div>
</div>
<div class="buttons-item">
<a href="#">
<button><span>button 1</span></button>
</a>
</div>
</div>
<div class="show-list-pages">
<div class="show-current-page">
<span>1</span>
</div>
<div class="show-count-pages">
<span>/ 2</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<button class="prev">prev</button>
<button class="next">next</button>
This is the other code without display: flex and translateX (is working) but the next item is not showing (because is not on inline, is under the first item)
var count = 1;
var next = document.querySelector('button.next');
var items = document.querySelectorAll('div.item');
var size = items[0].clientWidth;
next.addEventListener("click", function(e)
{
if(count == 2) {
return;
}
count++;
document.querySelector('div.main').style.transition = 'transform 1.0s ease-in-out';
document.querySelector('div.main').style.transform = 'translateX(' + ((-size * count)) + 'px)';
});
var prev = document.querySelector('button.prev');
prev.addEventListener("click", function(e)
{
if(count == 1) {
return;
}
count--;
document.querySelector('div.main').style.transition = 'transform 1.0s ease-in-out';
document.querySelector('div.main').style.transform = 'translateX(' + ((-size * count)) + 'px)';
});
.content {
margin-left: 50px;
}
.container {
width: 100%;
height: 600px;
}
.main {
/*display: flex;*/
width: 100%;
}
.container-slide {
width: 100%;
overflow: hidden;
position: relative;
}
.image {
width: 100%;
min-height: 600px;
max-height: 600px;
background-clip: padding-box;
float: left;
background-size: cover;
background-position: center center;
position: relative;
}
.info {
position: absolute;
bottom: 0;
left: 0;
width: 70%;
color: white;
background: green;
padding: 20px;
display: inline-flex;
align-items: center;
justify-content: center;
}
.buttons-info {
margin-left: 30px;
}
button.prev, button.next {
margin-top: 50px;
}
.show-list-pages {
position: absolute;
bottom: 20px;
right: 10px;
display: inline-flex;
align-items: center;
justify-content: center;
color: white;
}
<div class="content">
<div class="container container-slide">
<div class="main">
<div class="item">
<div class="image" style="background-image: url('https://i.redd.it/7nk7p8gl90371.jpg')">
<div class="info">
<div class="buttons-info">
<div class="show-main-text">
<span>title item 2</span>
</div>
</div>
<div class="buttons-item">
<a href="#">
<button><span>button 1</span></button>
</a>
</div>
</div>
<div class="show-list-pages">
<div class="show-current-page">
<span>1</span>
</div>
<div class="show-count-pages">
<span>/ 2</span>
</div>
</div>
</div>
</div>
<div class="item">
<div class="image" style="background-image: url('https://assets.hongkiat.com/uploads/minimalist-dekstop-wallpapers/4k/original/14.jpg')">
<div class="info">
<div class="buttons-info">
<div class="show-main-text">
<span>title item 1</span>
</div>
</div>
<div class="buttons-item">
<a href="#">
<button><span>button 1</span></button>
</a>
</div>
</div>
<div class="show-list-pages">
<div class="show-current-page">
<span>1</span>
</div>
<div class="show-count-pages">
<span>/ 2</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<button class="prev">prev</button>
<button class="next">next</button>
This is the code without display: flex and translateY instead of X, is working from up-down, but I want from left-right
var count = 1;
var next = document.querySelector('button.next');
var items = document.querySelectorAll('div.item');
var size = items[0].clientWidth;
next.addEventListener("click", function(e)
{
if(count == 2) {
return;
}
count++;
document.querySelector('div.main').style.transition = 'transform 1.0s ease-in-out';
document.querySelector('div.main').style.transform = 'translateY(' + ((-size * count)) + 'px)';
});
var prev = document.querySelector('button.prev');
prev.addEventListener("click", function(e)
{
if(count == 1) {
return;
}
count--;
document.querySelector('div.main').style.transition = 'transform 1.0s ease-in-out';
document.querySelector('div.main').style.transform = 'translateY(' + ((-size * count)) + 'px)';
});
.content {
margin-left: 50px;
}
.container {
width: 100%;
height: 600px;
}
.main {
/*display: flex;*/
width: 100%;
}
.container-slide {
width: 100%;
overflow: hidden;
position: relative;
}
.image {
width: 100%;
min-height: 600px;
max-height: 600px;
background-clip: padding-box;
float: left;
background-size: cover;
background-position: center center;
position: relative;
}
.info {
position: absolute;
bottom: 0;
left: 0;
width: 70%;
color: white;
background: green;
padding: 20px;
display: inline-flex;
align-items: center;
justify-content: center;
}
.buttons-info {
margin-left: 30px;
}
button.prev, button.next {
margin-top: 50px;
}
.show-list-pages {
position: absolute;
bottom: 20px;
right: 10px;
display: inline-flex;
align-items: center;
justify-content: center;
color: white;
}
<div class="content">
<div class="container container-slide">
<div class="main">
<div class="item">
<div class="image" style="background-image: url('https://i.redd.it/7nk7p8gl90371.jpg')">
<div class="info">
<div class="buttons-info">
<div class="show-main-text">
<span>title item 2</span>
</div>
</div>
<div class="buttons-item">
<a href="#">
<button><span>button 1</span></button>
</a>
</div>
</div>
<div class="show-list-pages">
<div class="show-current-page">
<span>1</span>
</div>
<div class="show-count-pages">
<span>/ 2</span>
</div>
</div>
</div>
</div>
<div class="item">
<div class="image" style="background-image: url('https://assets.hongkiat.com/uploads/minimalist-dekstop-wallpapers/4k/original/14.jpg')">
<div class="info">
<div class="buttons-info">
<div class="show-main-text">
<span>title item 1</span>
</div>
</div>
<div class="buttons-item">
<a href="#">
<button><span>button 1</span></button>
</a>
</div>
</div>
<div class="show-list-pages">
<div class="show-current-page">
<span>1</span>
</div>
<div class="show-count-pages">
<span>/ 2</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<button class="prev">prev</button>
<button class="next">next</button>
EDIT: I solved this issues, I just added min-width: 100% to the .item.
If you are looking for a carousel.
this is what I changed in CSS.
.main {
display: flex;
width: 200%;
}
.item{
width:100%;
}
this is what I changed in JS.
//in next -50% it shifts half way through .main
document.querySelector('div.main').style.transform = 'translateX(-50%)';
// in prev 0% it goes back to start
document.querySelector('div.main').style.transform = 'translateX(0%)';
var count = 1;
var next = document.querySelector('button.next');
var items = document.querySelectorAll('div.item');
var size = items[0].clientWidth;
next.addEventListener("click", function(e)
{
if(count == 2) {
return;
}
count++;
document.querySelector('div.main').style.transition = 'transform 1.0s ease-in-out';
document.querySelector('div.main').style.transform = 'translateX(-50%)';
});
var prev = document.querySelector('button.prev');
prev.addEventListener("click", function(e)
{
if(count == 1) {
return;
}
count--;
document.querySelector('div.main').style.transition = 'transform 1.0s ease-in-out';
document.querySelector('div.main').style.transform ='translateX(-0%)';
});
.content {
margin-left: 50px;
}
.container {
width: 100%;
height: 600px;
}
.main {
display: flex;
width: 200%;
}
.container-slide {
width: 100%;
overflow: hidden;
position: relative;
}
.image {
width: 100%;
min-height: 600px;
max-height: 600px;
background-clip: padding-box;
float: left;
background-size: cover;
background-position: center center;
position: relative;
}
.info {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
color: white;
background: green;
padding: 20px;
display: inline-flex;
align-items: center;
justify-content: center;
}
.item{
width:100%;
}
.buttons-info {
margin-left: 30px;
}
button.prev, button.next {
margin-top: 50px;
}
.show-list-pages {
position: absolute;
bottom: 20px;
right: 10px;
display: inline-flex;
align-items: center;
justify-content: center;
color: white;
}
<div class="content">
<div class="container container-slide">
<div class="main">
<div class="item">
<div class="image" style="background-image: url('https://i.redd.it/7nk7p8gl90371.jpg')">
<div class="info">
<div class="buttons-info">
<div class="show-main-text">
<span>title item 2</span>
</div>
</div>
<div class="buttons-item">
<a href="#">
<button><span>button 1</span></button>
</a>
</div>
</div>
<div class="show-list-pages">
<div class="show-current-page">
<span>1</span>
</div>
<div class="show-count-pages">
<span>/ 2</span>
</div>
</div>
</div>
</div>
<div class="item">
<div class="image" style="background-image: url('https://assets.hongkiat.com/uploads/minimalist-dekstop-wallpapers/4k/original/14.jpg')">
<div class="info">
<div class="buttons-info">
<div class="show-main-text">
<span>title item 1</span>
</div>
</div>
<div class="buttons-item">
<a href="#">
<button><span>button 1</span></button>
</a>
</div>
</div>
<div class="show-list-pages">
<div class="show-current-page">
<span>2</span>
</div>
<div class="show-count-pages">
<span>/ 2</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<button class="prev">prev</button>
<button class="next">next</button>
this is not the optimal solution as I tried to keep that original code.
this won't work if you add more than 2 images.
If you would like to change the entire code then here is the solution.
source MEDIUM carousel from scratch in vanilla JS
codepen.io carousel
!(function(d){
var itemClassName = "carousel__photo";
items = d.getElementsByClassName(itemClassName),
totalItems = items.length,
slide = 0,
moving = true;
// Set classes
function setInitialClasses() {
// Targets the previous, current, and next items
// This assumes there are at least three items.
items[totalItems - 1].classList.add("prev");
items[0].classList.add("active");
items[1].classList.add("next");
}
// Set event listeners
function setEventListeners() {
var next = d.getElementsByClassName('carousel__button--next')[0],
prev = d.getElementsByClassName('carousel__button--prev')[0];
next.addEventListener('click', moveNext);
prev.addEventListener('click', movePrev);
}
// Next navigation handler
function moveNext() {
// Check if moving
if (!moving) {
// If it's the last slide, reset to 0, else +1
if (slide === (totalItems - 1)) {
slide = 0;
} else {
slide++;
}
// Move carousel to updated slide
moveCarouselTo(slide);
}
}
// Previous navigation handler
function movePrev() {
// Check if moving
if (!moving) {
// If it's the first slide, set as the last slide, else -1
if (slide === 0) {
slide = (totalItems - 1);
} else {
slide--;
}
// Move carousel to updated slide
moveCarouselTo(slide);
}
}
function disableInteraction() {
// Set 'moving' to true for the same duration as our transition.
// (0.5s = 500ms)
moving = true;
// setTimeout runs its function once after the given time
setTimeout(function(){
moving = false
}, 500);
}
function moveCarouselTo(slide) {
// Check if carousel is moving, if not, allow interaction
if(!moving) {
// temporarily disable interactivity
disableInteraction();
// Update the "old" adjacent slides with "new" ones
var newPrevious = slide - 1,
newNext = slide + 1,
oldPrevious = slide - 2,
oldNext = slide + 2;
// Test if carousel has more than three items
if ((totalItems - 1) > 3) {
// Checks and updates if the new slides are out of bounds
if (newPrevious <= 0) {
oldPrevious = (totalItems - 1);
} else if (newNext >= (totalItems - 1)){
oldNext = 0;
}
// Checks and updates if slide is at the beginning/end
if (slide === 0) {
newPrevious = (totalItems - 1);
oldPrevious = (totalItems - 2);
oldNext = (slide + 1);
} else if (slide === (totalItems -1)) {
newPrevious = (slide - 1);
newNext = 0;
oldNext = 1;
}
// Now we've worked out where we are and where we're going,
// by adding/removing classes we'll trigger the transitions.
// Reset old next/prev elements to default classes
items[oldPrevious].className = itemClassName;
items[oldNext].className = itemClassName;
// Add new classes
items[newPrevious].className = itemClassName + " prev";
items[slide].className = itemClassName + " active";
items[newNext].className = itemClassName + " next";
}
}
}
function initCarousel() {
setInitialClasses();
setEventListeners();
// Set moving to false so that the carousel becomes interactive
moving = false;
}
initCarousel();
}(document));
.carousel-wrapper {
overflow: hidden;
width: 100%;
}
.carousel-wrapper * {
box-sizing: border-box;
}
.carousel {
transform-style: preserve-3d;
}
.carousel__photo {
opacity: 0;
position: absolute;
top:0;
width: 100%;
height:60vw;
max-height:90vh;
margin: auto;
padding: 1rem 4rem;
z-index: 100;
transition: transform .5s, opacity .5s, z-index .5s;
}
.carousel__photo.initial,
.carousel__photo.active {
opacity: 1;
position: relative;
z-index: 900;
}
.carousel__photo.prev,
.carousel__photo.next {
z-index: 800;
}
.carousel__photo.prev {
transform: translateX(-100%); /* Move 'prev' item to the left */
}
.carousel__photo.next {
transform: translateX(100%); /* Move 'next' item to the right */
}
/* buttons */
.carousel__button--prev,
.carousel__button--next {
position: absolute;
top:50%;
width: 3rem;
height: 3rem;
background-color: #FFF;
transform: translateY(-50%);
border-radius: 50%;
cursor: pointer;
z-index: 1001; /* Sit on top of everything */
border: 1px solid black;
}
.carousel__button--prev {
left:0;
}
.carousel__button--next {
right:0;
}
.carousel__button--prev::after,
.carousel__button--next::after {
content: " ";
position: absolute;
width: 10px;
height: 10px;
top: 50%;
left: 54%;
border-right: 2px solid black;
border-bottom: 2px solid black;
transform: translate(-50%, -50%) rotate(135deg);
}
.carousel__button--next::after {
left: 47%;
transform: translate(-50%, -50%) rotate(-45deg);
}
<div class="carousel-wrapper">
<div class="carousel">
<img class="carousel__photo initial" src="https://i.imgur.com/sKV54PO.jpeg">
<img class="carousel__photo" src="https://i.imgur.com/dZH9gh8.jpeg">
<img class="carousel__photo" src="https://i.imgur.com/TBgEy0n.jpeg">
<img class="carousel__photo" src="https://i.imgur.com/1PeQdB4.jpeg">
<img class="carousel__photo" src="https://i.imgur.com/ox8Cp47.jpeg">
<div class="carousel__button--next"></div>
<div class="carousel__button--prev"></div>
</div>
</div>
I created a variable translateAmount that starts at 0 and tracks where the carousel is at, and then it translates by the current amount. That way you can always translate it the right amount, your count variable keeps track of the number of pictures.
I also put a width 100% on the .item and width 200% on the .main div. I needed this because with the display: flex it tends to put everything in the screen.
Take a look:
HTML/JS
<html>
<head>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<div class="content">
<div class="container container-slide">
<div class="main">
<div class="item">
<div class="image" style="background-image: url('https://i.redd.it/7nk7p8gl90371.jpg')">
<div class="info">
<div class="buttons-info">
<div class="show-main-text">
<span>title item 2</span>
</div>
</div>
<div class="buttons-item">
<a href="#">
<button><span>button 1</span></button>
</a>
</div>
</div>
<div class="show-list-pages">
<div class="show-current-page">
<span>1</span>
</div>
<div class="show-count-pages">
<span>/ 2</span>
</div>
</div>
</div>
</div>
<div class="item">
<div class="image" style="background-image: url('https://i.redd.it/7nk7p8gl90371.jpg')">
<div class="info">
<div class="buttons-info">
<div class="show-main-text">
<span>title item 2</span>
</div>
</div>
<div class="buttons-item">
<a href="#">
<button><span>button 1</span></button>
</a>
</div>
</div>
<div class="show-list-pages">
<div class="show-current-page">
<span>1</span>
</div>
<div class="show-count-pages">
<span>/ 2</span>
</div>
</div>
</div>
</div>
<div class="item">
<div class="image" style="background-image: url('https://assets.hongkiat.com/uploads/minimalist-dekstop-wallpapers/4k/original/14.jpg')">
<div class="info">
<div class="buttons-info">
<div class="show-main-text">
<span>title item 1</span>
</div>
</div>
<div class="buttons-item">
<a href="#">
<button><span>button 1</span></button>
</a>
</div>
</div>
<div class="show-list-pages">
<div class="show-current-page">
<span>1</span>
</div>
<div class="show-count-pages">
<span>/ 2</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<button class="prev">prev</button>
<button class="next">next</button>
<script>
var count = 1;
var next = document.querySelector('button.next');
var items = document.querySelectorAll('div.item');
var size = items[0].clientWidth;
let translateAmount = 0;
next.addEventListener("click", function(e)
{
if(count == 3) {
return;
}
count++;
translateAmount -= size;
document.querySelector('div.main').style.transition = 'transform 1.0s ease-in-out';
document.querySelector('div.main').style.transform = 'translateX(' + translateAmount + 'px)';
});
var prev = document.querySelector('button.prev');
prev.addEventListener("click", function(e)
{
if(count == 1) {
return;
}
count--;
translateAmount += size;
document.querySelector('div.main').style.transition = 'transform 1.0s ease-in-out';
document.querySelector('div.main').style.transform = 'translateX(' + translateAmount + 'px)';
});
</script>
</body>
</html>
CSS
.content {
/* margin-left: 50px; */
border: 0px solid red;
width: 100vw;
overflow: hidden;
}
.container {
width: 100%;
height: 600px;
}
.main {
display: flex;
width: fit-content;
}
.item {
width: 100vw;
}
.container-slide {
width: 100%;
/* height: 50%; */
/* overflow: hidden; */
/* position: relative; */
}
.image {
width: 100%;
min-height: 600px;
max-height: 600px;
background-clip: padding-box;
/* float: left; */
background-size: cover;
background-position: center center;
position: relative;
}
.info {
position: absolute;
bottom: 0;
left: 0;
width: 70%;
color: white;
background: green;
padding: 20px;
display: inline-flex;
align-items: center;
justify-content: center;
}
.buttons-info {
margin-left: 30px;
}
button.prev, button.next {
margin-top: 50px;
}
.show-list-pages {
position: absolute;
bottom: 20px;
right: 10px;
display: inline-flex;
align-items: center;
justify-content: center;
color: white;
}
I am trying to achieve a "next page" slide animation in CSS and Javascript. If user clicks a div page, the current page move left and fade out and next page will replace the current container.
This is what I tried, but I don't know how to change container to have dimensions based on current page.
(function () {
document.querySelectorAll(".page").forEach((item, idx) => {
if (idx !== 0) {
item.classList.add("hidden");
item.style.maxHeight = 0;
} else {
}
});
document.querySelectorAll(".page").forEach((item) => {
item.addEventListener("click", (event) => {
const currentPage = event.target.closest(".page");
const nextPage = currentPage.nextElementSibling;
nextPage.style.maxHeight = "1000px";
nextPage.classList.add("show-page");
currentPage.classList.add("hide-page");
});
});
})();
.container {
font-family: inherit;
position: fixed;
bottom: 40px;
right: 40px;
background-color: #eb6383;
width: 300px;
padding: 10px;
display: flex;
flex-direction: column;
overflow: hidden;
}
.page {
display: flex;
flex-direction: column;
transition: 1s;
left: 0%;
opacity: 1;
position: relative;
background-color: yellow;
}
.hidden {
position: relative;
overflow: hidden;
left: 100%;
transition: 1s;
}
.show-page {
position: relative;
left: 0%;
transition: 1s;
}
.hide-page {
opacity: 0;
left: -100%;
transition: 1s;
}
<div class="container">
<div class="page">
<div class="Header">page 1</div>
<div class="Content">
content page 1
</div>
</div>
<div class="page">
<div class="Header">page 2</div>
<div class="Content">
content page 2
</div>
</div>
<div class="page">
<div class="Header">page 3</div>
<div class="Content">
content page 3
</div>
</div>
</div>
Instead of moving each slide on it's own, we can animate a parent element holding all the slides
Here's a simplified version.
(function() {
let slides = document.querySelectorAll('.page');
let slidesCount = slides.length
let index = 0; // index
slides.forEach(slide => {
slide.onclick = (e) => {
/* Logic */
let nextIndex = (++index % slidesCount);
/* End Logic */
/* Management for the CSS */
// By how much we want to move, In Percents.
// A negative value because we're moving left
let ditance = -100;
// If nextIndex = 2, Then rawCssValue = -200
let styleValue = nextIndex * ditance;
/* Applying the CSS */
let style = `translateX(${styleValue}%)`;
e.target.parentElement.style.transform = style;
}
});
})()
.container {
font-family: inherit;
position: fixed;
bottom: 40px;
right: 40px;
width: 300px;
background: #eb6383;
overflow: hidden;
}
.page {
display: flex;
transition: 1s;
left: 0%;
opacity: 1;
position: relative;
background-color: yellow;
}
/* New */
.page {
flex: 0 0 auto;
height: 100%;
width: 100%;
}
.page + .page {
margin-left: 20px;
}
.slide {
padding: 10px;
box-sizing: border-box;
height: 100%;
display: flex;
flex-wrap: nowrap;
background: #eb6383;
transition: all .5s linear;
transform: translateX(0);
}
<div class="container">
<div class="slide">
<div class="page">
<div class="Header">page 1</div>
<div class="Content">
content page 1
</div>
</div>
<div class="page">
<div class="Header">page 2</div>
<div class="Content">
content page 2
</div>
</div>
<div class="page">
<div class="Header">page 3</div>
<div class="Content">
content page 3
</div>
</div>
<div class="page">
<div class="Header">page 4</div>
<div class="Content">
content page 4
</div>
</div>
</div>
</div>
I recommend using buttons for navigating through the slider, clicking the page to the move will become problematic very quick Because the children consume the event.
I have a packery.js layout of divs of three different sizes. I would like them to appear in random order every time the page loads but so far I can only get the content inside the divs to randomize. So on refresh I get the divs in the same order/pattern but the content inside in a different order.
Here's the basic HTML:
<div class="container">
<div class="grid">
<div class="grid-item grid-item--height2">
<div class="grid-item-content">
<p>content here</p>
</div>
</div>
<div class="grid-item grid-item--width2">
<div class="grid-item-content">
<p>content here</p>
</div>
</div>
<div class="grid-item">
<div class="grid-item-content">
<p>content here</p>
</div>
</div>
</div>
</div>
Here's my CSS:
.grid {
width: 100vw;
}
/* clear fix */
.grid:after {
content: '';
display: block;
clear: both;
}
/* ---- .grid-item ---- */
.grid-item {
float: left;
width: 120px;
height: 120px;
background: #ffffff;
border: 2px solid hsla(0, 0%, 0%, 0.5);
}
.grid-item:hover {
cursor: pointer;
}
.grid-item--width2 { width: 240px; }
.grid-item--height2 { height: 240px; }
.grid-item--large {
width: 480px;
height: 300px;
background-color: slategrey;
}
& my Javascript:
var $grid = $('.grid').packery({
itemSelector: '.grid-item'
});
$grid.on( 'click', '.grid-item', function( event ) {
// change size of item by toggling large class
$( event.currentTarget ).toggleClass('grid-item--large');
// trigger layout after item size changes
$grid.packery('layout');
});
(function($) {
$.fn.randomize = function(tree, childElem) {
return this.each(function() {
var $this = $(this);
if (tree) $this = $(this).find(tree);
var unsortedElems = $this.children(childElem);
var elems = unsortedElems.clone();
elems.sort(function() { return (Math.round(Math.random())-0.5); });
for(var i=0; i < elems.length; i++)
unsortedElems.eq(i).replaceWith(elems[i]);
});
};
})(jQuery);
$(document).ready(function() {
$(".container").css("display", "block");
$("div.grid").randomize("div.grid-item");
});
I don't know if I'm just putting the js in the wrong order or something but I can't figure it out - I would really appreciate a push in the right direction!
Thank you.
The reason of only content being rendomized is because you are sorting children nodes of div.grid-item instead of children of div.grid
Second, i think packery is adding absolute positioning to the grid-item nodes. So fixing js code would not reflect the correct positioning unless
position: relative !important;
left: 0 !important;
top: 0 !important;
is added to .grid-item class.
Created a pen for this.
https://codepen.io/11kodykay11/pen/xxwVOra
So I figured it out, in case anyone is wondering.
The HTML (the inline CSS is just to illustrate that the divs randomize in order, not just the content):
<div class="container">
<div class="grid">
<div class="grid-item">
<div style="background-color: red;" class="grid-item-content expand">
<p>content here #1</p>
</div>
</div>
<div class="grid-item">
<div style="background-color: blue;" class="grid-item-content expand">
<p>content here #2</p>
</div>
</div>
<div class="grid-item">
<div style="background-color: green;" class="grid-item-content expand">
<p>content here #3</p>
</div>
</div>
<div class="grid-item">
<div style="background-color: yellow;" class="grid-item-content expand">
<p>content here #4</p>
</div>
</div>
<div class="grid-item">
<div style="background-color: orange;" class="grid-item-content expand">
<p>content here #5</p>
</div>
</div>
<div class="grid-item">
<div style="background-color: purple;" class="grid-item-content expand">
<p>content here #6</p>
</div>
</div>
</div>
</div>
The CSS:
.expand {
display: block;
width: 150px;
height: 150px;
}
.expand:hover {
cursor: pointer;
}
.grid-item-content {
width: 150px;
height: 150px;
border: 1px solid black;
}
.grid-item--large {
width: 520px;
height: 375px;
}
& the JS:
$(document).ready(function () {
var $grid = $(".grid").packery({
itemSelector: ".grid-item"
});
$grid.on("click", ".expand", function (event) {
$(event.currentTarget).toggleClass("grid-item--large");
$grid.packery("layout");
});
});
(function ($) {
$.fn.randomize = function (tree, childElem) {
return this.each(function () {
var $this = $(this);
if (tree) $this = $(this).find(tree);
var unsortedElems = $this.children(childElem);
var elems = unsortedElems.clone();
elems.sort(function () {
return Math.round(Math.random()) - 0.5;
});
for (var i = 0; i < elems.length; i++)
unsortedElems.eq(i).replaceWith(elems[i]);
});
};
})(jQuery);
$("div.grid").randomize("div.grid-item");
Codepen link: https://codepen.io/ddmmyyyy/pen/OJyQmQz
As the title suggest, I am making a div with a fixed attributes then stops when the user reaches a certain point scrolling.
Below is a GIF sample of the event i'm trying to replicate.
http://i.imgur.com/wCXAOwW.gifv
and here's my fiddle:
https://jsfiddle.net/e1u4rqtk/2/
var navWrap = $('#cont'),
nav = $('cont'),
startPosition = navWrap.offset().top,
stopPosition = $('#stop').offset().top - nav.outerHeight();
$(document).scroll(function() {
//stick nav to top of page
var y = $(this).scrollTop()
if (y > startPosition) {
nav.addClass('sticky');
if (y > stopPosition) {
nav.css('top', stopPosition - y);
} else {
nav.css('top', 0);
}
} else {
nav.removeClass('sticky');
}
});
But its not properly working. any idea what did i miss?
You don't need javascript for that, you can use position: sticky
HTML: (you don't need those extra divs)
<div class="d" id="fixedscroll">
<img src="https://ormuco.com/wp-content/uploads/2018/08/Large-Rectangle-336-x-280-Google-Ads-1-1-336x250.jpg">
</div>
CSS:
.d {
background-color: #FFF000;
width: 336px;
height: 600px;
margin: 0px auto;
}
#fixedscroll img {
position: sticky;
top: 0px;
}
Check it working https://jsfiddle.net/w9n2ubmg/
https://developer.mozilla.org/en-US/docs/Web/CSS/position
You can use position: sticky for newer version of browser, but in case you want your website work under IE/Edge 15, check out this example.
$(function(){
$("#adArea").css("min-height", $("#adArea").height());
var stopPos = $("#ad").offset().top;
var contPost = $("#adArea").next().offset().top - $("#ad").height();
$(document).scroll(function(){
var scrollTop = $(this).scrollTop();
if(scrollTop >= stopPos){
if(!$("#ad").hasClass("sticky")) $("#ad").addClass("sticky");
if(scrollTop >= contPost){
$("#ad").css("top", contPost - scrollTop);
}else{
$("#ad").css("top", 0);
}
}else{
if($("#ad").hasClass("sticky")) $("#ad").removeClass("sticky");
}
});
});
.container {
width: 100%;
background-color: #c2c2c2;
}
.block {
padding: 30px 0;
width: 100%;
border: 1px solid #000;
}
.sticky {
position: fixed;
top: 0;
}
#stop {
border:1px solid blue;
bottom: 0;
position: absolute;
width:100%;
}
#stop{
display:block;
}
#ad {
width: 336px;
height: 250px;
background-color: #000;
}
#adContainer {
padding: 50px 0px 300px 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="block"></div>
<div class="block" ></div>
<div class="block" ></div>
<div id="adArea">
<div id="adContainer">
<div id="ad"></div>
</div>
</div>
<div class="block"></div>
<div class="block"></div>
<div class="block" ></div>
<div class="block" ></div>
<div class="block" ></div>
<div class="block" ></div>
<div class="block" ></div>
<div class="block" ></div>
<div class="block" ></div>
<div class="block" ></div>
<div class="block" ></div>
</div>
I have created a Fadein/Fadeout slider. Left button and right button are working fine but I want to play slider by clicking on tab buttons.
JSfiddle
HTML
<p id="slide1_controls">
<div class="block-icon icon-s1">
<img class="block-img icon-s1" src="../_images/building_icon1.png" data-hover-image="../_images/building_icon1_hover.png" data-selected="false" />
</div>
<div class="block-icon icon-s2">
<img class="block-img icon-s2" src="../_images/building_icon2.png" data-hover-image="../_images/building_icon2_hover.png" data-selected="false" />
</div>
<div class="block-icon icon-s3">
<img class="block-img icon-s3" src="../_images/building_icon3.png" data-hover-image="../_images/building_icon3_hover.png" data-selected="false" />
</div>
<div class="block-icon icon-s4">
<img class="block-img icon-s4" src="../_images/building_icon4.png" data-hover-image="../_images/building_icon4_hover.png" data-selected="false" />
</div>
</p>
<div class="slider-text-context" id="target">
<div class="slide-01 fade-texts active">tab1</div>
<div class="slide-02 fade-texts">tab2</div>
<div class="slide-03 fade-texts">tab3</div>
<div class="slide-04 fade-texts">tab4</div>
</div>
CSS
.fade-texts {
width: 100%;
height: 259px;
left: 0px;
position: absolute;
}
.slider-btn-area {
position: absolute;
z-index: 8;
margin-left: auto;
margin-right: auto;
left: 25%;
top: 54%;
width: 50%;
}
#target > div {
display:none;
}
#target div:nth-child(1) {
display:block;
}
.tab-area {
position: absolute;
left: 25%;
top: 30%;
}
Javascript
$(".icon-s2").click(function() {
activeElem = $("#target .slide-02");
activeElem.removeClass('active').fadeOut(0);
if (!activeElem.is(':first-child')) {
activeElem.removeClass('active').fadeOut(0).prev().addClass('active').fadeIn(400);
}
}
$(".icon-s3").click(function() {
activeElem = $("#target .slide-03");
activeElem.removeClass('active').fadeOut(0);
if (!activeElem.is(':first-child')) {
activeElem.removeClass('active').fadeOut(0).prev().addClass('active').fadeIn(400);
}
}
When I press the tab it does not work to try to appear a DIV.
Your code made no sense. The way it looked was that the images had to be clicked in order to fadeIn/Out the tabs. I believe it should be the other way. I cleaned up the markup, and simplified the classes, ids, styles, etc...
Here's the DEMO
HTML
<div id="slides">
<div id="slide1" class="slide active">
<img class="img" src="http://placehold.it/150x50/000/Fff.png&text=FIRST" />
</div>
<div id="slide2" class="slide">
<img class="img" src="http://placehold.it/150X50/048/Fee.png&text=SECOND" />
</div>
<div id="slide3" class="slide">
<img class="img" src="http://placehold.it/150X50/fa8/375.png&text=THIRD" />
</div>
<div id="slide4" class="slide">
<img class="img" src="http://placehold.it/150X50/9a7/a10.png&text=FOURTH" />
</div>
</div>
<div class="tab-area" id="controls">
<div id="tab1" class="tab">1</div>
<div id="tab2" class="tab">2</div>
<div id="tab3" class="tab">3</div>
<div id="tab4" class="tab">4</div>
</div>
CSS
.slide {
display:none;
}
.active {
display: block;
}
.tab {
width: 16px;
height: 16px;
display: inline-block;
margin: 0 10px;
outline: 1px solid black;
text-align: center;
cursor: pointer;
}
jQuery/JavaScript
$(function () {
$('.tab').on('click', function (event) {
var tabID = event.target.id;
//console.log('tabID: '+tabID);
var order = tabID.split('b').pop();
//console.log('order: '+order);
var pos = parseInt(order, 10);
var slideID = 'slide'+pos;
//console.log('slideID: '+slideID);
var act = document.getElementById(slideID);
//console.log('act: '+act.id);
$('.slide').fadeOut(0).removeClass('active');
$(act).addClass('active').fadeIn(750);
});
});