【问题标题】:CSS Ripple effect with pseudo-element causing reflow带有伪元素的 CSS 波纹效果导致回流
【发布时间】: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.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')
);

【问题讨论】:

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

标签: css reactjs sass styled-components reflow


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 2020-12-27
    • 1970-01-01
    • 1970-01-01
    • 2018-06-23
    • 1970-01-01
    • 1970-01-01
    • 2014-10-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多