<div class="intro">
  <h1>CSS Journal</h1>
  <svg aria-label="scroll down" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
    <path stroke-linecap="round" stroke-linejoin="round" d="m4.5 5.25 7.5 7.5 7.5-7.5m-15 6 7.5 7.5 7.5-7.5" />
  </svg>
</div>
<section>
  <article>
    <figure class="rotate-right">
      <img src="https://assets.codepen.io/159218/NFC_0415.jpg" alt="Wing of a plane in the air" />
      <figcaption>Bon voyage</figcaption>
    </figure>
    <div class="entry">
      <p>Passport? Check! Luggage? Check! On tot he plane and enjoy the flight to your destination. A bit of chewing gum, sunglasses on, and away we go.</p>
    </div>
  </article>
  <article>
    <div class="entry">
      <p>Enjoy the rustic charm of the hotel, after a long flight, you deserve a little drink at the bar. Kick back for a while, let it all sink in and enjoy the facilities.</p>
    </div>
    <figure class="rotate-left">
      <img src="https://assets.codepen.io/159218/NFC_0404.jpg" alt="A lightbulb hanging in front of articles on the wall" />
      <figcaption>The Hotel Lights</figcaption>
    </figure>
  </article>
  <article>
    <figure class="rotate-right">
      <img src="https://assets.codepen.io/159218/NFC_0361.jpg" alt="A bunch of overground grey pipes" />
      <figcaption>Pipes in Berlin</figcaption>
    </figure>
    <div class="entry">
      <p>Time to do a little sightseeing. Take out your trusty camera or phone and start taking some pictures. Be careful not to overdo it. Enjoy the sights, take it all in. A memory and a feeling is more than just you taking a photo. Who knows what secrets the next street brings.</p>
    </div>
  </article>
  <article>
    <div class="entry">
      <p>No matter what you enjoy: Historic, Modern, architecture, nature. Enjoy these little moments you get to spend at your location.</p>
    </div>
    <figure class="rotate-left">
      <img src="https://assets.codepen.io/159218/NFC_0312.jpg" alt="Three high office buildings during the blue hour" />
      <figcaption>Office buildings</figcaption>
    </figure>
  </article>
</section>
<div class="warning">
  This demo uses scroll driven animations in CSS, it seems your current browser does not support this.<br />
  However, if you are using one of the evergreen browsers, you should notice this page still works even without them.
</div>
@import url("https://fonts.googleapis.com/css2?family=Annie+Use+Your+Telescope&display=swap");

@layer base, intro, layout, figures, entry;

@property --clip-1 {
  syntax: "<percentage>";
  initial-value: 0%;
  inherits: false;
}

@property --clip-2 {
  syntax: "<percentage>";
  initial-value: 0%;
  inherits: false;
}

@layer intro {
  .intro {
    display: flex;
    flex-direction: column;
    height: 100dvh;
    place-content: center;
    place-items: center;
    animation: scaleDown linear both;
    animation-timeline: view(block);
    animation-range: contain 80% exit-crossing 100%;
    & svg {
      width: 5vw;
      height: 5vw;
      animation: scrollIndicator 4s ease-out infinite;
    }
  }

  @keyframes scrollIndicator {
    0% {
      opacity: 0;
      transform: translateY(0);
    }
    25% {
      opacity: 1;
    }
    50% {
      opacity: 1;
    }
    100% {
      opacity: 0;
      transform: translateY(100%);
    }
  }

  @keyframes scaleDown {
    to {
      scale: 0;
      opacity: 0;
    }
  }
}

