CSS 伪元素导致回流的涟漪效应

CSS Ripple effect with pseudo-element causing reflow

我正在尝试使用样式组件创建 material 涟漪效果(无法导入 material 网络组件混入)。我想坚持使用 after 元素作为前景效果,以保持可访问性树完好无损。

但是,最明显的是在移动设备上,波纹过渡导致按钮内容回流。它似乎是由于显示更改(从 none 到块)而发生的,但我尝试了一些不共享此工件的替代方案,并且此副作用仍然存在。

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

感谢关注

编辑:只有在我为按钮添加悬停效果时才会出现此错误,非常奇怪。下面是 link 和代码示例(不幸的是,您必须设置一个 React 存储库才能重现它)

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.size}px;
    height: ${({ ripple }) => ripple.size}px;

    display: none;
    position: absolute;
    left: ${({ ripple }) => ripple.x}px;
    top: ${({ ripple }) => ripple.y}px;

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

    opacity: 0;
    animation: ripple ${({ ripple }) => ripple.duration}ms;
  }

  :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')
);

这个问题似乎与几年前应该解决的这个铬错误有关:

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