Home > Software design >  Cards animation without using z-index
Cards animation without using z-index

Time:05-13

I'm building an animation for cards. I wonder how to have the same effect for the card animation however without animating the z-index. The animation should use only transform and opacity properties.

I want to achieve the same effect(as demonstrated below) without using z-index in the animation, because it will cause painting to occur.

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

body {
  font-family: Arial, Helvetica, sans-serif;
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.container {
  position: relative;
}

.item {
  padding: 8px;
  background-color: blue;
  color: white;
  opacity: 0;
  height: 30px;
  width: 32px;
  text-align: center;
  position: absolute;
  top: auto;
  bottom: 0;
  animation: AnimateCard 16s infinite
    cubic-bezier(0.48, 0.18, 0.35, 1.01);
}

.item:nth-child(1) {
  animation-delay: -9s;
}
.item:nth-child(2) {
  animation-delay: -5s;
}
.item:nth-child(3) {
  animation-delay: -1s;
}
.item:nth-child(4) {
  animation-delay: 3s;
}

@keyframes AnimateCard {
  0% {
    transform: translateY(-72px);
    z-index: 1;
    opacity: 0;
  }
  26% {
    transform: translateY(-72px);
    z-index: 1;
    opacity: 0.2;
  }
  34% {
    transform: translateY(-36px);
    z-index: 1;
    opacity: 0.3;
  }
  51% {
    transform: translateY(-36px);
    z-index: 1;
    opacity: 0.3;
  }
  58% {
    transform: translateY(0);
    opacity: 1;
  }
  74% {
    transform: translateY(0);
    opacity: 1;
  }
  100% {
    transform: translateY(0);
    opacity: 0;
  }
}
<div >
  <div >1</div>
  <div >2</div>
  <div >3</div>
  <div >4</div>
</div>

CodePudding user response:

In order to achieve a more marked fading effect between 4 and 1, I've applied two changes:

  • removed z-index from keyframes
  • changed 100% keyframe with 83%, so that it will fade away before 100%.

Here's the full snippet:

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

body {
  font-family: Arial, Helvetica, sans-serif;
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.container {
  position: relative;
}

.item {
  padding: 8px;
  background-color: blue;
  color: white;
  opacity: 0;
  height: 30px;
  width: 32px;
  text-align: center;
  position: absolute;
  top: auto;
  bottom: 0;
  animation: AnimateCard 16s infinite
    cubic-bezier(0.48, 0.18, 0.35, 1.01);
}

.item:nth-child(1) {
  animation-delay: -9s;
}
.item:nth-child(2) {
  animation-delay: -5s;
}
.item:nth-child(3) {
  animation-delay: -1s;
}
.item:nth-child(4) {
  animation-delay: 3s;
}

@keyframes AnimateCard {
  0% {
    transform: translateY(-72px);
    opacity: 0;
  }
  26% {
    transform: translateY(-72px);
    opacity: 0.2;
  }
  34% {
    transform: translateY(-36px);
    opacity: 0.3;
  }
  51% {
    transform: translateY(-36px);
    opacity: 0.3;
  }
  58% {
    transform: translateY(0);
    opacity: 1;
  }
  74% {
    transform: translateY(0);
    opacity: 1;
  }
  83% {
    transform: translateY(0);
    opacity: 0;
  }
}
<div >
  <div >1</div>
  <div >2</div>
  <div >3</div>
  <div >4</div>
</div>

CodePudding user response:

We can clip the bottom most rectangle to height 0 as top one collapse on it:

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

body {
  font-family: Arial, Helvetica, sans-serif;
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.container {
  position: relative;
}

.item {
  padding: 8px;
  background-color: blue;
  color: white;
  opacity: 0;
  height: 30px;
  width: 32px;
  text-align: center;
  position: absolute;
  top: auto;
  bottom: 0;
  animation: AnimateCard 16s infinite cubic-bezier(0.48, 0.18, 0.35, 1.01);
}

.item:nth-child(1) {
  animation-delay: -9s;
}

.item:nth-child(2) {
  animation-delay: -5s;
}

.item:nth-child(3) {
  animation-delay: -1s;
}

.item:nth-child(4) {
  animation-delay: 3s;
}

@keyframes AnimateCard {
  0% {
    transform: translateY(-72px);
    opacity: 0;
  }
  26% {
    transform: translateY(-72px);
    opacity: 0.2;
  }
  34% {
    transform: translateY(-36px);
    opacity: 0.3;
  }
  51% {
    transform: translateY(-36px);
    opacity: 0.3;
  }
  58% {
    transform: translateY(0);
    opacity: 1;
  }
  74% {
    transform: translateY(0);
    opacity: 1;
  }
  76% {
    clip: rect(0px, 32px, 32px, 0px);
  }
  85% {
    clip: rect(32px, 32px, 32px, 0px);
  }
  100% {
    transform: translateY(0);
    opacity: 0;
  }
}
<div >
  <div >1</div>
  <div >2</div>
  <div >3</div>
  <div >4</div>
</div>

CodePudding user response:

I removed z-index from keyframes and just do small changes into your existing CSS style code so check below snippet.

*,::before, ::after {
    padding: 0;
    margin: 0;
    box-sizing: border-box;
}
body {
    font-family: Arial, Helvetica, sans-serif;
    min-height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    margin: 0;
    padding: 0;
}
.container {
    position: relative;
    box-shadow: 0 0 0 1px red;
    height: 200px;
    width: 64px;
    overflow: hidden;
}
.item {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 8px;
    background-color: blue;
    color: white;
    height: 60px;
    width: 64px;
    text-align: center;
    position: absolute;
    top: auto;
    bottom: 0;
    animation: AnimateCard 16s infinite cubic-bezier(0.48, 0.18, 0.35, 1.01);
}
.item:nth-child(1) {
    animation-delay: -9s;
}
.item:nth-child(2) {
    animation-delay: -5s;
}
.item:nth-child(3) {
    animation-delay: -1s;
}
.item:nth-child(4) {
    animation-delay: 3s;
}
@keyframes AnimateCard {
  0% {
    transform: translateY(-210px);
    opacity: 0;
  }
  26% {
    transform: translateY(-140px);
    opacity: 0.5;
  }
  34% {
    transform: translateY(-70px);
    opacity: 0.2;
  }
  51% {
    transform: translateY(-70px);
    opacity: 0.2;
  }
  58% {
    transform: translateY(0);
    opacity: 1;
  }
  74% {
    transform: translateY(0);
    opacity: 1;
  }
  91% {
    transform: translateY(140px);
    opacity: 1;
  } 
  100% {
    transform: translateY(210px);
    opacity: 0;
  }
}
<div >
    <div >1</div>
    <div >2</div>
    <div >3</div>
    <div >4</div>
</div>

  • Related