糯麦 NurMai

400-158-5662

糯麦科技

/

新闻资讯

/

技术讨论

/

现代CSS:使用纯CSS实现滚动图像弹出(pop-out)效果

现代CSS:使用纯CSS实现滚动图像弹出(pop-out)效果

原创 新闻资讯

于 2023-11-29 09:18:59 发布

12720 浏览

本文阐述使用 CSS 滚动驱动动画(scroll-driven animations)和零 JS 创建滚动图片弹出效果。


1.Scroll-driven Animations

Scroll-driven Animations 是网络上一种常见的用户体验模式。这些动画与滚动容器的滚动位置相关联。这意味着当你向上或向下滚动时,链接的动画会直接向前或向后刷新。想想有趣的效果,比如视差背景图片或随着滚动而移动的阅读指示器。一种类似的滚动驱动动画是与元素在其滚动容器中的位置相关联的动画。例如,有了它,元素可以在进入视图时淡入。


实现这类效果的经典方法是在主线程中响应滚动事件。这使得创建与滚动同步的高性能滚动驱动动画变得不可能或非常困难。有了 Scroll-driven Animations 规范,您现在可以使用新的 API 和概念来实现声明式滚动驱动动画,并与现有的 Web Animations API (WAAPI) 和 CSS Animations API 配合使用。


通过将滚动驱动动画与这两个现有的 API 集成,滚动驱动动画可以从这些 API 带来的所有优势中获益。这包括让这些动画脱离主线程运行的能力。现在可以在主线程外运行由滚动驱动的如丝般顺滑的动画,而这一切只需几行额外的代码即可以实现。


Scroll-driven Animation 规范中定义了两种新的 timeline,可以指定动画在元素滚动条滚动时运行,@keyframes 的进度也就跟着滚动进度进行。

•  Scroll Progress Timeline: 表示容器已滚动的距离,从0%到100%

•  View Progress Timeline: 标识容器内的元素相对于滚动距离的相对位置,从0%到100%。


本实践中使用的就是 View Progress Timeline,同时还使用到一个属性 animation-range:


该属性定义了动画在时间轴上的附加范围的起始和结束位置,即动画将在时间轴的哪个位置开始和结束。它包含两个子属性,可以分别来设置动画的起始和结束位置:

•  animation-start:指定动画的起始位置,可以使用百分比、时间值或关键字来表示。

•  animation-end:指定动画的结束位置,可以使用百分比、时间值或关键字来表示。


2.实现方案

2.1.创建页面框架

<main>
  <section class="first"><h2>xxx</h2></section>
  <section>
    <div class="pop-out-image skateboarder">
      <figure>
        <img src="https://assets.codepen.io/605876/skateboarder.jpeg"/>
      </figure>
      <figure aria-hidden="true">
        <img src="https://assets.codepen.io/605876/skateboarder-bg-removed.png"/>
      </figure>
    </div>
  </section>
  <section>
    <div class="pop-out-image snowboarder">
      <figure>
        <img src="https://assets.codepen.io/605876/snowboarder.jpeg"/>
      </figure>
      <figure aria-hidden="true">
        <img src="https://assets.codepen.io/605876/snowboarder-bg-removed.png"/>
      </figure>
    </div>
  </section>
  <section>
    <div class="pop-out-image mtb">
      <figure>
        <img
          src="https://assets.codepen.io/605876/mtb.jpeg"
          alt="skateboarder doing a trick mid air"
        />
      </figure>
      <figure aria-hidden="true">
        <img src="https://assets.codepen.io/605876/mtb-bg-removed.png" />
      </figure>
    </div>
  </section>
  <section>
    <div class="pop-out-image mtx">
      <figure>
        <img
          src="https://assets.codepen.io/605876/mtx.jpeg"
          alt="skateboarder doing a trick mid air"
        />
      </figure>
      <figure aria-hidden="true">
        <img src="https://assets.codepen.io/605876/mtx-bg-removed.png" />
      </figure>
    </div>
  </section>
  <section class="last"><h2>xxx</h2></section>