@layer figures {
  figure {
    --rotate: 20deg;

    position: relative;
    aspect-ratio: 1;
    background: white;
    box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;

    container: frame;
    container-type: size;

    animation: rotate linear both;
    animation-timeline: view(block);
    animation-range: cover 20% contain 30%;
    @media (max-width: 749px) {
      max-width: 300px;
      align-self: center;
    }
  }

  @keyframes rotate {
    entry 100%,
    exit 0% {
      opacity: 1;
      rotate: var(--rotate);
    }
    exit 100% {
      opacity: 0;
      rotate: 0deg;
    }
  }

  img {
    aspect-ratio: 1;
    object-fit: cover;

    clip-path: inset(var(--clip-1) var(--clip-1) var(--clip-2) var(--clip-1));
    animation: createFrame linear both;
    animation-timeline: view(block);
    animation-range: cover 15% contain 40%;
  }

  @keyframes createFrame {
    to {
      --clip-1: 5%;
      --clip-2: 15%;
      box-shadow: rgba(50, 50, 93, 0.25) 0px 6px 12px -2px,
        rgba(0, 0, 0, 0.3) 0px 3px 7px -3px;
    }
  }

  figcaption {
    --clip-1: 100%;

    position: absolute;
    inset-inline: 5cqw;
    bottom: 1.2cqh;
    font-size: 8cqh;
    text-overflow: ellipsis;
    white-space: nowrap;
    overflow: hidden;
    z-index: 1;

    clip-path: inset(0 var(--clip-1) 0 0);
    animation: revealText linear both;
    animation-timeline: view(block);
    animation-range: cover 25% contain 35%;
  }

  @keyframes revealText {
    to {
      --clip-1: 0%;
    }
  }
}

@layer entry {
  article {
    display: grid;
    align-items: center;
    gap: 8vmax;
    @media (min-width: 750px) {
      grid-template-columns: 2fr 3fr;
      gap: 10vmax;
    }
    &:has(.entry + figure) {
      @media (min-width: 750px) {
        grid-template-columns: 3fr 2fr;
      }
      figure {
        --rotate: -20deg;
      }
    }
  }
  .entry {
    animation: revealEntry linear both;
    animation-timeline: view(block);
    animation-range: cover 20% contain 40%;
  }

  @keyframes revealEntry {
    from {
      color: transparent;
      transform: translateY(20%);
    }
    to {
      color: black;
      transform: translateY(0%);
    }
  }

  .entry p {
    font-size: clamp(1.25rem, 0.9891rem + 1.3043vi, 2rem);
    background-image: repeating-linear-gradient(
      to top,
      #95d9c3 0 0.125rem,
      transparent 0.125rem 1lh
    );
    background-position-y: 0.8lh;
    animation: fadein linear both;
    animation-timeline: view(block);
    animation-range: entry 10% contain 10%;
  }

  @keyframes fadein {
    0% {
      opacity: 0;
    }
    100% {
      opacity: 1;
    }
  }
}

@layer layout {
  section {
    display: flex;
    flex-direction: column;
    gap: 40vmax;
    margin-inline: auto;
    padding-inline: 10vmax;
    padding-bottom: 50vh;
    max-width: 1400px;
  }
}

@layer base {
  *,
  *::before,
  *::after {
    box-sizing: border-box;
  }
  body {
    margin: 0;
    font-family: "Annie Use Your Telescope", cursive;
    background: radial-gradient(ivory 70%, transparent 30%),
      radial-gradient(ivory 70%, transparent 30%), #f5f3f3;
    background-size: 5px 5px;
  }

  figure {
    padding: 0;
    margin: 0;
  }

  img {
    display: block;
    width: 100%;
    max-width: 100%;
  }

  h1 {
    margin: 0;
    font-size: 10vw;
  }
  .warning {
    display: none;
  }
}

@layer supportfixes {
  @supports not (animation-timeline: view(block)) {
    .intro {
      animation: none;
    }
    section * {
      animation: none;
    }
    figure {
      rotate: var(--rotate);
    }
    figcaption {
      --clip-1: 0%;
    }
    img {
      --clip-1: 5%;
      --clip-2: 15%;
      box-shadow: rgba(50, 50, 93, 0.25) 0px 6px 12px -2px,
        rgba(0, 0, 0, 0.3) 0px 3px 7px -3px;
    }

    .warning {
      position: fixed;
      top: 1rem;
      left: 1rem;
      padding: 1rem;
      border: 5px solid deeppink;
      background: white;
      display: block;
      font-family: Arial, Helvetica, sans-serif;
    }
  }

  @media (prefers-reduced-motion) {
    .intro {
      animation: none;
    }
    section * {
      animation: none;
    }
    figure {
      rotate: var(--rotate);
    }
    figcaption {
      --clip-1: 0%;
    }
    img {
      --clip-1: 5%;
      --clip-2: 15%;
      box-shadow: rgba(50, 50, 93, 0.25) 0px 6px 12px -2px,
        rgba(0, 0, 0, 0.3) 0px 3px 7px -3px;
    }
  }
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.