【问题标题】:How do you change a style of a child when hovering over a parent using MUI styles?当使用 MUI 样式将鼠标悬停在父级上时,如何更改子级的样式?
【发布时间】:2020-03-29 10:04:58
【问题描述】:

我在反应中使用 MUI。假设我有这些样式的组件:

const useStyles = makeStyles(theme => ({
  outerDiv: {
    backgroundColor: theme.palette.grey[200],
    padding: theme.spacing(4),
    '&:hover': {
      cursor: 'pointer',
      backgroundColor: theme.palette.grey[100]
   }
  },
  addIcon: (props: { dragActive: boolean }) => ({
    height: 50,
    width: 50,
    color: theme.palette.grey[400],
    marginBottom: theme.spacing(2)
  })
}));

function App() {
  const classes = useStyles();
  return (
    <Grid container>
      <Grid item className={classes.outerDiv}>
        <AddIcon className={classes.addIcon} />
      </Grid>
    </Grid>
  );
}

当悬停在outerDiv 上时,我想使用上述样式更改addIcon 的样式。

Here 是我的例子。

【问题讨论】:

    标签: reactjs css-selectors material-ui jss onhover


    【解决方案1】:

    这表示当前选择器是父组件:

    '&': { /* styles */ }
    

    这表示父组件处于悬停状态:

    '&:hover': { /* styles */ }
    

    这表示父组件中处于悬停状态的子组件:

    '&:hover .child': { /* styles */ }
    

    如果您使用的是伪类,也可以省略 & 符号 &amp;

    ':hover .child': { /* styles */ }
    

    使用sxprop的完整代码(styled()中也可以使用相同的样式对象):

    <Box
      sx={{
        width: 300,
        height: 300,
        backgroundColor: "darkblue",
        ":hover .child": {
          backgroundColor: "orange"
        }
      }}
    >
      <Box className="child" sx={{ width: 200, height: 200 }} />
    </Box>
    

    【讨论】:

      【解决方案2】:

      下面是 v4 的正确语法示例("&amp; $addIcon" 嵌套在 &amp;:hover 中)。再往下是一些 v5 示例。

      import * as React from "react";
      import { render } from "react-dom";
      import { Grid, makeStyles } from "@material-ui/core";
      import AddIcon from "@material-ui/icons/Add";
      
      const useStyles = makeStyles(theme => ({
        outerDiv: {
          backgroundColor: theme.palette.grey[200],
          padding: theme.spacing(4),
          '&:hover': {
            cursor: 'pointer',
            backgroundColor: theme.palette.grey[100],
            "& $addIcon": {
              color: "purple"
            }
         }
        },
        addIcon: (props: { dragActive: boolean }) => ({
          height: 50,
          width: 50,
          color: theme.palette.grey[400],
          marginBottom: theme.spacing(2)
        })
      }));
      
      function App() {
        const classes = useStyles();
        return (
          <Grid container>
            <Grid item className={classes.outerDiv}>
              <AddIcon className={classes.addIcon} />
            </Grid>
          </Grid>
        );
      }
      
      const rootElement = document.getElementById("root");
      render(<App />, rootElement);
      

      相关文档和答案:


      对于已经开始使用 Material-UI v5 的用户,下面的示例实现了相同的样式,但利用了新的 sx 属性。

      import Grid from "@mui/material/Grid";
      import { useTheme } from "@mui/material/styles";
      import AddIcon from "@mui/icons-material/Add";
      
      export default function App() {
        const theme = useTheme();
        return (
          <Grid container>
            <Grid
              item
              sx={{
                p: 4,
                backgroundColor: theme.palette.grey[200],
                "&:hover": {
                  backgroundColor: theme.palette.grey[100],
                  cursor: "pointer",
                  "& .addIcon": {
                    color: "purple"
                  }
                }
              }}
            >
              <AddIcon
                className="addIcon"
                sx={{
                  height: "50px",
                  width: "50px",
                  color: theme.palette.grey[400],
                  mb: 2
                }}
              />
            </Grid>
          </Grid>
        );
      }
      


      这是另一个 v5 示例,但使用 Emotion 的 styled 函数而不是 Material-UI 的 sx 属性:

      import Grid from "@mui/material/Grid";
      import { createTheme, ThemeProvider } from "@mui/material/styles";
      import AddIcon from "@mui/icons-material/Add";
      import styled from "@emotion/styled/macro";
      
      const StyledAddIcon = styled(AddIcon)(({ theme }) => ({
        height: "50px",
        width: "50px",
        color: theme.palette.grey[400],
        marginBottom: theme.spacing(2)
      }));
      const StyledGrid = styled(Grid)(({ theme }) => ({
        padding: theme.spacing(4),
        backgroundColor: theme.palette.grey[200],
        "&:hover": {
          backgroundColor: theme.palette.grey[100],
          cursor: "pointer",
          [`${StyledAddIcon}`]: {
            color: "purple"
          }
        }
      }));
      const theme = createTheme();
      export default function App() {
        return (
          <ThemeProvider theme={theme}>
            <Grid container>
              <StyledGrid item>
                <StyledAddIcon />
              </StyledGrid>
            </Grid>
          </ThemeProvider>
        );
      }
      


      还有一个使用 Emotion 的 css prop 的 v5 示例:

      /** @jsxImportSource @emotion/react */
      import Grid from "@mui/material/Grid";
      import { createTheme, ThemeProvider } from "@mui/material/styles";
      import AddIcon from "@mui/icons-material/Add";
      
      const theme = createTheme();
      export default function App() {
        return (
          <ThemeProvider theme={theme}>
            <Grid container>
              <Grid
                item
                css={(theme) => ({
                  padding: theme.spacing(4),
                  backgroundColor: theme.palette.grey[200],
                  "&:hover": {
                    backgroundColor: theme.palette.grey[100],
                    cursor: "pointer",
                    "& .addIcon": {
                      color: "purple"
                    }
                  }
                })}
              >
                <AddIcon
                  className="addIcon"
                  css={(theme) => ({
                    height: "50px",
                    width: "50px",
                    color: theme.palette.grey[400],
                    marginBottom: theme.spacing(2)
                  })}
                />
              </Grid>
            </Grid>
          </ThemeProvider>
        );
      }
      

      【讨论】:

      • 感谢您提供的文档链接,帮助很大!
      • 并且还可以在子css定义中引用父级:'$outerDiv:hover &amp;': { color: 'purple' },
      • 完美!非常感谢!!
      【解决方案3】:

      可能很明显,但只是为了补充上面的答案:如果您引用了一个单独的类名,请不要忘记您还需要在 makeStyles 钩子中创建它,否则它将不起作用。例如:

      const useStyles = makeStyles({
        parent: {
          color: "red",
          "&:hover": {
            "& $child": {
              color: "blue" // will only apply if the class below is declared (can be declared empty)
            }
          }
        },
        // child: {} // THIS must be created / uncommented in order for the code above to work; assigning the className to the component alone won't work.
      })
      
      const Example = () => {
        const classes = useStyles()
        return (
          <Box className={classes.parent}>
            <Box className={classes.child}>
              I am red unless you create the child class in the hook
            </Box>
          </Box>
        )
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-28
        • 2014-06-30
        • 1970-01-01
        • 2015-05-31
        相关资源
        最近更新 更多