Interoperabilidade da Biblioteca de Estilo
Enquanto você pode usar a solução de estilo baseada em JSS fornecida pelo Material-UI para estilizar sua aplicação, você também pode usar o que você já conhece e ama (desde CSS simples a styled-components).
Este guia tem como objetivo documentar as alternativas mais populares, mas você deve descobrir que os princípios aplicados aqui podem ser adaptados para outras bibliotecas. Existem exemplos para as seguintes soluções de estilo:
CSS puro
Nada extravagante, apenas 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>Padrão</Button>
<Button className="button">Customizado</Button>
</div>
);
}
Controlando prioridade ⚠️
Nota: O JSS injeta seus estilos na parte inferior do <head>
. Se você não quiser marcar atributos de estilo com !important, você precisa alterar a ordem de injeção do CSS, como na demonstração:
import { StylesProvider } from '@material-ui/core/styles';
<StylesProvider injectFirst>
{/* Sua árvore de componentes.
Agora, você pode sobrescrever os estilos do Material-UI. */}
</StylesProvider>
Elementos mais profundos
Se você tentar estilizar um Drawer com variante permanente, provavelmente precisará afetar o elemento Paper, elemento filho do Drawer. No entanto, o paper não é o elemento raiz do Drawer e, portanto, a customização de styled-components como acima não funcionará. Você precisa usar a API classes
do Material-UI.
O exemplo a seguir sobrescreve o estilo de label
e Button
, além dos estilos customizados no próprio botão.
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>Padrão</Button>
<Button classes={{ root: 'button', label: 'button-label' }}>
Customizado
</Button>
</div>
);
}
CSS global
Fornecer explicitamente os nomes das classes ao componente é um esforço excessivo? Você pode segmentar os nomes de classe gerados por 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>Customizado</Button>;
}
Controlando prioridade ⚠️
Nota: O JSS injeta seus estilos na parte inferior do <head>
. Se você não quiser marcar atributos de estilo com !important, você precisa alterar a ordem de injeção do CSS, como na demonstração:
import { StylesProvider } from '@material-ui/core/styles';
<StylesProvider injectFirst>
{/* Sua árvore de componentes.
import { StylesProvider } from '@material-ui/core/styles';
<StylesProvider injectFirst>
{/* Sua árvore de componentes. */}
</StylesProvider>
Styled Components
O método styled()
funciona perfeitamente em todos os componentes.
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>Padrão</Button>
<StyledButton>Customizado</StyledButton>
</div>
);
}
Controlando prioridade ⚠️
Nota: Ambos, styled-components e JSS injetam seus estilos na parte inferior do <head>
. A melhor abordagem para garantir que os estilos do styled-components sejam carregados por último, é alterar a ordem de injeção do CSS, como na demonstração:
import { StylesProvider } from '@material-ui/core/styles';
<StylesProvider injectFirst>
{/* Sua árvore de componentes.
Agora, você pode sobrescrever os estilos do Material-UI. */}
</StylesProvider>
Outra abordagem é usar os caracteres &&
em styled-components para aumentar a especificidade repetindo o nome da classe. Evite o uso de !important
.
Elementos mais profundos
Se você tentar estilizar um Drawer com variante permanente, provavelmente precisará afetar o elemento Paper, elemento filho do Drawer. No entanto, o paper não é o elemento raiz do Drawer e, portanto, a customização de styled-components como acima não funcionará. Você precisa usar a API classes
do Material-UI.
O exemplo a seguir sobrescreve o estilo de label
e Button
, além dos estilos customizados no próprio botão. Também funciona como solução de contorno para este problema com styled-components, por "consumir" propriedades que não devem ser passadas para o componente subjacente.
<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>Padrão</Button>
<StyledButton>Customizado</StyledButton>
</div>
);
}
A demonstração acima depende dos valores padrão de classes
, mas você pode fornecer seu próprio nome de classe: .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>Padrão</Button>
<StyledButton>Customizado</StyledButton>
</div>
);
}
Tema
Material-UI tem uma estrutura de tema rica, que você pode aproveitar para manipulações de cores, transições, consultas de mídia e muito mais.
Incentivamos a compartilhar o mesmo objeto de tema entre Material-UI e seus estilos.
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>
Portais
O Portal fornece uma maneira de elegante para renderizar filhos em um nó DOM que existe fora da hierarquia DOM do componente pai. Devido a maneira como o escopo de CSS do styled-components funciona, você pode encontrar problemas nos quais o estilo não é aplicado.
Por exemplo, se você tentar estilizar o Menu de um componente Select usando a propriedade MenuProps
, você precisará passar a propriedade className
para o elemento que está sendo renderizado fora de sua hierarquia DOM. O exemplo a seguir mostra uma solução alternativa:
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;
}
`;
Módulos CSS
É difícil saber a participação de mercado nesta solução de estilo, pois é dependente da solução de empacotamento que as pessoas estão usando.
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 ou qualquer outro irá injetar o CSS na página
import styles from './CssModulesButton.css';
import Button from '@material-ui/core/Button';
export default function CssModulesButton() {
return (
<div>
<Button>Padrão</Button>
<Button className={styles.button}>Customizado</Button>
</div>
);
}
Controlando prioridade ⚠️
Nota: O JSS injeta seus estilos na parte inferior do <head>
. Se você não quiser marcar atributos de estilo com !important, você precisa alterar a ordem de injeção do CSS, como na demonstração:
import { StylesProvider } from '@material-ui/core/styles';
<StylesProvider injectFirst>
{/* Sua árvore de componentes.
Agora, você pode sobrescrever os estilos do Material-UI. */}
</StylesProvider>
Elementos mais profundos
Se você tentar estilizar um Drawer com variante permanente, provavelmente precisará afetar o elemento Paper, elemento filho do Drawer. No entanto, o paper não é o elemento raiz do Drawer e, portanto, a customização de styled-components como acima não funcionará. Você precisa usar a API classes
do Material-UI.
O exemplo a seguir sobrescreve o estilo de label
e Button
, além dos estilos customizados no próprio botão.
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 ou qualquer outro irá injetar o CSS na página
import styles from './CssModulesButtonDeep.css';
import Button from '@material-ui/core/Button';
export default function CssModulesButtonDeep() {
return (
<div>
<Button>Padrão</Button>
<Button classes={styles}>Customizado</Button>
</div>
);
}
Emotion
A propriedade css
O método css() do Emotion funciona perfeitamente com Material-UI.
/** @jsx jsx */
import { jsx, css } from '@emotion/core';
import Button from '@material-ui/core/Button';
export default function EmotionCSS() {
return (
<div>
<Button>Padrão</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;
}
`}
>
Customizado
</Button>
</div>
);
}
Controlando prioridade ⚠️
Nota: O JSS injeta seus estilos na parte inferior do <head>
. Se você não quiser marcar atributos de estilo com !important, você precisa alterar a ordem de injeção do CSS, como na demonstração:
import { StylesProvider } from '@material-ui/core/styles';
<StylesProvider injectFirst>
{/* Sua árvore de componentes.
Agora, você pode sobrescrever os estilos do Material-UI. */}
</StylesProvider>
Tema
Material-UI tem uma estrutura de tema rica, que você pode aproveitar para manipulações de cores, transições, consultas de mídia e muito mais.
Incentivamos a compartilhar o mesmo objeto de tema entre Material-UI e seus estilos.
<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;
}
`}
>
Customizado
</Button>
A API styled()
Funciona exatamente como styled components. Você pode usar o mesmo guia.