【问题标题】:Media Queries in Material-UI Using Styled-ComponentsMaterial-UI 中使用 Styled-Components 的媒体查询
【发布时间】:2020-05-12 06:46:36
【问题描述】:

Material UI 有一组不错的内置媒体查询:https://material-ui.com/customization/breakpoints/#css-media-queries

Material UI 还允许我们将 Styled-Components 与 Material UI 一起使用:https://material-ui.com/guides/interoperability/#styled-components

我想知道如何将两者结合在一起。也就是说,如何使用 Styled Components 和 Material-UI 的内置断点进行媒体查询?

谢谢。

更新:

这是我正在尝试做的一个示例:

import React, { useState } from 'react'
import styled from 'styled-components'


import {
  AppBar as MuiAppBar,
  Drawer as MuiDrawer,
  Toolbar,
} from '@material-ui/core'


const drawerWidth = 240

const AdminLayout = ({ children }) => {

  return (
    <BaseLayout>
      <AppBar position="static">
        <Toolbar>
          TOOLBAR
        </Toolbar>
      </AppBar>
      <Drawer>
        DRAWER
      </Drawer>
      {children}
    </BaseLayout>
  )
}

AdminLayout.propTypes = {
  children: PropTypes.node.isRequired,
}

export default AdminLayout

// ------- STYLES -------
const AppBar = styled(MuiAppBar)`
  /* Implement appBar styles from useStyles */
`

const Drawer = styled(MuiDrawer)`
  /* Implement drawer styles from useStyles */
`

// STYLES THAT I WANT TO CONVERT TO STYLED-COMPONENTS
const useStyles = makeStyles(theme => ({
  root: {
    display: 'flex',
  },
  drawer: {
    [theme.breakpoints.up('sm')]: {
      width: drawerWidth,
      flexShrink: 0,
    },
  },
  appBar: {
    [theme.breakpoints.up('sm')]: {
      width: `calc(100% - ${drawerWidth}px)`,
      marginLeft: drawerWidth,
    },
  },
  toolbar: theme.mixins.toolbar,
}))

【问题讨论】:

  • theme.breakpoints.down('sm') 只是一个字符串'(min-width:600px)',在样式组件中使用它
  • 这需要我对像素值进行硬编码——如果我想使用sm 变量怎么办?
  • 什么?使用 theme.breakpoints.down('sm') 时无需硬编码
  • 也许我没有关注。您介意向我展示一个如何在样式组件中使用theme.breakpoints.down('sm') 的示例吗?
  • 做一个小例子,说明你在没有样式组件的情况下尝试使用 MU 设置样式,我将向你展示一个示例

标签: reactjs material-ui styled-components


【解决方案1】:

breakpoints are provided 作为默认主题的一部分。

它们是常量,不会改变,因此您可以在组件或样式主题中使用它们:

import React from 'react';
import styled from 'styled-components';
import { makeStyles } from '@material-ui/core/styles';

const useStyles = makeStyles(theme => {
  console.log('md', theme.breakpoints.up('md'));
  return {};
});

const BP = {
  MD: `@media (min-width:960px) `,
};

const Container = styled.div`
  background-color: green;

  ${({ bp }) => bp} {
    background-color: red;
  }
`;

export default function StyledComponentsButton() {
  useStyles();
  return <Container bp={BP.MD}>Example</Container>;
}

【讨论】:

  • 感谢您的回答以及您为此付出的所有时间。不过,我很遗憾地说,但这不是我想要做的。对于初学者,const BP 硬编码md 断点的像素值。但我想使用theme.breakpoints 中的md 断点。其次,我不想依赖道具——我只想将媒体查询插入到样式化组件中。
  • 我的问题是如何在 styled-component 中访问 theme.breakpoint。
  • 如我多次提到的,使用风格化主题传递它
【解决方案2】:

下面是一个示例,展示了一种利用带有样式组件的 Material-UI 主题断点的方法。这会将 Material-UI 主题传递给 styled-components ThemeProvider,以使其可作为样式中的道具使用。该示例还使用 StylesProviderinjectFirst 属性,这样 Material-UI 样式将出现在 &lt;head&gt; 的开头而不是结尾,因此 styled-components 样式出现在 Material-UI 样式和因此,当特异性相同时获胜。

import React from "react";
import styled, { ThemeProvider as SCThemeProvider } from "styled-components";
import { useTheme, StylesProvider } from "@material-ui/core/styles";
import MuiAppBar from "@material-ui/core/AppBar";

const AppBar = styled(MuiAppBar)`
  background-color: red;
  ${props => props.theme.breakpoints.up("sm")} {
    background-color: orange;
  }
  ${props => props.theme.breakpoints.up("md")} {
    background-color: yellow;
    color: black;
  }
  ${props => props.theme.breakpoints.up("lg")} {
    background-color: green;
    color: white;
  }
`;
export default function App() {
  const muiTheme = useTheme();
  return (
    <StylesProvider injectFirst>
      <SCThemeProvider theme={muiTheme}>
        <AppBar>Sample AppBar</AppBar>
      </SCThemeProvider>
    </StylesProvider>
  );
}

相关文档:

【讨论】:

  • 这样的东西对我有用: const GridBox = styled(Box)` ${({theme}) => ` display: grid;网格模板行:自动; ${theme.breakpoints.up("sm")} { 网格模板列:5fr 3fr; }; } ;
  • 在我看来,这有太多的情感味道。我更喜欢 Mike Mathew 的不使用情感语法的解决方案。
【解决方案3】:

如果您使用"Style Objects" approach(即“JavaScript”)来设置样式组件,那么这是实现相同结果的方法。这是建立在前面提到的 Ryan Cogswell 之上的。

如果从另一个 CSS-in-JS 系统(如 Material-UI 的内置 JSS)切换,有些人可能更喜欢这个。此外,“样式对象”方法只需要您引入一次props,而不是在任何行上使用props 变量。有选择是好事。 ?

样式对象

const AppBar = styled(MuiAppBar)((props) => ({
  backgroundColor: red;

  [props.theme.breakpoints.up("sm")]: {
    backgroundColor: orange,
  },
  [props.theme.breakpoints.up("md")]: {
    backgroundColor: yellow,
    color: black,
  },
  [props.theme.breakpoints.up("lg")]: {
    backgroundColor: green,
    color: white,
  },
}));

样式对象,但更简洁

由于我们只需要使用 JavaScript 方法访问一次道具,并且我们只在这个样式区域中使用主题,因此我们可以从传入的 props 中解构 theme 以减少代码。

const AppBar = styled(MuiAppBar)(({ theme }) => ({
  backgroundColor: red;

  [theme.breakpoints.up("sm")]: {
    backgroundColor: orange,
  },
  [theme.breakpoints.up("md")]: {
    backgroundColor: yellow,
    color: black,
  },
  [theme.breakpoints.up("lg")]: {
    backgroundColor: green,
    color: white,
  },
}));

注意:如果您使用的是 TypeScript,并且已将您的样式化组件主题设置为与 Material-UI 主题相匹配,那么无论是 CSS 还是 JavaScript 方法,类型安全仍然可以正常工作。

【讨论】:

    猜你喜欢
    • 2021-08-18
    • 2020-11-16
    • 2020-06-28
    • 2021-05-30
    • 2020-12-20
    • 2020-05-14
    • 2019-08-02
    • 2018-09-14
    • 2019-06-27
    相关资源
    最近更新 更多