Material UI中使用createStyles实现样式继承及菜单过渡动画失效问题排查
Hey there! Let's break down solutions for both your style redundancy and transition animation issues:
Instead of duplicating most properties across menuOpen and menuClose, you can define a base style object and extend it using the spread operator (...). This keeps your code clean and maintainable:
import { makeStyles, Theme } from '@material-ui/core/styles'; const useStyles = makeStyles((theme: Theme) => { // Define shared base menu styles once const baseMenuStyles = { zIndex: 1, width: 200, height: '100%', position: 'fixed', top: 48, transition: 'left 0.1s ease', // Add "ease" for smoother animation marginRight: theme.spacing(2), background: '#3f51b5', // Fix: Use valid `:first-child` pseudo-class instead of `first-element` '& > div:first-child': { marginTop: 100 } }; return { menuOpen: { ...baseMenuStyles, left: 0 // Only override the unique property }, menuClose: { ...baseMenuStyles, left: -200 // Only override the unique property } }; });
Looking at your generated CSS and setup, the most likely culprit is that your menu DOM element is being re-mounted (destroyed and recreated) when you toggle the menu, which skips the transition. Here's how to fix it:
Key Fix: Keep the Same DOM Element, Toggle Classes
Instead of rendering entirely different elements for open/closed states, use a single element and switch between classes. This preserves the DOM node and allows the transition to work:
import { useState } from 'react'; // Inside your component const [isMenuOpen, setIsMenuOpen] = useState(false); const classes = useStyles(); return ( {/* Use a single div, toggle the class based on state */} <div className={isMenuOpen ? classes.menuOpen : classes.menuClose}> {/* Your menu content here */} </div> );
Optional: Alternative Structure with Base + State Classes
If you prefer separating base styles from state-specific styles, you can also do this (just ensure the state class overrides the base left value):
const useStyles = makeStyles((theme: Theme) => ({ menuBase: { zIndex: 1, width: 200, height: '100%', position: 'fixed', top: 48, transition: 'left 0.1s ease', marginRight: theme.spacing(2), background: '#3f51b5', '& > div:first-child': { marginTop: 100 } }, menuOpen: { left: 0 }, menuClose: { left: -200 } }));
Then in your component:
<div className={`${classes.menuBase} ${isMenuOpen ? classes.menuOpen : classes.menuClose}`}> {/* Menu content */} </div>
Additional Checks
- Double-check that no parent elements have
overflow: hiddenorposition: staticthat might interfere with the fixed positioning. - Remove redundant
transitionproperties from state-specific classes (you only need it in the base style).
内容的提问来源于stack exchange,提问作者aarona

