Customizing components
Вы можете легко настроить внешний вид компонента Material-UI.
Поскольку компоненты могут использоваться в разных контекстах, существует несколько подходов к этому. Переходя от самого нераспространённого варианта к самому широко используемому, это:
- Конкретное изменение для единичного случая
- Динамическое изменение для единичного случая
- Особый вариант компонента использумый в различных контекстах
- Material Design варианты как у компонента кнопка
- Глобальное изменение темы
1. Конкретное изменение для единичного случая
Возможно, вам придется изменить стиль компонента в конкретном месте. Для этого вам предоставляются следующие методы:
Переопределение стилей через имена классов
Первый способ переопределения стиля компонента - использовать имена классов. Каждый компонент предоставляет свойство className
которое всегда применяется к корневому элементу.
В этом примере компонент высшего-порядка withStyles()
используется для внедрения пользовательских стилей в DOM и передачи имени класса компоненту ClassNames
через его свойство classes
. Для создания стилей вы можете воспользоваться любым доступным стилевым решением, вплоть до обычного CSS, но вы обязаны принимать во внимание порядок внедрения CSS, поскольку CSS внедренный в DOM через Material-UI имеет максимально возможную специфичность, так как <link>
внедряется в самом конце раздела <head />
для гарантии корректного отображения компонентов.
Overriding styles with classes
Когда className
свойства недостаточно, и вам нужен доступ ко вложенным элементам, вы можете воспользоваться свойством объекта classes
для настройки всех CSS, внедренных через Material-UI для данного компонента.
Список классов, доступных для каждого компонента представлен на странице API-документации компонента. Обратитесь к разделу ** CSS ** и ищите в столбце с именем правила. В качестве примера можно привести компонент пункт меню и состояние выбрано. Помимо доступа к вложенным элементам, свойство classes
можно использовать для настройки специальных состояний компонентов Material-UI:
В этом примере также используется withStyles()
(см. выше), но теперь ClassesNesting
присваивает свойству classes
компонета Button
обьект сопоставляющий имена переопределяемых классов (стилевые правила) с **именам использумых классов CSS ** (значениями). Существующие классы компонента будут по прежнему внедряться, поэтому необходимо указать только те стили, которые вы хотите добавить или переопределить.
Обратите внимание, что в дополнение к стилю кнопки, стиль текста кнопки был изменен на стиль с заглавными буквами:
<Button
classes={{
root: classes.root, // class name, e.g. `classes-nesting-root-x`
label: classes.label, // class name, e.g. `classes-nesting-label-x`
}}
>
classes nesting
</Button>
Переопределение стилей через глобальные имена классов
Использование инструментов разработчика
Инструменты разработчика браузера могут сэкономить вам много времени. В режиме разработки имена классов Material-UI следуют простому шаблону: Mui[имя компонента]-[имя стилевого правила]-[UUID]
.
Вернемся к упомянутому выше примеру. Как вы можете переопределить текст кнопки?
Используя инструменты разработчика, вы знаете, что вам нужно нацелиться на компонент Button
и стилевое правило label
:
<Button classes={{ label: 'my-class-name' }} />
Краткая запись
Приведенный выше пример кода может быть сокращен за счет использования **того же CSS API ** в качестве дочернего компонента. В этом примере компонент высшего порядка withStyles()
внедряет свойство classes
, используемое затем компонентом Button
.
const StyledButton = withStyles({
root: {
background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
borderRadius: 3,
border: 0,
color: 'white',
height: 48,
padding: '0 30px',
boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)',
},
label: {
textTransform: 'capitalize',
},
})(Button);
<StyledButton>classes shorthand</StyledButton>
Pseudo-classes
Особые состояния компонент, такие как * наведение (hover)*, * фокус *, disabled и selected, стилизованы при помощи CSS с более высокой специфичностью. Специфичность - это весовой коэффициент применяемый к данной декларации CSS.
Чтобы переопределить особые состояния компонентов, вам нужно увеличить специфичность. Вот пример с disable состоянием и компонентом кнопка использующим псевдокласс (:disabled
):
.Button {
color: black;
}
.Button:disabled { /* Increase the specificity */
color: white;
}
<Button disabled className="Button">
Иногда вы не можете использовать псевдо-класс, так как это состояние в платформе отсутствует. В качестве примера можно привести компонент пункт меню и состояние выбрано. Помимо доступа к вложенным элементам, свойство classes
можно использовать для настройки специальных состояний компонентов Material-UI:
.MenuItem {
color: black;
}
.MenuItem.selected { /* Increase the specificity */
color: blue;
}
<MenuItem selected classes={{ root: 'MenuItem', selected: 'selected' }}>
Почему я должен повышать специфичность для переопределения отдельного состояния компонента?
Спецификация CSS, по определению, обязывает псевдоклассы повышать специфичность. Для согласованности Material-UI повышает специфичность своих пользовательских псевдоклассов. Это имеет одно важное преимущество: оно позволяет выбрать определённое состояние, которое вы хотите изменить.
Могу ли я использовать другое API, которое требует меньше шаблонов?
Вместо предоставления значений API свойства classes
, вы можете положиться на глобальные имена классов которые генерируется Material-UI. Оно реализует все эти пользовательские псевдоклассы:
classes key | Global class name |
---|---|
checked | Mui-checked |
disabled | Mui-disabled |
error | Mui-error |
focused | Mui-focused |
focusVisible | Mui-focusVisible |
required | Mui-required |
expanded | Mui-expanded |
selected | Mui-selected |
.MenuItem {
color: black;
}
.MenuItem.Mui-selected { /* Increase the specificity */
color: blue;
}
<MenuItem selected className="MenuItem">
Используйте $ruleName
для ссылки на правило в той же таблице стилей
Плагин jss-nested (доступный по умолчанию) позволяет упростить процесс повышения специфичности.
const styles = {
root: {
'&$disabled': {
color: 'white',
},
},
disabled: {},
};
компилируется в:
.root-x.disable-x {
color: white;
}
⚠️ ️ Чтобы это сработало, вам нужно применить к DOM оба сгенерированных имени класса (root
& disabled
).
<Button
disabled
classes={{
root: classes.root, // class name, e.g. `root-x`
disabled: classes.disabled, // class name, e.g. `disabled-x`
}}
>
<Button
disabled
classes={{
root: classes.root, // class name, e.g. `root-x`
disabled: classes.disabled, // class name, e.g. `disabled-x`
}}
>
classes state
</Button>
Переопределение с помощью встраиваемых (inline) стилей
Второй способ переопределить стиль компонента – использовать подход встроенного стиля. Каждый компонент предоставляет свойство style
. Эти свойства всегда применяются к корневому элементу.
Вам не нужно беспокоиться о специфичности CSS, так как встроенный стиль имеет приоритет над обычным CSS.
<Button style={style}>inline-style</Button>
Когда я должен использовать встраиваемый стиль, а когда классы?
2. Динамическое изменение для единичного случая
You have learned how to override the style of a Material-UI component in the previous section. Теперь давайте посмотрим, как мы можем сделать эти переопределения динамическими. Here are five alternatives; each has its pros and cons.
Динамический CSS
<React.Fragment>
<FormControlLabel
control={
<Switch
checked={color === 'blue'}
onChange={handleChange}
color="primary"
value="dynamic-class-name"
/>
}
label="Blue"
/>
<StyledButton color={color}>Dynamic CSS</StyledButton>
</React.Fragment>
<React.Fragment>
<FormControlLabel
control={
<Switch
checked={color === blue}
onChange={handleChange}
color="primary"
value="dynamic-class-name"
/>
}
label="Blue"
/>
<Button className={classes.button} style={color}>
CSS variables
</Button>
</React.Fragment>
3. Особый вариант компонента
Возможно вам потребуется создать вариант компонента и использовать его в разных контекстах, например раскрашенную кнопку на странице вашего товара, но вы, вероятно, захотите сохранить свой код компактным.
Наилучший подход состоит в том, чтобы следовать варианту 1, а затем воспользоваться преимуществами композиции React, экспортируя настроенный компонент для использования там, где он вам нужен.
<ClassNames>Component</ClassNames>
4. Material Design варианты
Спецификация Material Design допускает существование некоторых компонентов в различных вариантах. Так, например, кнопки реализованы в разных формах: text (прежде "flat"), contained (прежде "raised"), FAB и другие.
Material-UI старается реализовать все эти варианты. Пожалуйста, обратитесь к разделу документации Поддерживаемые компоненты, чтобы узнать текущее состояние реализации всех компонентов Material Design.
5. Глобальное изменение темы
In order to promote consistency between components, and manage the user interface appearance as a whole, Material-UI provides a mechanism to apply global changes.
The demos of this section covers how to the change the button's font size.
Настраиваемые параметры темы
You can adjust the theme configuration variables.
const theme = createMuiTheme({
typography: {
button: {
fontSize: '1rem',
},
},
});
<ThemeProvider theme={theme}>
<Button>font-size: 1rem</Button>
</ThemeProvider>
Глобальное переопределение CSS
Вы также можете настроить все экземпляры компонента с помощью CSS. Это очень похоже на настройку Bootstrap. Components expose global class names to enable this.
const GlobalCss = withStyles({
// @global is handled by jss-plugin-global.
'@global': {
// You should target [class*="MuiButton-root"] instead if you nest themes.
'.MuiButton-root': {
fontSize: '1rem',
},
},
})(() => null);
// …
<GlobalCss />
<React.Fragment>
<GlobalCss />
<Button>font-size: 1rem</Button>
</React.Fragment>
Глобальное переопределение темы
Вы можете воспользоваться переопределением
ключевых параметров темы
, чтобы потенциально изменить любой стиль, внедренный Material-UI в DOM. Дальнейшие подробности об этом в разделе документации темы.
const theme = createMuiTheme({
overrides: {
MuiButton: {
root: {
fontSize: '1rem',
},
},
},
});
<ThemeProvider theme={theme}>
<Button>font-size: 1rem</Button>
</ThemeProvider>
Adding new component variants
You can take advantage of the variants
key in the theme
's components section to add new variants to Material-UI components. These new variants, can specify which styles the component should have, if specific props are defined together.
The definitions are specified in an array, under the component's name. For every one of them a class is added in the head. The order is important, so make sure that the styles that should win will be specified lastly.
const theme = createMuiTheme({
components: {
MuiButton: {
variants: [
{
props: { variant: 'dashed' },
style: {
textTransform: 'none',
border: `2px dashed grey${blue[500]}`,
},
},
{
props: { variant: 'dashed', color: 'secondary' },
style: {
border: `4px dashed ${red[500]}`,
},
},
],
},
},
});
If you are using TypeScript, you will need to specify your new variants/colors, using module augmentation.
declare module '@material-ui/core/Button/Button' {
interface ButtonPropsVariantOverrides {
dashed: true;
}
}
<ThemeProvider theme={theme}>
<Button variant="dashed">Dashed</Button>
<Button variant="dashed" color="secondary">
Secondary
</Button>
<Button variant="dashed" size="large">
Large
</Button>
<Button variant="dashed" color="secondary" size="large">
Secondary large
</Button>
</ThemeProvider>