跳转到内容

样式库的互通性

当您可以使用 Materal-UI 提供的基于 JSS 的样式解决方案来装饰应用程序,也可以用您已经熟知和喜欢的工具(从纯 CSS 到 styled-components)。

本指南旨在归档当前比较流行的一些替代方案,但是您会发现在这里运用的法则,也可以在其他库里适用。 我们为以下的样式方案提供了一些示例:

纯 CSS

没有什么特别花哨的,只是纯 CSS。

编辑按钮

PlainCssButton.css

.button {
  background-color: #6772e5;
  color: #fff;
  box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
  padding: 7px 14px;
}
.button:hover {
  background-color: #5469d4;
}

PlainCssButton.js

import React from 'react';
import Button from '@material-ui/core/Button';
import './PlainCssButton.css';

export default function PlainCssButton() {
  return (
    <div>
      <Button>默认的按钮</Button>
      <Button className="button">自定义按钮</Button>
    </div>
  );
}

控制的优先权 ⚠️

请注意: JSS 在 <head> 底部注入其样式表。 如果您不想使用 !important 来标记样式属性的话,则需要更改 CSS 的注入顺序,如下所示:

import { StylesProvider } from '@material-ui/core/styles';

<StylesProvider injectFirst>
  {/* 你的组件树。
      现在,您可以覆盖 Material-UI 的样式。 */}
</StylesProvider>

更深层的元素

如果您尝试赋予 Drawer(抽屉)组件以永久的变体的样式,这很可能会影响到抽屉组件的子纸张元素。 但是,纸张元素不是抽屉组件的根元素,因此上面的自定义 styled-components 将不起作用。 您则需要使用 Material-UI 的 classes API 来达到目的。

以下示例除了自定义按钮本身的样式外,还会覆盖 Button标签(label)的样式。

PlainCssButtonDeep.css

.button {
  background-color: #6772e5;
  box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
  padding: 7px 14px;
}
.button:hover {
  background-color: #5469d4;
}
.button-label {
  color: #fff;
}

PlainCssButtonDeep.js

import React from 'react';
import Button from '@material-ui/core/Button';
import './PlainCssButtonDeep.css';

export default function PlainCssButtonDeep() {
  return (
    <div>
      <Button>默认的</Button>
      <Button classes={{ root: 'button', label: 'button-label' }}>
        自定义的
      </Button>
    </div>
  );
}

全局 CSS

明确向提组件提供类名是不是太大费周章了? 您可以定位到由 Material-UI 生成的类名

编辑按钮

GlobalCssButton.css

.MuiButton-root {
  background-color: #6772e5;
  box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
  padding: 7px 14px;
}
.MuiButton-root:hover {
  background-color: #5469d4;
}
.MuiButton-label {
  color: #fff;
}

GlobalCssButton.js

import React from 'react';
import Button from '@material-ui/core/Button';
import './GlobalCssButton.css';

export default function GlobalCssButton() {
  return <Button>自定义的</Button>;
}

控制的优先权 ⚠️

请注意: JSS 在 <head> 底部注入其样式表。 如果您不想使用 !important 来标记样式属性的话,则需要更改 CSS 的注入顺序,如下所示:

import { StylesProvider } from '@material-ui/core/styles';

<StylesProvider injectFirst>
  {/* 你的组件树。
      现在,您可以覆盖 Material-UI 的样式。 */}
</StylesProvider>

Styled Components

stars npm

styled() 方法完美适用于我们所有的组件。

编辑按钮

import React from 'react';
import styled from 'styled-components';
import Button from '@material-ui/core/Button';

const StyledButton = styled(Button)`
  background-color: #6772e5;
  color: #fff;
  box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
  padding: 7px 14px;
  &:hover {
    background-color: #5469d4;
  }
`;

export default function StyledComponents() {
  return (
    <div>
      <Button>默认的按钮</Button>
      <StyledButton>自定义按钮</StyledButton>
    </div>
  );
}

控制的优先权 ⚠️

