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。
我正在尝试使用样式组件创建 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。