带有伪元素的 CSS 波纹效果导致回流

Posted

技术标签:

【中文标题】带有伪元素的 CSS 波纹效果导致回流【英文标题】:CSS Ripple effect with pseudo-element causing reflow 【发布时间】:2021-01-09 00:05:36 【问题描述】:

我正在尝试使用 styled-components 创建材质波纹效果(无法导入材质 web-components mixins)。我想坚持使用 after 元素作为前景效果,以保持可访问性树完好无损。

但是,最值得注意的是,在移动设备上,波纹过渡会导致按钮内容重排。这似乎是由于显示更改(从无到阻塞)而发生的,但我尝试了一些不共享此工件的替代方法,并且此副作用仍然存在。

这是我的代码(我正在使用一些道具来设置波纹,但如果您想重现,可以硬设置它们):[这是代码的过时版本]

感谢您的关注。

编辑:该错误仅在我向按钮添加悬停效果时发生,非常奇怪。下面是链接和代码示例(不幸的是,您必须设置一个反应存储库才能重现它)

https://github.com/Eduardogbg/ripple-hover-reflow-bug

import React,  useRef, useReducer  from 'react';
import ReactDOM from 'react-dom';
import styled from 'styled-components'

const ButtonBase = styled.button`
  cursor: pointer;

  width: 250px;
  height: 6vh;
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
  outline: none;
  position: relative;
  overflow: hidden;
  border-width: 0;

  background-color: cyan;

  :hover 
    filter: brightness(1.06);
  

  ::after 
    content: '';
    pointer-events: none;
    
    width: $( ripple ) => ripple.sizepx;
    height: $( ripple ) => ripple.sizepx;

    display: none;
    position: absolute;
    left: $( ripple ) => ripple.xpx;
    top: $( ripple ) => ripple.ypx;

    border-radius: 50%;
    background-color: $( ripple ) => ripple.color;

    opacity: 0;
    animation: ripple $( ripple ) => ripple.durationms;
  

  :focus:not(:active)::after 
    display: block;
  
  
  @keyframes ripple 
    from 
      opacity: 0.75;
      transform: scale(0);
    
    to 
      opacity: 0;
      transform: scale(2);
    
  
`

const rippleReducer = ref => (ripple, event) => 
  const  x, y, width, height  = ref.current.getBoundingClientRect()
  const size = Math.max(width, height) 
  
  return 
    ...ripple,
    size, 
    x: event.pageX - x - size / 2,
    y: event.pageY - y - size / 2
  


const DEFAULT_RIPPLE = 
  size: 0,
  x: 0,
  y: 0,
  color: 'white',
  duration: 850


const Button = props => 
  const ref = useRef(null)

  const [ripple, dispatch] = useReducer(
    rippleReducer(ref),
     ...DEFAULT_RIPPLE, ...props.ripple 
  )

  return (
    <ButtonBase
      ref=ref
      className=props.className
      ripple=ripple
      onClick=event => 
        event.persist()
        dispatch(event)
      
    >
      props.children
    </ButtonBase>
  )


ReactDOM.render(
  <div style=
    backgroundColor: 'red',
    width: '500px', height: '500px',
    display: 'grid',
    placeItems: 'center'
  >
    <Button>
      <span style= fontSize: '30px' >
        abacabadabaca
      </span>
    </Button>
  </div>,
  document.getElementById('root')
);

【问题讨论】:

请添加呈现的 html - 甚至如何开始使用您在此处给出的内容进行测试?请阅读how to create a minimal reproducible example。 好吧,我看不出 HTML 有什么帮助。我是这样做的,因此只需复制粘贴即可在带有样式组件的反应回购中进行复制。但是我可以删除 react 的东西并留下 CSS,然后将类应用于按钮。 我们不应该做任何工作来测试你的代码。呈现的 HTML 和 CSS 将允许我们测试您的按钮,然后为您提供帮助。 当然,我知道安装依赖项很不方便。我试图将它归结为 CSS,但它没有发生。这可能与我写的一些 JS 有关。我将发布一个最小的 repo 来重现它 我无法重现该错误,因为它似乎仅在我添加悬停效果时才会发生。没想到会这样。将更新问题 【参考方案1】:

这个问题似乎与几年前应该解决的这个铬错误有关:Image moves on hover when changing filter in chrome

设置transform: translate3d(0,0,0); 看起来像一个修复,虽然我的眼睛不是像素完美的。

【讨论】:

以上是关于带有伪元素的 CSS 波纹效果导致回流的主要内容,如果未能解决你的问题,请参考以下文章

带有CSS内容的div,伪元素后不可见

css 平行四边形 - 带有伪元素

css伪类 伪元素

伪元素和伪类的区别

伪类选择器与伪元素选择器的区别

伪类和伪元素