<div class="card" data-text="Full of vitamins and minerals">
  <div class="card__brand">
    <h2>果物</h2>
    <h3>The fruit store</h3>
  </div>
  <div class="card__image">
    <img src="https://i.imgur.com/XXPLapu.png" alt="orange" loading="lazy" onload="setTimeout(() => imageLoaded(this), 0)" width="500" height="750">
  </div>
  <div class="card__title">
    <h1>オレンジ</h1>
    <hr>
    <p>
      オレンジはミカン科ミカン属の常緑小高木、またはその果実のこと。
    </p>
    <hr>
    <p>
      The orange is the fruit of the citrus species &#171;Citrus × sinensis&#187; in the family Rutaceae, native to China.
    </p>
    <p class="card__title__tag">
      グラム:130g
    </p>
  </div>
  <span class="card__ripple"></span>
</div>

<div class="card" data-text="Instant energy">
  <div class="card__brand">
    <h2>果物</h2>
    <h3>The fruit store</h3>
  </div>
  <div class="card__image">
    <img src="https://i.imgur.com/j8S8ciK.png" alt="banana" loading="lazy" onload="setTimeout(() => imageLoaded(this), 0)" width="500" height="750">
  </div>
  <div class="card__title">
    <h1>バナナ</h1>
    <hr>
    <p>
      バナナは、バショウ科バショウ属のうち、果実を食用とする品種群の総称である。
    </p>
    <hr>
    <p>
      A banana is an edible fruit – produced by several kinds of large herbaceous flowering plants in the genus Musa.
    </p>
    <p class="card__title__tag">
      グラム:120g
    </p>
  </div>
  <span class="card__ripple"></span>
</div>

<div class="card" data-text="Rich source of Antioxidants">
  <div class="card__brand">
    <h2>果物</h2>
    <h3>The fruit store</h3>
  </div>
  <div class="card__image">
    <img src="https://i.imgur.com/DE6lwqa.png()" alt="avocado" loading="lazy" onload="setTimeout(() => imageLoaded(this), 0)" width="500" height="750">
  </div>
  <div class="card__title">
    <h1>アボカド</h1>
    <hr>
    <p>
      アボカドとは、クスノキ科ワニナシ属の常緑高木およびその果実。
    </p>
    <hr>
    <p>
      The avocado, a tree with probable origin in south-central Mexico, is classified as a member of the flowering plant family Lauraceae.
    </p>
    <p class="card__title__tag">
      グラム:170g
    </p>
  </div>
  <span class="card__ripple"></span>
</div>
@import url('https://fonts.googleapis.com/css?family=Noto+Sans+JP:100,400&display=swap&subset=japanese');

:root {
  --card-size: 70vw;
  --card-padding: calc(var(--card-size) / 35);
  --fruit-size: 150%;
  --fruit-color-orange: #a79ab6;
  --fruit-color-banana: #143956;
  --fruit-color-avocado: #ec8f4c;
  --transition-easing-function: cubic-bezier(0.7, 0.0, 0.1, 1);
  --transition-duration: 600ms;
  --transition-blur-duration: 2000ms;
  --transition-drop-duration: 150ms;
  --transition-text-duration: 500ms;
  
  @media (min-width: 1000px) {
    --card-size: 40vw;
  }
}

%image-blur {
  filter: blur(5px) contrast(1.2);
  opacity: 0.05;
  will-change: filter, opacity, transform;
  transform: scale(0.9);
  transition: 
    filter var(--transition-blur-duration) var(--transition-easing-function),
    opacity var(--transition-blur-duration) var(--transition-easing-function),
    transform var(--transition-blur-duration) var(--transition-easing-function);
} 

%image-filter {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  will-change: opacity;
  opacity: 0;
  transition: opacity calc(var(--transition-duration) / 2) var(--transition-easing-function);
  
  .card--in & {
    opacity: 1;
  }
}

