样式库的互通性
虽然你可以使用 Material-UI 提供的基于 emotion 的样式解决方案来自定义你的应用程序,但你也可以使用你已知和喜欢的方案(从普通的 CSS 到 styled-components)。
本指南旨在归档当前比较流行的一些替代方案,但是您会发现在这里运用的法则,也可以在其他库里适用。 我们为以下的样式方案提供了一些示例:
纯 CSS
没有什么特别花哨的,只是纯 CSS。
PlainCssSlider.css
.slider {
color: #20b2aa;
}
.slider:hover {
color: #2e8b57;
}
PlainCssSlider.js
import * as React from 'react';
import Slider from '@material-ui/core/Slider';
import './PlainCssSlider.css';
export default function PlainCssSlider() {
return (
<div>
<Slider defaultValue={30} />
<Slider defaultValue={30} className="slider" />
</div>
);
}
CSS 注入顺序⚠️
注意: 大多数的 CSS-in-JS 解决方案是在 HTML <head>
的底部注入它们的样式,这会导致你的自定义样式被 Material-UI 的样式规则所覆盖。 如果你有移除 !important 的需求,那么就需要改变 CSS 注入顺序。 Here's a demo of how it can be done in Material-UI:
import * as React from 'react';
import { StylesProvider } from '@material-ui/core';
export default function GlobalCssPriority() {
return (
<StylesProvider injectFirst>
{/* Your component tree. 现在你可以覆盖 Material-UI 的样式。 */}
</StylesProvider>
);
}
Note: If you are using emotion and have a custom cache in your app, that one will override the one coming from Material-UI. In order for the injection order to still be correct, you need to add the prepend option. 下面是一个示例: In order for the injection order to still be correct, you need to add the prepend option. 下面是一个示例:
import * as React from 'react';
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
const cache = createCache({
key: 'css',
prepend: true,
});
export default function PlainCssPriority() {
return (
<CacheProvider value={cache}>
{/* Your component tree. 现在你可以覆盖 Material-UI 的样式。 */}
</CacheProvider>
);
}
Note: If you are using styled-components and have StyleSheetManager
with a custom target
, make sure that the target is the first element in the HTML <head>
. If you are curious to see how it can be done, you can take a look on the StylesProvider
implementation in the @material-ui/styled-engine-sc
package. If you are curious to see how it can be done, you can take a look on the StylesProvider
implementation in the @material-ui/styled-engine-sc
package.
更深层的元素
如果你试图自定义滑块的样式,那么很可能会影响到滑块的一些子元素,例如滚动条的箭头(thumb)。 在 Material-UI 中,所有的子元素都增加了两层的特定类:.parent .child {}
。 所以在编写覆盖样式的时候,你也需要这样做。
以下示例除了覆盖滑块本身的自定义样式外,还覆盖了滑块的 thumb
样式。
PlainCssSliderDeep1.css
.slider {
color: #20b2aa;
}
.slider:hover {
color: #2e8b57;
}
.slider .MuiSlider-thumb {
border-radius: 1px;
}
PlainCssSliderDeep1.js
import * as React from 'react';
import Slider from '@material-ui/core/Slider';
import './PlainCssSliderDeep1.css';
export default function PlainCssSliderDeep1() {
return (
<div>
<Slider defaultValue={30} />
<Slider defaultValue={30} className="slider" />
</div>
);
}
上面的演示依赖于 默认的className
值,但是你也可以使用 componentsProps
API 来提供你自己的类名。
PlainCssSliderDeep2.css
.slider {
color: #20b2aa;
}
.slider:hover {
color: #2e8b57;
}
.slider .thumb {
border-radius: 1px;
}
PlainCssSliderDeep2.js
import * as React from 'react';
import Slider from '@material-ui/core/Slider';
import './PlainCssSliderDeep2.css';
export default function PlainCssSliderDeep2() {
return (
<div>
<Slider defaultValue={30} />
<Slider
defaultValue={30}
className="slider"
componentsProps={{ thumb: { className: 'thumb' } }}
/>
</div>
);
}
全局 CSS
明确向提组件提供类名是不是太大费周章了? 您可以定位到由 Material-UI 生成的类名。
GlobalCssSlider.css
.MuiSlider-root {
color: #20b2aa;
}
.MuiSlider-root:hover {
color: #2e8b57;
}
GlobalCssSlider.js
import * as React from 'react';
import Slider from '@material-ui/core/Slider';
import './GlobalCssSlider.css';
export default function GlobalCssSlider() {
return <Slider defaultValue={30} />;
}
CSS 注入顺序⚠️
注意: 大多数的 CSS-in-JS 解决方案是在 HTML <head>
的底部注入它们的样式,这会导致你的自定义样式被 Material-UI 的样式规则所覆盖。 如果你有移除 !important 的需求,那么就需要改变 CSS 注入顺序。 Here's a demo of how it can be done in Material-UI:
import * as React from 'react';
import { StylesProvider } from '@material-ui/core';
export default function GlobalCssPriority() {
return (
<StylesProvider injectFirst>
{/* Your component tree. 现在你可以覆盖 Material-UI 的样式。 */}
</StylesProvider>
);
}
Note: If you are using emotion and have a custom cache in your app, that one will override the one coming from Material-UI. In order for the injection order to still be correct, you need to add the prepend option. 下面是一个示例: In order for the injection order to still be correct, you need to add the prepend option. 下面是一个示例:
import * as React from 'react';
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
const cache = createCache({
key: 'css',
prepend: true,
});
export default function GlobalCssPriority() {
return (
<CacheProvider value={cache}>
{/* 这里编写你的组件树。 现在你可以覆盖 Material-UI 的样式。 */}
</CacheProvider>
);
}
Note: If you are using styled-components and have StyleSheetManager
with a custom target
, make sure that the target is the first element in the HTML <head>
. If you are curious to see how it can be done, you can take a look on the StylesProvider
implementation in the @material-ui/styled-engine-sc
package. If you are curious to see how it can be done, you can take a look on the StylesProvider
implementation in the @material-ui/styled-engine-sc
package.
更深层的元素
如果你试图自定义滑块的样式,那么很可能会影响到滑块的一些子元素,例如滚动条的箭头(thumb)。 在 Material-UI 中,所有的子元素都增加了两层的特定类:.parent .child {}
。 所以在编写覆盖样式的时候,你也需要这样做。
以下示例除了覆盖滑块本身的自定义样式外,还覆盖了滑块的 thumb
样式。
GlobalCssSliderDeep.css
.MuiSlider-root {
color: #20b2aa;
}
.MuiSlider-root:hover {
color: #2e8b57;
}
.MuiSlider-root .MuiSlider-thumb {
border-radius: 1px;
}
GlobalCssSliderDeep.js
import * as React from 'react';
import Slider from '@material-ui/core/Slider';
import './GlobalCssSliderDeep.css';
export default function GlobalCssSliderDeep() {
return <Slider defaultValue={30} />;
}
Styled Components
改变默认的样式引擎
默认情况下,Material-UI 组件使用 emotion 来作为它们的样式引擎。 但是,如果你想使用 styled-components
的话,那么你可以参考这个 示例项目 来配置你的应用程序。 按照这种方法来配置的话,则可以减少捆绑包的大小,并且无需配置 CSS 注入顺序。
在正确配置了样式引擎之后,你可以使用 @material-ui/core/styles
中的 experimentalStyled()
工具集来直接访问主题。
import * as React from 'react';
import Slider from '@material-ui/core/Slider';
import { experimentalStyled as styled } from '@material-ui/core/styles';
const CustomizedSlider = styled(Slider)`
color: #20b2aa;
:hover {
color: #2e8b57;
}
`;
export default function StyledComponents() {
return <CustomizedSlider defaultValue={30} />;
}
更深层的元素
如果你试图自定义滑块的样式,那么很可能会影响到滑块的一些子元素,例如滚动条的箭头(thumb)。 在 Material-UI 中,所有的子元素都增加了两层的特定类:.parent .child {}
。 所以在编写覆盖样式的时候,你也需要这样做。
以下示例除了覆盖滑块本身的自定义样式外,还覆盖了滑块的 thumb
样式。
import * as React from 'react';
import Slider from '@material-ui/core/Slider';
import { experimentalStyled as styled } from '@material-ui/core/styles';
const CustomizedSlider = styled(Slider)`
color: #20b2aa;
:hover {
color: #2e8b57;
}
& .MuiSlider-thumb {
border-radius: 1px;
}
`;
export default function StyledComponentsDeep1() {
return (
<div>
<Slider defaultValue={30} />
<CustomizedSlider defaultValue={30} />
</div>
);
}
上面的演示依赖于 默认的className
值,但是你也可以使用 componentsProps
API 来提供你自己的类名。
import * as React from 'react';
import { experimentalStyled as styled } from '@material-ui/core/styles';
import Slider from '@material-ui/core/Slider';
const CustomizedSlider = styled((props) => (
<Slider componentsProps={{ thumb: { className: 'thumb' } }} {...props} />
))`
color: #20b2aa;
:hover {
color: #2e8b57;
}
& .thumb {
border-radius: 1px;
}
`;
export default function StyledComponentsDeep2() {
return (
<div>
<Slider defaultValue={30} />
<CustomizedSlider defaultValue={30} />
</div>
);
}
主题
通过使用 Material-UI 主题提供者(theme provider),该主题也可以在样式引擎的主题上下文中可用(emotion 或 styled-components,取决于你的配置)。
⚠️如果你已经使用了 styled-component 或 emotion 驱动的自定义主题,那么它可能会不兼容 Material-UI 的主题规范。 如果它不兼容,那么你需要先渲染 Material-UI 的 ThemeProvider。 这样做就可以确保主题结构的隔离。 这对于想要在代码库中渐进式地使用 Material-UI 组件是非常理想的。
我们鼓励你在 Material-UI 和你项目的其他部分之间共享相同的主题对象。
const CustomizedSlider = styled(Slider)(
({ theme }) => `
color: ${theme.palette.primary.main};
:hover {
color: ${darken(theme.palette.primary.main, 0.2)};
}
`,
);
<ThemeProvider theme={customTheme}>
<CustomizedSlider defaultValue={30} />
</ThemeProvider>
Portals(传送门组件)
代办:在使用新的样式引擎实现传送门(portal)后,将会填写这部分内容。
CSS Modules
鉴于它全权依赖于大家使用的打包方案,我们很难得知 此种样式方案 的市场占有率。
CssModulesSlider.module.css
.slider {
color: #20b2aa;
}
.slider:hover {
color: #2e8b57;
}
CssModulesSlider.js
import * as React from 'react';
import Slider from '@material-ui/core/Slider';
// webpack, parcel or else will inject the CSS into the page
import styles from './CssModulesSlider.module.css';
export default function CssModulesSlider() {
return (
<div>
<Slider defaultValue={30} />
<Slider defaultValue={30} className={styles.slider} />
</div>
);
}
CSS 注入顺序⚠️
注意: 大多数的 CSS-in-JS 解决方案是在 HTML <head>
的底部注入它们的样式,这会导致你的自定义样式被 Material-UI 的样式规则所覆盖。 如果你有移除 !important 的需求,那么就需要改变 CSS 注入顺序。 Here's a demo of how it can be done in Material-UI:
import * as React from 'react';
import { StylesProvider } from '@material-ui/core';
export default function GlobalCssPriority() {
return (
<StylesProvider injectFirst>
{/* Your component tree. 现在你可以覆盖 Material-UI 的样式。 */}
</StylesProvider>
);
}
Note: If you are using emotion and have a custom cache in your app, that one will override the one coming from Material-UI. In order for the injection order to still be correct, you need to add the prepend option. 下面是一个示例: In order for the injection order to still be correct, you need to add the prepend option. 下面是一个示例:
import * as React from 'react';
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
const cache = createCache({
key: 'css',
prepend: true,
});
export default function CssModulesPriority() {
return (
<CacheProvider value={cache}>
{/* 这里编写你的组件 现在你可以覆盖 Material-UI 的样式。 */}
</CacheProvider>
);
}
Note: If you are using styled-components and have StyleSheetManager
with a custom target
, make sure that the target is the first element in the HTML <head>
. If you are curious to see how it can be done, you can take a look on the StylesProvider
implementation in the @material-ui/styled-engine-sc
package. If you are curious to see how it can be done, you can take a look on the StylesProvider
implementation in the @material-ui/styled-engine-sc
package.
更深层的元素
如果你试图自定义滑块的样式,那么很可能会影响到滑块的一些子元素,例如滚动条的箭头(thumb)。 在 Material-UI 中,所有的子元素都增加了两层的特定类:.parent .child {}
。 所以在编写覆盖样式的时候,你也需要这样做。
以下示例除了覆盖滑块本身的自定义样式外,还覆盖了滑块的 thumb
样式。
CssModulesSliderDeep1.module.css
.slider {
color: #20b2aa;
}
.slider:hover {
color: #2e8b57;
}
.slider .MuiSlider-thumb {
border-radius: 1px;
}
CssModulesSliderDeep1.js
import * as React from 'react';
// webpack, parcel or else will inject the CSS into the page
import styles from './CssModulesSliderDeep1.module.css';
import Slider from '@material-ui/core/Slider';
export default function CssModulesSliderDeep1() {
return (
<div>
<Slider defaultValue={30} />
<Slider defaultValue={30} className={styles.slider} />
</div>
);
}
上面的演示依赖于 默认的className
值,但是你也可以使用 componentsProps
API 来提供你自己的类名。
CssModulesSliderDeep2.module.css
.slider {
color: #20b2aa;
}
.slider:hover {
color: #2e8b57;
}
.slider .thumb {
border-radius: 1px;
}
CssModulesSliderDeep2.js
import * as React from 'react';
// webpack, parcel or else will inject the CSS into the page
import styles from './CssModulesSliderDeep2.module.css';
import Slider from '@material-ui/core/Slider';
export default function CssModulesSliderDeep2() {
return (
<div>
<Slider defaultValue={30} />
<Slider
defaultValue={30}
className={styles.slider}
componentsProps={{ thumb: { className: styles.thumb } }}
/>
</div>
);
}
Emotion
css
属性
Emotion 的 css() 方法与 Material-UI 无缝协作。
/** @jsx jsx */
import { jsx, css } from '@emotion/react';
import Slider from '@material-ui/core/Slider';
export default function EmotionCSS() {
return (
<div>
<Slider defaultValue={30} />
<Slider
defaultValue={30}
css={css`
color: #20b2aa;
:hover {
color: #2e8b57;
}
`}
/>
</div>
);
}
主题
它会像 styled components 一样起作用。 您可以 使用相同的指南 。
styled()
API
它会像 styled components 一样起作用。 您可以 使用相同的指南 。