进入 DOM 的元素是否有流动的 CSS 高度 属性?使用 Semantic-UI-React Transitions 时会发生 Jank

Is there a fluid CSS height property for elements entering the DOM? Jank happens when using Semantic-UI-React Transitions

我不确定在这里问这个问题是否合适;我考虑了 软件推荐,但我想我应该先在这里试一试。

我正在创建一个 PWA,在每次迭代中,我真的很想专注于使它 look/feel 尽可能不那么卡顿和流畅。好吧,就像本机应用程序一样。

所以问题来了——我正在使用由 Semantic-UI-React 提供的转换(动画),虽然它在 space 上占据它的元素时效果很好,但我想知道是否有一种做法或模式可以处理相邻 DOM 元素与正在动画的元素的行为?

我在下面提供了一个 GIF 来说明我的意思。我想我可以将动画元素移出表单容器以防止卡顿,但我想知道是否有更优雅的模式或方法...

谢谢!

不幸的是,对此没有特别优雅的方法。

关于您的 post 标题中的问题,一种常见的方法是对新元素的 height 进行动画处理。如果你不知道元素的高度,不幸的是从 0px 动画到 auto does not yet work 但你可以通过动画从 max-height0px 来捏造它一个略大于您期望元素的最大大小的值。

但不要那样做。

它会导致浏览器在每个动画帧上布局页面,并且几乎肯定会在 lower-end 设备上卡顿。

相反,您最好设置动画 transform

最常见的方法是:

  1. 在添加新元素之前获取将要受影响的元素的原始位置(使用getBoundingClientRect()等)到 DOM (也许使用 getSnapshotBeforeUpdate 除非你使用钩子,在这种情况下你可以使用 useRef 来达到类似的效果)。

  2. 添加新元素后(您可能还通过使用 transform 和合适的 scale() 函数来制作动画),从哪里计算增量与过去相比,偏移元素现在是。

  3. 设置一个 transform 动画,从 delta 的负数到零(即 FLIP 方法)。例如。如果元素已向下移动 300px,则将 transformtranslateY(-300px) 动画化为 none.

当然,您需要对流程中受影响的所有元素执行此操作,因此将它们全部放在一个容器中并为其设置动画可能是最简单的方法。

关于第三点你有几个技术选择,none其中很棒:

  • CSS 转换。这些是最简单的,但您必须触发样式刷新才能使负增量起点保持不变。例如

    elem.style.transform = `translateY(-${offset}px)`;
    elem.style.transition = `transform .3s`;
    getComputedStyle(elem).transform; // Flush style
    elem.style.transform = `none`;
    
  • CSS 动画。使用 CSSOM 动态生成 @keyframes 规则很痛苦,但至少您不需要触发样式刷新(为了方便,您可以使用隐式 to-keyframe 设置动画) .

    @keyframes random-id { from: { translateY(-300px); } }
    
  • 网络动画。这大概是最well-suited.

    elem.animate({ transform: [ `translateY(-${offset}px)`, 'none' ] }, 300);
    
    // In future when browsers ship support for implicit to/from keyframes:
    elem.animate({ transform: `translateY(-${offset}px)`, offset: 0 }, 300);
    

    不幸的是,Safari 在技术预览中仅支持 Web 动画,因此 Safari 用户将获得 un-animated 版本,直到下一个 Safari 版本发布。在基于 Chromium 的 Edge 发布之前,Edge 用户还将获得 un-animated 版本。还有一个 polyfill,但目前没有积极维护。

如果您使用的是 React,Animating the Unanimatable 是一篇关于这一切的有用文章。

另一个棘手的部分是确保滚动不会跳跃,为此您可能需要查看滚动锚定。