如何在MUI v5(Emotion)中实现CSS keyframes适配Box/Typography组件
MUI v5 纵向轮播旋转文字实现方案
MUI v5 默认使用@emotion作为样式引擎,你原有keyframes的实现逻辑可以直接复用,只需要修正语法问题、替换原生标签为MUI组件、补全必要的容器样式即可。
原有代码问题修正
你之前编写的keyframes存在CSS语法错误:百分比选择器后多写了多余的冒号,会导致动画完全失效,修正后的keyframes语法如下:
const spin = keyframes` 0%, 20% { transform: translateY(0); } 25%, 45% { transform: translateY(-208px); } 50%, 70% { transform: translateY(-416px); } 75%, 95% { transform: translateY(-624px); } 100% { transform: translateY(-832px); } `;
注意:当前位移值基于单个文字项高度208px计算,后续如果调整文字大小、行高,需要同步修改位移值,保证每次动画刚好位移一个完整文字项的高度。
另外你原有代码缺少外层容器的固定高度和溢出隐藏样式,会导致动画过程中所有文字项全部外露,无法实现轮播切换的效果,这部分需要补全。
替换为MUI组件的两种实现方式
方式1:沿用@emotion 原生写法(改动最小)
MUI的Box组件原生支持Emotion的css属性,文字项直接替换为Typography组件即可:
import { Box, Typography } from '@mui/material'; import { css, keyframes } from '@emotion/react'; export const Home = () => { const spin = keyframes` 0%, 20% { transform: translateY(0); } 25%, 45% { transform: translateY(-208px); } 50%, 70% { transform: translateY(-416px); } 75%, 95% { transform: translateY(-624px); } 100% { transform: translateY(-832px); } `; const animatedContainer = css` height: 208px; overflow: hidden; animation: ${spin} 7s ease-in-out infinite; `; const textItem = css` height: 208px; display: flex; align-items: center; `; return ( <> {/* 其他页面内容 */} <Box css={animatedContainer}> <Typography css={textItem} variant="h2">restaurants</Typography> <Typography css={textItem} variant="h2">museums</Typography> <Typography css={textItem} variant="h2">landmarks</Typography> <Typography css={textItem} variant="h2">parks</Typography> </Box> {/* 其他页面内容 */} </> ) }
方式2:使用MUI sx属性写法(符合MUI开发规范)
MUI本身重导出了keyframes方法,可以直接从@mui/material引入,不需要单独依赖@emotion的导出,所有样式写在sx属性中,可以直接调用MUI主题的设计token:
import { Box, Typography, keyframes } from '@mui/material'; export const Home = () => { const spin = keyframes` 0%, 20% { transform: translateY(0); } 25%, 45% { transform: translateY(-208px); } 50%, 70% { transform: translateY(-416px); } 75%, 95% { transform: translateY(-624px); } 100% { transform: translateY(-832px); } `; return ( <> {/* 其他页面内容 */} <Box sx={{ height: '208px', overflow: 'hidden', animation: `${spin} 7s ease-in-out infinite` }} > <Typography variant="h2" sx={{ height: '208px', display: 'flex', alignItems: 'center' }}> restaurants </Typography> <Typography variant="h2" sx={{ height: '208px', display: 'flex', alignItems: 'center' }}> museums </Typography> <Typography variant="h2" sx={{ height: '208px', display: 'flex', alignItems: 'center' }}> landmarks </Typography> <Typography variant="h2" sx={{ height: '208px', display: 'flex', alignItems: 'center' }}> parks </Typography> </Box> {/* 其他页面内容 */} </> ) }
可选优化项
- 若需要适配响应式字号,可通过ref获取单个文字项的实际渲染高度,动态计算keyframes的位移值,避免硬编码px导致的错位
- 调整动画总时长即可修改切换速度,当前配置下每个词汇停留时长占总时长的20%,过渡动画占5%
- 100%关键帧设置位移为-832px(4个文字项的总高度)是为了实现无缝循环,动画重置到0%位置时视觉上不会出现跳变
内容的提问来源于stack exchange,提问作者benwl
相关产品推荐
相关产品推荐

