List / Grid / Tile view transitions using jquery or javascript

Viewed 408

I want to achieve list / grid / tile view using Jquery/JS. enter image description here

I have surfed a lot regarding grid/list view with animation, but got only grid/list view solutions. but i need grid/list view along with animation(i,e tranistion effect). I have attached sample video of the transition effect.

3 Answers

Code

https://codepen.io/shahriarkh/pen/NWvOyry?editors=0110

Click the "Change Style" button above the grid to toggle animation.


Here it is!
I used grid because it's animateable, since it's a 2d grid while both block and flex are 1d.

However, there's a problem with the appearing scroll bar on the right. It's damn annoying and I couldn't find a way to fix it. In line 9 of JS code, every card should move to left by 120px * N, but when the scrollbar appears, it's no longer 120 and becomes a bit larger than 120 (like 126). I don't know where it is coming from... although 120 works fine when you add overflow-y: hidden to body, it's not an applicable workaround (you need the scroll!).

Update

I found the solution! Using overflow-y: scroll + scrollbar-width: none does the trick. However, you need to somehow let users know the page is scrollable.


BTW, what's the original video? I'm wondering if it's a webpage and somebody already did this :) Also, Framer Motion might be a good choice instead of harcoding.

Here is my basic implementation. I've tried to create output like the video.
The idea is to wrap list item in a wrapper. Wrappers are statically placed and list items are absolutely placed. When view changes wrapper gets arranged automatically as per stylesheet or container rules. But move list items after with animations.

var pos = [];
var offs = null;

function init() {
  offs = $(".container").first().offset();
  $(".wrapper").each(function (i) {
    updatePositions();
    $(this).children(0).css({
      top: pos[i].top,
      left: pos[i].left
    });
  });
}

$(document).ready(function () {
  init();
});

$(window).resize(function () {
  init();
})

function updatePositions() {
  $(".wrapper").each(function(index) {
    var tp = $(this).offset().top - offs.top;
    var lf = $(this).offset().left - offs.left;
    pos[index] = {
      top: tp,
      left: lf
    };
  });
}

function grid() {
  if ($(".wrapper").first().hasClass("gv-wrapper")) return;
  updatePositions();
  $(".wrapper").each(function(index) {
    $(this).removeClass("dv-wrapper cv-wrapper");
    $(this).addClass("gv-wrapper");

    $(this).children(0).css({
      opacity: 0.8,
      top: pos[index].top,
      left: pos[index].left
    });
  });

  updatePositions();
  $(".wrapper").each(function(index) {
    $(this).children(0).children(0).removeClass("dv-video cv-video");
    $(this).children(0).children(1).removeClass("dv-details cv-details");
    $(this).children(0).children(0).first().addClass("gv-video");
    $(this).children(0).children(1).last().addClass("gv-details");
    $(this).children(0).animate({
      height: "100px",
      width: "200px",
      opacity: 1,
      top: pos[index].top,
      left: pos[index].left
    }, 1000, "swing");
  });
}


function detailed() {
  if ($(".wrapper").first().hasClass("dv-wrapper")) return;

  updatePositions();

  $(".wrapper").each(function(index) {
    $(this).removeClass("gv-wrapper cv-wrapper");
    $(this).addClass("dv-wrapper");

    $(this).children(0).css({
      opacity: 0.8,
      top: pos[index].top,
      left: pos[index].left
    });
  });

  updatePositions();
  $(".wrapper").each(function(index) {
    $(this).children(0).children(0).removeClass("gv-video cv-video");
    $(this).children(0).children(1).removeClass("gv-details cv-details");
    $(this).children(0).children(0).first().addClass("dv-video");
    $(this).children(0).children(1).last().addClass("dv-details");

    $(this).children(0).animate({
      height: "100px",
      width: "95%",
      opacity: 1,
      top: pos[index].top,
      left: pos[index].left
    }, 1000, "swing");
  });
}


function collapsed() {
  if ($(".wrapper").first().hasClass("cv-wrapper")) return;

  updatePositions();
  $(".wrapper").each(function(index) {
    $(this).removeClass("dv-wrapper gv-wrapper");
    $(this).addClass("cv-wrapper");

    $(this).children(0).css({
      opacity: 0.8,
      top: pos[index].top,
      left: pos[index].left
    });
  });

  updatePositions();
  $(".wrapper").each(function(index) {
    $(this).children(0).children(0).removeClass("dv-video gv-video");
    $(this).children(0).children(1).removeClass("dv-details gv-details");
    $(this).children(0).children(0).first().addClass("cv-video");
    $(this).children(0).children(1).last().addClass("cv-details");

    $(this).children(0).animate({
      height: "50px",
      width: "94%",
      opacity: 1,
      top: pos[index].top,
      left: pos[index].left
    }, 1000, "swing");
  });

}
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  counter-reset: number;
  background-color: #ffffff;
  padding: 24px;
}