请注意: styled-components 和 JSS 都在 <head> 的底部注入其样式表。 若想要 styled-components 的样式在最后加载,我们推荐的最佳方法是更改 CSS 的注入顺序,如下演示:

import { StylesProvider } from '@material-ui/core/styles';

<StylesProvider injectFirst>
  {/* 你的组件树。
      Now, you can override Material-UI's styles. */}
</StylesProvider>
      现在,您可以覆盖 Material-UI 的样式。 */}
</StylesProvider>

另外一个在 styled-components 中使用 && 字符的方案则是通过重复类名来 增强其优先级。 您应该避免使用 !imporant

更深层的元素

如果您尝试赋予Drawer(抽屉)组件以永久的变体的样式,您很可能会需要涉及抽屉组件的子纸张元素。 但是,这不是抽屉组件的根元素,因此上面的样式组件自定义将不起作用。 您则需要使用 Material-UI 的 API 中的 classes 来达到目的。

以下示例除了按钮本身的自定义样式外,还会覆盖 labelButton 样式。 通过“消费”不应该传递到底层的那些属性,它还解决了 这个 styled-components 问题

<NoSsr>
  <Button>Default</Button>
  <StyledButton>Customized</StyledButton>
</NoSsr>
import React from 'react';
import styled from 'styled-components';
import Button from '@material-ui/core/Button';

const StyledButton = styled(Button)`
  background-color: #6772e5;
  box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
  padding: 7px 14px;
  &:hover {
    background-color: #5469d4;
  }
  & .MuiButton-label {
    color: #fff;
  }
`;

export default function StyledComponentsDeep() {
  return (
    <div>
      <Button>默认的按钮</Button>
      <StyledButton>自定义按钮</StyledButton>
    </div>
  );
}

以上的例子依赖于 默认的的值,但是您也可以提供自定义的类名:.label

import React from 'react';
import styled from 'styled-components';
import Button from '@material-ui/core/Button';

const StyledButton = styled(({ color, ...other }) => (
  <Button classes={{ label: 'label' }} {...other} />
))`
  background-color: #6772e5;
  box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
  padding: 7px 14px;
  &:hover {
    background-color: #5469d4;
  }
  & .label {
    color: #fff;
  }
`;

export default function StyledComponentsDeep() {
  return (
    <div>
      <Button>默认的按钮</Button>
      <StyledButton>自定义按钮</StyledButton>
    </div>
  );
}

主题

Material-UI 有着一个丰富的主题架构,而您可以利用它来做一些颜色的处理,过渡动画,媒体查询等等。

我们鼓励在 Materal-UI 和您的样式之间分享相同的主题对象(theme object)。

const StyledButton = styled(Button)`
  ${({ theme }) => `
  background-color: ${theme.palette.primary.main};
  color: #fff;
  box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
  padding: 4px 10px;
  font-size: 13px;
  &:hover {
    background-color: ${darken(theme.palette.primary.main, 0.2)};
  }
  ${theme.breakpoints.up('sm')} {
    font-size: 14px;
    padding: 7px 14px;
  }
  `}
`;
<NoSsr>
  <MuiThemeProvider theme={customTheme}>
    <ThemeProvider theme={customTheme}>
      <Button>Default</Button>
      <StyledButton>Customized</StyledButton>
    </ThemeProvider>
  </MuiThemeProvider>
</NoSsr>

Portals(传送门组件)

传送门组件提供了一种一流的方法,它将子元素渲染在其父组件的 DOM 层次结构之外的 DOM 节点中。 当您使用这样的 styled-components 规范其 CSS 的方式时,可能会遇到一些无法附着样式的问题。

例如,若您尝试用 MenuProps 属性来样式化 Select 组件的 Menu,您将需要将 className 属性传递到它的 DOM 层次结构之外渲染的元素当中。 下面的示例演示了一个变通办法:

import React from 'react';
import styled from 'styled-components';
import Menu from '@material-ui/core/Menu';
import MenuItem from '@material-ui/core/MenuItem';

const StyledMenu = styled(({ className, ...props }) => (
  <Menu {...props} classes={{ paper: className }} />
))`
  box-shadow: none;
  border: 1px solid #d3d4d5;

  li {
    padding-top: 8px;
    padding-bottom: 8px;
  }
`;

