I m creating ticker in which the divs will be scrolling infinitely vertically on next/prev buttons ... I have created it but there is a small issue in it .. when i click on prev button the divs scrolls upward on first click and after that it scrolls downward and same goes for next button as well ..Someone help please
var buttons = $('.next-prev');
$(buttons).each(function(){
$(this).click(function(){
var id = $(this).attr('id');
if(id=="next"){
$('#scroll-div').stop().animate({scrollTop:40},400,'swing',function(){
$(this).scrollTop(0).find('div:last').after($('div:first', this));
});
}
else {
$('#scroll-div').stop().animate({scrollTop:40},400,'swing',function(){
$(this).scrollTop(40).find(' div:first').before($(' div:last', this));
});
}
})
})
* {
box-sizing: border-box;
}
#scroll-div {
overflow: hidden;
width: 300px;
height: 250px;
background: green;
padding: 10px;
}
#scroll-div div {
display: block;
height: 30px;
padding: 10px 10px;
margin-bottom: 10px;
background: cyan;
}
.item:last-child {
margin-bottom: 0px;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<button class="next-prev" id="next">
up
</button>
<button class="next-prev" id="prev">
down
</button>
</div>
<div id="scroll-div">
<div>div 1</div>
<div>div 2</div>
<div>div 3</div>
<div>div 4</div>
<div>div 5</div>
<div>div 6</div>
<div>div 7</div>
<div>div 8</div>
<div>div 9</div>
<div>div 10</div>
</div>
var buttons = $('.next-prev');
$('#scroll-div').prepend($('#scroll-div').find('div:last-child')); // prepend last element
$('#scroll-div').scrollTop(40); // scroll div to position 40 so first (div 10) not visible
$(buttons).each(function(){
$(this).click(function(){
var id = $(this).attr('id');
if(id=="next"){
$('#scroll-div').append($('#scroll-div').find('div:first-child')); //do modification first
} else {
$('#scroll-div').prepend($('#scroll-div').find('div:last-child'));
}
$('#scroll-div').stop().animate({scrollTop:40},400,'swing'); // then scroll
})
})
* {
box-sizing: border-box;
}
#scroll-div {
overflow: hidden;
width: 300px;
height: 250px;
background: green;
padding: 10px;
}
#scroll-div div {
display: block;
height: 30px;
padding: 10px 10px;
margin-bottom: 10px;
background: cyan;
}
.item:last-child {
margin-bottom: 0px;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<button class="next-prev" id="next">
up
</button>
<button class="next-prev" id="prev">
down
</button>
</div>
<div id="scroll-div">
<div>div 1</div>
<div>div 2</div>
<div>div 3</div>
<div>div 4</div>
<div>div 5</div>
<div>div 6</div>
<div>div 7</div>
<div>div 8</div>
<div>div 9</div>
<div>div 10</div>
</div>
Related
I have a Swiper but can't resize the navigation arrows for some reason.
.swiper-button-next,
.swiper-button-prev {
color: white !important;
fill: white !important;
stroke: white !important;
width: 10px !important;
height: 10px !important;
}
It does not matter what values I give, the arrows stay the same.
An easy and straightforward solution is to remove the default arrows and use custom ones. To do so, you need:
.swiper-button-prev:after,
.swiper-button-next:after {
display: none;
}
And then have for example an icon for each controller like so:
<div class="swiper-button-next">Custom</div>
<div class="swiper-button-prev">Custom</div>
Here is a working live demo to get an idea:
var swiper = new Swiper(".mySwiper", {
navigation: {
nextEl: ".swiper-button-next",
prevEl: ".swiper-button-prev"
}
});
html,
body {
height: 100%;
}
.swiper {
width: 100%;
height: 100%;
}
.swiper-slide {
text-align: center;
display: grid;
place-items:center;
}
.swiper-button-prev:after,
.swiper-button-next:after {
display: none;
}
i{
color:crimson;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css" rel="stylesheet"/>
<link href="https://cdn.jsdelivr.net/npm/swiper/swiper-bundle.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/swiper/swiper-bundle.min.js"></script>
<div class="swiper mySwiper">
<div class="swiper-wrapper">
<div class="swiper-slide">Slide 1</div>
<div class="swiper-slide">Slide 2</div>
<div class="swiper-slide">Slide 3</div>
<div class="swiper-slide">Slide 4</div>
<div class="swiper-slide">Slide 5</div>
<div class="swiper-slide">Slide 6</div>
<div class="swiper-slide">Slide 7</div>
<div class="swiper-slide">Slide 8</div>
<div class="swiper-slide">Slide 9</div>
</div>
<div class="swiper-button-next"><i class="fa-solid fa-circle-chevron-right fa-2x"></i></div>
<div class="swiper-button-prev"><i class="fa-solid fa-circle-chevron-left fa-2x"></i></div>
</div>
I'm creating a vertical slider and I need to have one slide bigger than the others. I usually use Flickity but as it doesn't support Vertical slides, I'm using Swiper.js.
The thing is every row should be the same size but that's not my case. What I've done is to create a cell that is 2x the size of a normal slide, and then track if I'm going to slide to that cell, then move two slides, so I skip one that it's not used.
The problem is that the last one is hidden. I've added one extra and then hidden the last one. I know it's a very tricky solution.
I think there might be better ways so I wanted to ask if you think my solution could be emproved? I attatch you the code:
https://codepen.io/scros/pen/LYVJKrQ
var swiper = new Swiper(".swiper-container", {
direction: "vertical",
slidesPerView: 4,
spaceBetween: 15,
// slidesPerGroup: 2,
cssMode: true,
pagination: {
el: ".swiper-pagination",
clickable: true
}
});
console.log(swiper.params);
swiper.on("slideNextTransitionStart", function() {
console.log("slide changed");
console.log(swiper.activeIndex);
if (swiper.activeIndex === 1) {
swiper.slideTo(2, 700);
}
});
swiper.on("slidePrevTransitionStart", function() {
console.log("slide changed");
console.log(swiper.activeIndex);
if (swiper.activeIndex === 1) {
swiper.slideTo(0, 700);
}
});
.swiper-container {
width: 600px;
height: 500px;
overflow: hidden;
}
.swiper-slide {
border-radius: 0.3rem;
font-size: 18px;
color: white;
background-color: #8ec5fc;
background-image: linear-gradient(62deg, #8ec5fc 0%, #e0c3fc 100%);
display: flex;
justify-content: center;
align-items: center;
}
.slide1 {
padding: 4rem 0;
}
.wrapper {
background-color: #eef2f7;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
<link href="https://idangero.us/swiper/dist/css/swiper.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.3.2/js/swiper.min.js"></script>
<div class="wrapper">
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide slide1">
<h1>Big Slide</h1>
</div>
<div class="swiper-slide slide">Slide 2</div>
<div class="swiper-slide">Slide 3</div>
<div class="swiper-slide">Slide 4</div>
<div class="swiper-slide">Slide 5</div>
<div class="swiper-slide">Slide 6</div>
<div class="swiper-slide">Slide 7</div>
<div class="swiper-slide">Slide 8</div>
<div class="swiper-slide">Slide 9</div>
<div class="swiper-slide">Slide 10</div>
<div class="swiper-slide"></div>
</div>
</div>
</div>
Thanks!
I'm creating vertically auto scrolling divs using jquery with animation... I have finished creating it but the only problem is when I scroll down the window to the middle of list div where divs are scrolling, it pushes the window up to the scrolling list div. I don't know what the problem is. However when I try to give the list div width in pixels, it is not pushing up...
Try to scroll down to the middle of the scrolling list div. You will understand what the problem is. Thanks...
setInterval(function(){
$('#list').stop().animate({scrollTop:40}, 400, 'swing', function(){
$(this).scrollTop(0).find('div:last').after($('div:first', this));
});
}, 1000);
* {
box-sizing: border-box;
}
body {
height: 1000px;
}
#list {
overflow: hidden;
width: 100%;
height: 250px;
background: red;
padding: 10px;
margin-top: 100px;
}
#list div {
display: block;
height: 30px;
padding: 10px 10px;
margin-bottom: 10px;
background: yellow;
}
.item:last-child {
margin-bottom: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="list">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
<div>Item 4</div>
<div>Item 5</div>
<div>Item 6</div>
<div>Item 7</div>
<div>Item 8</div>
<div>Item 9</div>
<div>Item 10</div>
</div>
What an odd bug. From what I can tell, because of the removal/insertion of the first element to the end of the list, this results in Chrome re-rendering the list causing the change in your scrollY offset.
Personally, I can think of two ways to address the issue.
1) Remove the div (#list) from the DOM flow.
Note: This requires wrapping your #list element in a containing element.
Because your removing/appending elements to your #list element, this is causing a reflow to occur (???). Initially, I thought using position: absolute would address this, as you're no longer affecting the DOM flow. However, even position: absolute still causes the scroll position to jump.
I then looked at position: fixed, which DOES work (as it's basically sitting on top of everything) - This obviously isn't going to work as you want the list to scroll with the page! So, how can we get around this??
transform to the rescue!
Let's take advantage of a transform quirk! Usually, when an element is position: fixed, it's relative to the viewport. However, if an ancestor element has a transformation, the element that is fixed positioned will be relative to the transformed element. Let's give this a shot!
As I mentioned, you'll need to apply a wrapping/containing element to transform. In the code snippet below, I've wrapped your #list element with a new div#transformed.
CSS changes are straight forward and look like:
#transformed { transform: translateZ(0); }
#list { position: fixed; }
And that is it! Check out the snippet below to see it in action.
setInterval(function(){
$('#list').stop().animate({scrollTop:40}, 400, 'swing', function(){
$(this).find('div:last').after($('div:first', this));
});
}, 1000);
* {
box-sizing: border-box;
}
body {
height: 1000px;
}
#transformed {
transform: translateZ(0);
}
#list {
position: fixed;
overflow: hidden;
width: 100%;
height: 250px;
background: red;
padding: 10px;
margin-top: 100px;
}
#list div {
display: block;
height: 30px;
padding: 10px 10px;
margin-bottom: 10px;
background: yellow;
}
.item:last-child {
margin-bottom: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="transformed">
<div id="list">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
<div>Item 4</div>
<div>Item 5</div>
<div>Item 6</div>
<div>Item 7</div>
<div>Item 8</div>
<div>Item 9</div>
<div>Item 10</div>
</div>
</div>
2) Sliding a layer
As for the second way to address the issue, this is more a discussion/opinion on how to approach this (so, unfortunately can't provide code).
Rather than manipulate the scrollTop, I would look into a "sliding" layer approach (either using transformY or top).
You'll find JS-based carousels take a similar approach (funny enough, carousels tend to either use a scroll-offset approach - as similar to this question, or a "sliding" layer approach! They just tend to do it horizontally)
As for the layer you manipulate, again I would suggest removing it from the DOM flow (so position: absolute). In theory, manipulating this layer shouldn't affect the scroll offset...
Anyway, hope this was helpful and the position: fixed approach works for you :)
Edit
Regarding your comment, you can achieve a "downward" scroll by reversing your setInterval logic. However, instead of scrolling and then moving the item that just scrolled out to the bottom of the list, you will need to move the element you want to scroll in to the top of the list, offset the scrollTop, and then scroll in.
Here's a snippet that demonstrates:
setInterval(function(){
$('#list')
.find('div:first')
.before($('div:last', '#list'))
.end()
.scrollTop(40)
.stop()
.animate({scrollTop:0}, 400, 'swing');
}, 1000);
* {
box-sizing: border-box;
}
body {
height: 1000px;
}
#transformed {
transform: translateZ(0);
}
#list {
position: fixed;
overflow: hidden;
width: 100%;
height: 250px;
background: red;
padding: 10px;
margin-top: 100px;
}
#list div {
display: block;
height: 30px;
padding: 10px 10px;
margin-bottom: 10px;
background: yellow;
}
.item:last-child {
margin-bottom: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="transformed">
<div id="list">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
<div>Item 4</div>
<div>Item 5</div>
<div>Item 6</div>
<div>Item 7</div>
<div>Item 8</div>
<div>Item 9</div>
<div>Item 10</div>
</div>
</div>
Edit # 2:
Regarding up/down buttons, you can easily achieve that by combining the two scripts we've written so far! Here's are two snippets that animates up/down when you click (the first will scroll each time you click, and the second snippet will change the animation direction):
function animateList(direction) {
if (direction === 'down') {
$('#list')
.find('div:first')
.before($('div:last', '#list'))
.end()
.scrollTop(40)
.stop()
.animate({scrollTop:0}, 400, 'swing');
} else {
$('#list')
.animate({scrollTop:40}, 400, 'swing', function(){
$(this)
.find('div:last')
.after($('div:first', this));
});
}
}
$('button').on('click', function () {
var direction = $(this).attr('id');
animateList(direction);
});
* {
box-sizing: border-box;
}
body {
height: 1000px;
}
#transformed {
transform: translateZ(0);
}
#list {
position: fixed;
overflow: hidden;
width: 100%;
height: 250px;
background: red;
padding: 10px;
margin-top: 100px;
}
#list div {
display: block;
height: 30px;
padding: 10px 10px;
margin-bottom: 10px;
background: yellow;
}
.item:last-child {
margin-bottom: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="transformed">
<div id="list">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
<div>Item 4</div>
<div>Item 5</div>
<div>Item 6</div>
<div>Item 7</div>
<div>Item 8</div>
<div>Item 9</div>
<div>Item 10</div>
</div>
</div>
<button id="up">Scroll Up</button>
<button id="down">Scroll Down</button>
And the snippet that changes the direction:
var interval;
function animateList(direction) {
// Reset interval
if (interval) {
clearInterval(interval);
}
if (direction === 'down') {
interval = setInterval(function () {
$('#list')
.find('div:first')
.before($('div:last', '#list'))
.end()
.scrollTop(40)
.stop()
.animate({scrollTop:0}, 400, 'swing');
}, 1000);
} else {
interval = setInterval(function () {
$('#list')
.animate({scrollTop:40}, 400, 'swing', function(){
$(this)
.find('div:last')
.after($('div:first', this));
});
}, 1000);
}
}
$('button').on('click', function () {
var direction = $(this).attr('id');
animateList(direction);
});
// Initial animation
animateList('up');
* {
box-sizing: border-box;
}
body {
height: 1000px;
}
#transformed {
transform: translateZ(0);
}
#list {
position: fixed;
overflow: hidden;
width: 100%;
height: 250px;
background: red;
padding: 10px;
margin-top: 100px;
}
#list div {
display: block;
height: 30px;
padding: 10px 10px;
margin-bottom: 10px;
background: yellow;
}
.item:last-child {
margin-bottom: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="transformed">
<div id="list">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
<div>Item 4</div>
<div>Item 5</div>
<div>Item 6</div>
<div>Item 7</div>
<div>Item 8</div>
<div>Item 9</div>
<div>Item 10</div>
</div>
</div>
<button id="up">Scroll Up</button>
<button id="down">Scroll Down</button>
I have converted your inner divs to a unordered list. I added an overflow-y:scroll initially, which also worked, but changed it to overflow-y:hidden on seeing your comment. I found but both work. If you scroll down the page and then scroll back up, it doesn't 'start again' (unless it's had the time to iterate though all 10 list items). You may need to adjust the css/box height to get the red border at the bottom, but I'll leave this to you
Hope this helps
Overflow-hidden:
setInterval(function() {
$('#ulList').stop().animate({
scrollTop: 40
}, 400, 'swing', function() {
$(this).scrollTop(0).find('li:last').after($('li:first', this));
});
}, 1000);
* {
box-sizing: border-box;
}
body {
height: 1000px;
}
#list {
overflow-y:hidden;
width: 100%;
height: 250px;
background: red;
padding: 10px;
margin-top: 100px;
}
#list ul {
margin: 10px 10px;
padding: 10px 0px;
}
#list ul li {
display: block;
height: 30px;
margin-bottom: 10px;
background: yellow;
}
.item:last-child {
margin-bottom: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="list">
<ul id="ulList">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
<li>Item 10</li>
</ul>
</div>
Overflow:scroll
setInterval(function() {
$('#ulList').stop().animate({
scrollTop: 40
}, 400, 'swing', function() {
$(this).scrollTop(0).find('li:last').after($('li:first', this));
});
}, 1000);
* {
box-sizing: border-box;
}
body {
height: 1000px;
}
#list {
overflow-y:scroll;
width: 100%;
height: 250px;
background: red;
padding: 10px;
margin-top: 100px;
}
#list ul {
margin: 10px 10px;
padding: 10px 0px;
}
#list ul li {
display: block;
height: 30px;
margin-bottom: 10px;
background: yellow;
}
.item:last-child {
margin-bottom: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="list">
<ul id="ulList">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
<li>Item 10</li>
</ul>
</div>
I have a sidebar which I want to scroll conditionally. I have provided the structure. In the layout both left and right side has lots of content. What I want when a user scroll down, let the both side scroll together. When the bottom of the right section comes visible, I want right section to stop going up, and let the left section keep scrolling. And when the user scrolls up, let the both left and right section scroll up. When the top edge of the right section comes visible, I want right section to stop scrolling anymore and let the left section keep scrolling on its own. How can I achieve this layout?
.main{
width : 100%;
}
.mainBody{
width: calc(100% - 200px);
background-color: pink;
display : inline-block;
}
.mainBody div{
margin-bottom : 500px;
}
.Sidebar{
display : inline-block;
width : 200px;
float: right;
background-color : yellow;
}
.Sidebar div{
margin-bottom : 350px;
}
<div class="main">
<div class="mainBody">
<div>Hello World 1</div>
<div>Hello World 2</div>
<div>Hello World 3</div>
<div>Hello World 4</div>
<div>Hello World 5</div>
</div>
<div class="Sidebar">
<div>Sidebar Section 1</div>
<div>Sidebar Section 2</div>
<div>Sidebar Section 3</div>
<div>Sidebar Section 4</div>
<div>Sidebar Section 5</div>
</div>
</div>
you mean this ?
$(window).on("scroll", function() {
wh = $(this).height(),
st = $(this).scrollTop(),
side = $(".Sidebar"),
sh = side.outerHeight();
if( (st + wh) >= sh ) {
side.addClass("fixed");
} else {
side.removeClass("fixed");
}
})
.main{
width : 100%;
}
.mainBody{
width: calc(100% - 200px);
background-color: pink;
display : inline-block;
}
.mainBody div{
margin-bottom : 500px;
}
.Sidebar{
display : inline-block;
width : 200px;
float: right;
background-color : yellow;
}
.Sidebar div{
margin-bottom : 350px;
}
.Sidebar.fixed{
position: fixed;
right: 0;
bottom: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main">
<div class="mainBody">
<div>Hello World 1</div>
<div>Hello World 2</div>
<div>Hello World 3</div>
<div>Hello World 4</div>
<div>Hello World 5</div>
</div>
<div class="Sidebar">
<div>Sidebar Section 1</div>
<div>Sidebar Section 2</div>
<div>Sidebar Section 3</div>
<div>Sidebar Section 4</div>
<div>Sidebar Section 5</div>
</div>
</div>
If you want to stop scrolling right section when its reach bottom , you need to set max-height of left section to that right section height , also set overflow property ....
var sidebarHeight = $('.Sidebar').height();
$(".mainBody").css({"max-height": sidebarHeight, "overflow-y":"scroll"});
.main{
width : 100%;
}
.mainBody{
width: calc(100% - 200px);
background-color: pink;
display : inline-block;
}
.mainBody div{
margin-bottom : 500px;
}
.Sidebar{
display : inline-block;
width : 200px;
float: right;
background-color : yellow;
}
.Sidebar div{
margin-bottom : 350px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main">
<div class="mainBody">
<div>Hello World 1</div>
<div>Hello World 2</div>
<div>Hello World 3</div>
<div>Hello World 4</div>
<div>Hello World 5</div>
</div>
<div class="Sidebar">
<div>Sidebar Section 1</div>
<div>Sidebar Section 2</div>
<div>Sidebar Section 3</div>
<div>Sidebar Section 4</div>
<div>Sidebar Section 5</div>
</div>
</div>
First of all get the height of sidebar $('#sidebar').height() and decrease window height $(window).height(); from sidebar height then you can apply/add fixed class .fixed-right-bar. Like given below example:-
var sidebarHeight = $('#sidebar').height();
var documentHeight = $(window).height();
$(window).on('scroll', function(){
if($(window).scrollTop() > sidebarHeight-documentHeight){
$('#sidebar').addClass('fixed-right-bar');
}
else{
$('#sidebar').removeClass('fixed-right-bar');
}
});
.main{
width : 100%;
}
.mainBody{
width: calc(100% - 200px);
background-color: pink;
display : inline-block;
}
.mainBody div{
margin-bottom : 500px;
}
.Sidebar{
display : inline-block;
width : 200px;
float: right;
background-color : yellow;
}
.Sidebar div{
margin-bottom : 350px;
}
.fixed-right-bar{ position:fixed; right:0; bottom:0;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="main">
<div class="mainBody">
<div>Hello World 1</div>
<div>Hello World 2</div>
<div>Hello World 3</div>
<div>Hello World 4</div>
<div>Hello World 5</div>
</div>
<div class="Sidebar" id="sidebar">
<div>Sidebar Section 1</div>
<div>Sidebar Section 2</div>
<div>Sidebar Section 3</div>
<div>Sidebar Section 4</div>
<div>Sidebar Section 5</div>
</div>
</div>
I am experimenting with a tile-like layout for my site with which the user can interact. Each box is a button used to select a product, and upon selection of a product, the other boxes fade out and are hidden. This effect is toggle-able.
I have slightly modified the following fiddle that I found online, and it comes very close the desired result.
$('.box').click(function() {
$('.box').not(this).fadeToggle(250);
});
div.box {
width: 100px;
height: 63px;
background-color: #52c6ec;
margin: 5px;
padding-top: 37px;
float: left;
text-align: center;
color: #fff;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="box" id="box1">Box 1</div>
<div class="box" id="box2">Box 2</div>
<div class="box" id="box3">Box 3</div>
<div class="box" id="box4">Box 4</div>
<div class="box" id="box5">Box 5</div>
<div class="box" id="box6">Box 6</div>
<div class="box" id="box7">Box 7</div>
<div class="box" id="box8">Box 8</div>
<div class="box" id="box9">Box 9</div>
<div class="box" id="box10">Box 10</div>
<div class="box" id="box11">Box 11</div>
<div class="box" id="box12">Box 12</div>
<div class="box" id="box13">Box 13</div>
<div class="box" id="box14">Box 14</div>
<div class="box" id="box15">Box 15</div>
<div class="box" id="box16">Box 16</div>
<div class="box" id="box17">Box 17</div>
<div class="box" id="box18">Box 18</div>
<div class="box" id="box19">Box 19</div>
<div class="box" id="box20">Box 20</div>
The only thing I want to do is to have the selected item transition (via animation) to the top-left, rather than just appearing there. Preferably also during the fading of the other boxes.
Because I'm using floats here, I cannot figure out how to animate these, since they don't have any numeric properties.
Ideas for a jQuery solution? Thanks.
Is this what you want?
var t, l, loctop, locleft;
$('.box').click(function() {
var e = $(this);
if( $('.box').not(this).is(':visible') )
{
t = e.position().top + 'px';
l = e.position().left + 'px';
loctop = locleft = 0;
$(this).css( {position: 'fixed', top:t, left:l} );
$('.box').not(this).fadeToggle(550, function(){
$(e).animate({
top: loctop,
left: locleft
}, 800, function(){
$(this).stop(true, true);
});
});
}
else
{
loctop = parseInt(t);
locleft = parseInt(l);
$(e).animate({
top: loctop,
left: locleft
}, 800, function(){
$('.box').not(this).fadeIn(550, function(){
$(e).css( {position: 'relative', top:'', left:''} );
});
});
}
});
div.box {
width: 100px;
height: 63px;
background-color: #52c6ec;
margin: 5px;
padding-top: 37px;
float: left;
text-align: center;
color: #fff;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="box" id="box1">Box 1</div>
<div class="box" id="box2">Box 2</div>
<div class="box" id="box3">Box 3</div>
<div class="box" id="box4">Box 4</div>
<div class="box" id="box5">Box 5</div>
<div class="box" id="box6">Box 6</div>
<div class="box" id="box7">Box 7</div>
<div class="box" id="box8">Box 8</div>
<div class="box" id="box9">Box 9</div>
<div class="box" id="box10">Box 10</div>
<div class="box" id="box11">Box 11</div>
<div class="box" id="box12">Box 12</div>
<div class="box" id="box13">Box 13</div>
<div class="box" id="box14">Box 14</div>
<div class="box" id="box15">Box 15</div>
<div class="box" id="box16">Box 16</div>
<div class="box" id="box17">Box 17</div>
<div class="box" id="box18">Box 18</div>
<div class="box" id="box19">Box 19</div>
<div class="box" id="box20">Box 20</div>
Here's my attempt in vanilla JS (tested on Chrome and Firefox)
Basically it works only with CSS transitions over the transform property for the selected element and over the opacity for all the other elements. The fadeOut/In runs while the selected element is moving as you specified.
CodePen Demo
CSS
main {
display: flex;
flex-wrap: wrap;
border: 1px solid #ccc;
}
div {
background: #a0c6df;
width: 100px;
height: 100px;
border: 2px #8fa0c6 dashed;
margin: 10px;
opacity: 1;
cursor: pointer;
transition: all 1s;
}
main.fadeout div:not(.current) {
opacity: 0;
cursor: default;
}
JS
var main = document.querySelector('main');
var boxes = document.querySelectorAll('main div');
var animationIsRunning = false;
var getBoxPosition = function() {
[].forEach.call(boxes, function(b) {
var gBCR = b.getBoundingClientRect();
b.dataset.top = gBCR.top;
b.dataset.left = gBCR.left;
});
}
window.addEventListener('resize', function() {
var dc;
getBoxPosition();
if (dc = main.querySelector('div.current')) {
main.classList.remove('fadeout');
dc.classList.remove('current');
dc.style.transform = 'translate(0,0)';
}
});
main.addEventListener('click', function(evt) {
var b = evt.target,
left = 0,
top = 0;
/* listen to the div click event only */
if (b.nodeName.toLowerCase() !== 'div') { return false; }
/* don't listen if there's a current element and user clicked
over a hidden div */
if (
main.querySelector('.current') &&
!b.classList.contains('current')
) { return false; }
/* only if another animation is not running... */
if (!animationIsRunning) {
animationIsRunning = true;
b.classList.toggle('current');
main.classList.toggle('fadeout');
if (b.classList.contains('current')) {
left = b.dataset.left;
top = b.dataset.top;
}
b.style.transform = 'translate(-'+ left +'px, -'+ top +'px)';
}
});
main.addEventListener('transitionend', function() {
animationIsRunning = false;
});
getBoxPosition();
Take a look at this awesome plugin (http://isotope.metafizzy.co/) from David Desandro
You can find an exemple on codepen here :
http://codepen.io/desandro/pen/nFrte
An exemple from isotope blog :
// external js: isotope.pkgd.js
var $notifElem;
$( document ).ready( function() {
var $grid = $('.grid').isotope({
itemSelector: '.grid-item',
masonry: {
columnWidth: 100
}
});
$grid.on( 'layoutComplete', function( event, laidOutItems ) {
console.log( 'layoutComplete with ' + laidOutItems.length + ' items' );
});
$grid.on( 'click', '.grid-item', function() {
// change size of item by toggling gigante class
$( this ).toggleClass('grid-item--gigante');
$grid.isotope('layout');
});
});
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
body {
font-family: sans-serif;
}
/* ---- grid ---- */
.grid {
background: #DDD;
max-width: 1200px;
}
/* clear fix */
.grid:after {
content: '';
display: block;
clear: both;
}
/* ---- .grid-item ---- */
.grid-item {
float: left;
width: 100px;
height: 100px;
background: #0D8;
border: 2px solid #333;
border-color: hsla(0, 0%, 0%, 0.7);
}
.grid-item--width2 { width: 200px; }
.grid-item--height2 { height: 200px; }
.grid-item:hover {
background: #8CF;
cursor: pointer;
}
.grid-item--gigante {
width: 200px;
height: 300px;
background: #F80;
}
.notification {
position: fixed;
background: black;
opacity: 0;
color: white;
font-size: 16px;
padding: 0.5em;
right: 0;
top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.isotope/2.2.2/isotope.pkgd.js"></script>
<h1>Isotope - layoutComplete</h1>
<p>Open Developer Console to view event logs.</p>
<p>Click item to toggle size</p>
<div class="grid">
<div class="grid-item grid-item--width2"></div>
<div class="grid-item grid-item--height2"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--width2 grid-item--height2"></div>
<div class="grid-item grid-item--width2"></div>
<div class="grid-item grid-item--width2"></div>
<div class="grid-item grid-item--height2"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--width2"></div>
<div class="grid-item grid-item--height2"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--width2"></div>
<div class="grid-item grid-item--height2"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--width2"></div>
<div class="grid-item grid-item--height2"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
</div>
<div class="notification"></div>
Hope this will be very useful for you. I have created full working
code You can use this.
var a=0;
$('.box').click(function() {
if(a==0){
var position = $(this).position();
$( "this" ).text( "left: " + position.left + ", top: " + position.top );
$(this).css({
"position":"absolute",
"left":position.left,
"top":position.top
})
$('.box').not(this).fadeOut(250);
$(this).animate({
"left":"0px",
"top":"0px"
}, 1000);
a=1;
}
else{
$('.box').not(this).fadeIn(250);
$(this).css({"position":"static"});
a=0;
}
});
div.box {
width: 100px;
height: 63px;
background-color: #52c6ec;
margin: 5px;
padding-top: 37px;
float: left;
text-align: center;
color: #fff;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="box" id="box1">Box 1</div>
<div class="box" id="box2">Box 2</div>
<div class="box" id="box3">Box 3</div>
<div class="box" id="box4">Box 4</div>
<div class="box" id="box5">Box 5</div>
<div class="box" id="box6">Box 6</div>
<div class="box" id="box7">Box 7</div>
<div class="box" id="box8">Box 8</div>
<div class="box" id="box9">Box 9</div>
<div class="box" id="box10">Box 10</div>
<div class="box" id="box11">Box 11</div>
<div class="box" id="box12">Box 12</div>
<div class="box" id="box13">Box 13</div>
<div class="box" id="box14">Box 14</div>
<div class="box" id="box15">Box 15</div>
<div class="box" id="box16">Box 16</div>
<div class="box" id="box17">Box 17</div>
<div class="box" id="box18">Box 18</div>
<div class="box" id="box19">Box 19</div>
<div class="box" id="box20">Box 20</div>