%text-translate {
  opacity: 0;
  will-change: opacity, transform;
  transform: translate(0, -1vw);
  transition: 
    transform var(--transition-text-duration) calc(var(--transition-duration) + calc(var(--transition-duration) / 4)) var(--transition-easing-function),
    opacity var(--transition-text-duration) calc(var(--transition-duration) + calc(var(--transition-duration) / 4)) var(--transition-easing-function);
  
  .card--in & {
    opacity: 1;
    transform: translate(0, 0);
  }
}

.card {
  background-color: rgba(255, 255, 255, 0);
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  height: calc(var(--card-size) / 3.5);
  padding: var(--card-padding);
  box-shadow: 0 0 0 rgba(0, 0, 0, 0.0), 0 0 0 rgba(255, 255, 255, 0.0), 0 0 0 0 rgba(255, 255, 255, 0.0);
  transition: 
    background-color calc(var(--transition-duration) / 4) var(--transition-easing-function),
    box-shadow var(--transition-duration) var(--transition-easing-function);
  
  &+.card {
    margin-top: calc(var(--card-size) / 3.5);
  }
  
  &:not(.card--in) {
    @extend %image-blur;
    
    &.card--loaded {
      filter: blur(0) contrast(1);
      opacity: 1;
      transform: scale(1);
    }
  }
  
  &--in {
    animation: var(--transition-drop-duration) var(--transition-easing-function) calc(calc(var(--transition-drop-duration) + 10ms) * -1) 2 alternate drop-animation;
    background-color: rgba(255, 255, 255, 1);
    box-shadow: 20px 10px 20px rgba(0, 0, 0, 0.1), 0 0 20px rgba(255, 255, 255, 0.1), -1px 1px 0 0 rgba(255, 255, 255, 0.05);
  }
  
  &__brand {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    letter-spacing: 0.1em;
    z-index: 1;
    
    h2 {
      font-size: calc(var(--card-size) / 17.5);
      border: calc(var(--card-size) / 280) solid currentColor;
      border-radius: 100%;
      height: calc(var(--card-size) / 7);
      width: calc(var(--card-size) / 7);
      white-space: nowrap;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      margin-bottom: calc(var(--card-size) / 70);
      will-change: opacity, transform;
      opacity: 0;
      transform: rotate(-22.5deg);
      transition: 
        opacity var(--transition-duration) var(--transition-duration) var(--transition-easing-function),
        transform var(--transition-duration) var(--transition-duration) var(--transition-easing-function);
      
      .card--in & {
        opacity: 1;
        transform: rotate(0);
      }
    }
    
    h3 {
      font-size: calc(var(--card-size) / 70);
      text-transform: uppercase;
      opacity: 0;
      transition: opacity var(--transition-duration) calc(var(--transition-duration) + calc(var(--transition-duration) / 4)) var(--transition-easing-function);
      
      .card--in & {
        opacity: 1;
      }
    }
  }
  
  &__image {
    position: relative;
    display: flex;
    justify-content: center;
    justify-self: center;
    align-items: center;
    top: calc(var(--card-padding) * -1);
    width: var(--fruit-size);
    height: calc(100% + calc(var(--card-padding) * 2));
    background-size: 90%;
    background-position: center center;
    background-repeat: no-repeat;
    transition: background-size calc(var(--transition-duration) / 1.33) var(--transition-easing-function);
    
    .card--in & {
      background-size: 100%;
    }
    
    img {
      position: absolute;
      object-fit: contain;
      width: 90%;
      height: calc(var(--card-size) / 1.4);
      z-index: -1;
      opacity: 1;
      filter: grayscale(0);
      user-select: none;
      transition: 
        opacity calc(var(--transition-duration) / 2) var(--transition-easing-function),
        filter calc(var(--transition-duration) / 2) var(--transition-easing-function);
      
      .card--in & {
        opacity: .05;
        filter: grayscale(1);
      }
    }
    
    &::before {
      @extend %image-filter;
      background-image: url(https://images.unsplash.com/photo-1533628635777-112b2239b1c7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=80);
      background-position: center center;
      background-size: 100%;
      mix-blend-mode: hard-light;
    }
    
    &::after {
      @extend %image-filter;
      mix-blend-mode: color;
    }
    
    .card:nth-child(1) & {
      background-image: url(https://i.imgur.com/XXPLapu.png);
      &::after {
        background-color: var(--fruit-color-orange);
      }
    }
    
    .card:nth-child(2) & {
      background-image: url(https://i.imgur.com/j8S8ciK.png);
      &::after {
        background-color: var(--fruit-color-banana);
      }
    }
    
    .card:nth-child(3) & {
      background-image: url(https://i.imgur.com/DE6lwqa.png);
      &::after {
        background-color: var(--fruit-color-avocado);
      }
    }
  }
  
  &__title {
    @extend %text-translate;
    display: grid;
    grid-template-rows: repeat(4, auto) 1fr;
    grid-template-columns: 1fr .5fr;
    align-items: flex-start;
    writing-mode: vertical-rl;
    z-index: 1;
    
    h1 {
      @extend %text-translate;
      font-size: calc(var(--card-size) / 23.333);
      transition-delay: calc(var(--transition-duration) + calc(var(--transition-duration) / 4));
    }
    
    hr {
      @extend %text-translate;
      margin-block-start: calc(var(--card-size) / 70);
      margin-block-end: calc(var(--card-size) / 70);
      height: 100%;
      width: calc(var(--card-size) / 350);
      border: unset;
      background-color: currentColor;
      transition-delay: calc(var(--transition-duration) + calc(var(--transition-duration) / 3.5));
      
      &~hr {
        width: calc(var(--card-size) / 700);
        transition-delay: calc(var(--transition-duration) + calc(var(--transition-duration) / 2.75));
      }
    }
    
    p {
      @extend %text-translate;
      font-size: calc(var(--card-size) / 70);
      text-align: justify;
      font-weight: 100;
      transition-delay: calc(var(--transition-duration) + calc(var(--transition-duration) / 2.5));
      
      &:first-of-type {
        writing-mode: vertical-lr;
        letter-spacing: 0.1em;
        transition-delay: calc(var(--transition-duration) + calc(var(--transition-duration) / 3));
      }
    }
    
    &__tag {
      writing-mode: horizontal-tb;
      grid-column: 2;
      grid-row: 1/5;
      justify-self: flex-end;
      letter-spacing: 0.1em;
    }
  }
  
  &__ripple {
    position: absolute;
    display: flex;
    align-items: center;
    justify-content: center;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    opacity: 0.32;
    overflow: hidden;
    contain: strict;
    
    &::before {
      background-color: currentColor;
      content: "";
      position: absolute;
      width: var(--card-size);
      height: var(--card-size);
      box-shadow: 0 0 40px 0 currentColor;
      border-radius: 50%;
      will-change: transform, opacity;
      transform: scale(0);
      transition: 
        transform calc(var(--transition-duration) / 2) ease-out, 
        opacity calc(var(--transition-duration) / 2) ease-out;
        
      .card--in & {
        transform: scale(1);
        opacity: 0;
      }
      
      .card:nth-child(1) & {
        color: var(--fruit-color-orange);
      }
      
      .card:nth-child(2) & {
        color: var(--fruit-color-banana);
      }
      
      .card:nth-child(3) & {
        color: var(--fruit-color-avocado);
      }
    }
  }
}

@keyframes drop-animation {
  to {
    transform: scale(0.97);
  }
}

// Base + reset
html {
  font-family: 'Noto Sans JP', sans-serif;
  font-weight: 400;
  color: #363435;
}

body {
  background-color: white;
  background: linear-gradient(-120deg, white, rgba(54, 52, 53, .05));
  min-height: 100vh;
  margin: unset;
  padding: 20vh calc(calc(100vw - var(--card-size)) * 0.5);
}

h1, h2, h3, p {
  margin: unset;
}
View Compiled
const imageLoaded = (image) => {
  const card = image.parentElement.parentElement;
  card.addEventListener('transitionend', () => {
    observer.observe(card);
  });
  card.classList.add('card--loaded');
}

const observer = new IntersectionObserver(entries => {
  entries.forEach(entry => {
    if (entry.intersectionRatio >= 1) {
      setTimeout(() => {
        requestAnimationFrame(() => {
          entry.target.classList.add('card--in');
        });
      }, 500);
    }
  });
}, { threshold: 1 });

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.