i.fas {
  margin: 5px;
}

i.fas:hover {
  background-color: white;
}

.container {
  width: 500px;
  min-height: 90vh;
  margin: 0 auto;
  background-color: #ADC2A9;
  border: 1px dotted gray;
  font-size: 0.7em;
  position: relative;
}

.wrapper {
  margin: 10px 10px;
  /* to debug enable the color */
  /*background-color: darkcyan;*/
}

.record {
  position: absolute;
  width: 95%;
  top: 0px;
  left: 0px;
  background-color: #D3E4CD;
}

.record:first-child:before {
  counter-increment: number;
  content: counter(number);
  position: absolute;
  top: 10%;
  left: 10%;
  font-size: 23px;
  color: blue
}

.video {
  width: 200px;
  height: 100px;
  background: linear-gradient(white 40%, #5e819ef8);
}


/* list view */

.dv-wrapper {
  height: 100px;
  width: 95%;
  float: left;
}

.dv-video {}

.dv-details {
  position: absolute;
  width: calc(100% - 200px);
  top: 0px;
  right: 0px;
  float: right;
  padding-left: 10px;
  overflow: hidden;
}


/* grid view */

.gv-wrapper {
  height: 100px;
  width: 200px;
  float: left;
}

.gv-video {
  float: left;
}

.gv-details {
  position: absolute;
  left: 0px;
  bottom: 0px;
  padding-left: 10px;
  overflow: hidden;
}


/* collapsed view */

.cv-wrapper {
  height: 50px;
  width: 80%;
}

.cv-video {
  float: left;
  display: none;
}

.cv-details {
  padding-left: 10px;
  overflow: hidden;
}

.details p {
  width: 100%;
  text-overflow: ellipsis;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" rel="stylesheet" />

<div style="margin: 0 50%; width: 100px; transform: translate(-50%);">
  <i class="fas fa-list" onclick="detailed()"></i>
  <i class="fa fa-th" onclick="grid()"></i>
  <i class="fas fa-bars" onclick="collapsed()"></i>
</div>
<div class="container">
  <div class="dv-wrapper wrapper">
    <div class="record">
      <div class="video dv-video"></div>
      <div class="details dv-details">
        <p>1 Lorem ipsum dolor sit amet consectetur adipiorem ipsum dolor sit amet consectetur adipisicing elit. Deserunt, dolor.</p>
      </div>
    </div>
  </div>
  <div class="dv-wrapper wrapper">
    <div class="record">
      <div class="video dv-video"></div>
      <div class="details dv-details">
        <p>2 Lorem ipsum dolor sit amet consectetur adipisicing elit. Deserunt, dolor.</p>
      </div>
    </div>
  </div>
  <div class="dv-wrapper wrapper">
    <div class="record">
      <div class="video dv-video"></div>
      <div class="details dv-details">
        <p>3 Lorem ipsum dolor sit amet consectetur adipisicing elit. Deserunt, dolor.</p>
      </div>
    </div>
  </div>
  <div class="dv-wrapper wrapper">
    <div class="record">
      <div class="video dv-video"></div>
      <div class="details dv-details">
        <p>4 Lorem ipsum dolor sit amet consectetur adipisicing elit. Deserunt, dolor.</p>
      </div>
    </div>
  </div>
  <div class="dv-wrapper wrapper">
    <div class="record">
      <div class="video dv-video"></div>
      <div class="details dv-details">
        <p>5 Lorem ipsum dolor sit amet consectetur adipisicing elit. Deserunt, dolor.</p>
      </div>
    </div>
  </div>

</div>

This is just a demo code. It can be improved in many ways. We can put wrappers in existing grid or flex containers and animate content items like shown above.
Let me know if any readymade third party available that will reduce or improve above code.

I know this does not exactly look like your desired result, but maybe it´s suitable for u or you can build up on it. i just used a transition on width and an interval to have a small delay in the transform.

function toggle(){
  var k= 0;
  var i = setInterval(function(){
t = $('.test').length;
if(k>t){
 clearInterval(t)
}
$('.test').eq(k).toggleClass("test2");
k++;

  },120)
}

setTimeout(function(){
  toggle()
},1000)
.wrap {
  width:500px;
  min-height:100vh;
  position:relative;
  margin: 0 auto;
}
.test {
  color:white;
  margin:10px;
  background:black;
  width:100px;
  height:100px;
  float:left;
  -webkit-transition: width 1s ease-in-out;
  -moz-transition: width 1s ease-in-out;
  -o-transition: width 1s ease-in-out;
  transition: width 1s ease-in-out;
}
.test2 {
  width:100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrap">
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>

  </div>

If u wanted it to be exactly like in the video u would probably have to work with translate-x translate-y

Related