</main>


2.2.核心样式


本 demo 实现中,使用了现代 CSS 嵌套,如果你对此不了解,可以参考小懒的文章[现代CSS:你真的还需要 CSS 预处理器吗?。


核心样式中首先对 section 元素应用了 grid 网格布局并设置高度为 100vh,这样可以保证每个 section 都在一个屏幕内。


动画的核心用到了 animation-timeline 和 animation-range。

body {
  background: hsl(0 0% 2%);
}

main {
  width: 1000px;
  margin: 0 auto;
  max-width: 100%;
  padding: 0 1rem;
  & section {
    display: grid;
    place-items: center;
    max-width: 100%;
    height: 100vh;

    & h2 {
      background: linear-gradient(hsl(0 0% 98%) 30%, hsl(0 0% 30%));
      color: transparent;
      background-clip: text;
      font-size: clamp(3rem, 6vw + 1rem, 12rem);
    }

    .pop-out-image {
      view-timeline-name: --popper;
      aspect-ratio: 1;
      position: relative;
      width: clamp(100px, 45vmin, 300px);
      outline: 4px dashed transparent;
      transition: transform 0.2s;
      border-radius: 1rem;
    }

    .skateboarder {
      --size: 170%;
      --y2: -40%;
    }

    .snowboarder {
      --size: 155%;
      --x1: -65%;
      --y2: -35%;
    }

    .mtb {
      --size: 185%;
      --y2: -45%;
    }

    .mtx {
      --size: 170%;
      --x1: -52%;
      --y2: -40%;
      --y1: -10%;
    }

    & figure {
      position: absolute;
      width: 100%;
      margin: 0;
      border-radius: 1rem;
      overflow: hidden;
      inset: 0;
      transition: transform 0.2s;

      & img {
        position: absolute;
        top: 0%;
        left: 50%;
        width: var(--size, 100%);
        aspect-ratio: 1;
        animation: slide-up linear both;
        animation-timeline: --popper;
        animation-range: entry 100% cover 50%;
        object-fit: cover;
        object-position: right;
        translate: var(--x1, -50%) var(--y1, 0);
      }

      &:last-of-type {
        --b: 2;
        overflow: visible;
        clip-path: inset(-200% 0 0 0);
      }
    }
  }
}

@keyframes slide-up {
  to {
    translate: var(--x1, -50%) var(--y2, -50%);
    filter: brightness(var(--b, 1));
  }
}


3.效果预览


11.gif

CSS

网站建设

小程序开发

阅读排行

  • 1. 几行代码就能实现Html大转盘抽奖

    大转盘抽奖是网络互动营销的一种常见形式,其通过简单易懂的界面设计,让用户在游戏中体验到乐趣,同时也能增加商家与用户之间的互动。本文将详细介绍如何使用HTML,CSS和JavaScript来实现大转盘抽奖的功能。

    查看详情
  • 2. 微信支付商户申请接入流程

    微信支付,是微信向有出售物品/提供服务需求的商家提供推广销售、支付收款、经营分析的整套解决方案,包括多种支付方式,如JSAPI支付、小程序支付、APP支付H5支付等支付方式接入。

    查看详情
  • 3. 浙江省同区域公司地址变更详细流程

    提前准备好所有需要的资料,包含:房屋租赁合同、房产证、营业执照正副本、代理人身份证正反面、承诺书(由于我们公司其中一区域已有注册另外一公司,所以必须需要承诺书)

    查看详情
  • 4. 阿里云域名ICP网络备案流程

    根据《互联网信息服务管理办法》以及《非经营性互联网信息服务备案管理办法》,国家对非经营性互联网信息服务实行备案制度,对经营性互联网信息服务实行许可制度。

    查看详情
  • 5. 微信小程序申请注册流程

    微信小程序注册流程与微信公众号较为相似,同时微信小程序支持通过已认证的微信公众号进行注册申请,无需进行单独认证即可使用,同一个已认证微信公众号可同时绑定注册多个小程序。

    查看详情