CSS Modules

stars

鉴于它全权依赖于大家使用的打包方案,我们很难得知 此种样式方案 的市场占有率。

编辑按钮

CssModulesButton.css

.button {
  background-color: #6772e5;
  color: #fff;
  box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
  padding: 7px 14px;
}
.button:hover {
  background-color: #5469d4;
}

CssModulesButton.js

import React from 'react';
// webpack,parcel 或者其他工具会将 CSS 注入到此页面
import styles from './CssModulesButton.css';
import Button from '@material-ui/core/Button';

export default function CssModulesButton() {
  return (
    <div>
      <Button>默认的按钮</Button>
      <Button className={styles.button}>自定义按钮</Button>
    </div>
  );
}

Controlling priority ⚠️

请注意: JSS 在 <head> 底部注入其样式表。 如果您不想使用 !important 来标记样式属性的话,则需要更改 CSS 的注入顺序,如下所示:

import { StylesProvider } from '@material-ui/core/styles';

<StylesProvider injectFirst>
  {/* 你的组件树。
      Now, you can override Material-UI's styles. */}
</StylesProvider>
      现在,您可以覆盖 Material-UI 的样式。 */}
</StylesProvider>

更深层的元素

如果您尝试赋予Drawer(抽屉)组件以永久的变体的样式,您很可能会需要涉及抽屉组件的子纸张元素。 但是,这不是抽屉组件的根元素,因此上面的样式组件自定义将不起作用。 您则需要使用 Material-UI 的 API 中的 classes 来达到目的。

以下示例除了按钮本身的自定义样式外,还会覆盖 labelButton 样式。

CssModulesButtonDeep.css

.root {
  background-color: #6772e5;
  box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
  padding: 7px 14px;
}
.root:hover {
  background-color: #5469d4;
}
.label {
  color: #fff;
}

CssModulesButtonDeep.js

import React from 'react';
// webpack,parcel 或者其他工具会将 CSS 注入到此页面
import styles from './CssModulesButtonDeep.css';
import Button from '@material-ui/core/Button';

export default function CssModulesButtonDeep() {
  return (
    <div>
      <Button>默认的按钮</Button>
      <Button classes={styles}>自定义按钮</Button>
    </div>
  );
}

Emotion

stars npm

css 属性

Emotion的 css() 方法与 Material-UI 无缝协作。

编辑按钮

/** @jsx jsx */
import { jsx, css } from '@emotion/core';
import Button from '@material-ui/core/Button';

export default function EmotionCSS() {
  return (
    <div>
      <Button>默认的按钮</Button>
      <Button
        css={css`
          background-color: #6772e5;
          color: #fff;
          box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
          padding: 7px 14px;
          &:hover {
            background-color: #5469d4;
          }
        `}
      >
        自定义按钮
      </Button>
    </div>
  );
}

控制的优先权 ⚠️

请注意: JSS 在 <head> 底部注入其样式表。 如果您不想使用 !important 来标记样式属性的话,则需要更改 CSS 的注入顺序,如下所示:

import { StylesProvider } from '@material-ui/core/styles';

<StylesProvider injectFirst>
  {/* 你的组件树。
      现在,您可以覆盖 Material-UI 的样式。 */}
</StylesProvider>

主题

Material-UI 有着一个丰富的主题架构,而您可以利用它来做一些颜色的处理,过渡动画,媒体查询等等。

我们鼓励在 Materal-UI 和您的样式之间分享相同的主题对象(theme object)。

<Button
  css={theme => css`
    background-color: ${theme.palette.primary.main};
    color: #fff;
    box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
    padding: 4px 10px;
    font-size: 13px;
    &:hover {
      background-color: ${darken(theme.palette.primary.main, 0.2)};
    }
    ${theme.breakpoints.up('sm')} {
      font-size: 14px;
      padding: 7px 14px;
    }
  `}
>
  自定义按钮
</Button>

styled() API

它会像 styled components 一样起作用。 您可以 使用相同的指南