
Для стилизации react компонентов наша команда использует styled-components.
О styled-components уже есть статьи на Хабре, поэтому подробно останавливаться на этом не будем.
Знакомство с Styled components
Лучше, быстрее, мощнее: styled-components v4
Написав много компонентов мы обнаружили, что почти в каждом компоненте мы копируем повторяющиеся свойства.
Например во многих компонентах мы писали так:
padding-top: ${props => props.paddingTop || '0'};
padding-bottom: ${props => props.paddingBottom || '0'};
padding-right: ${props => props.paddingRight || '0'};
padding-left: ${props => props.paddingLeft || '0'};
Styled system
Копирование повторяющихся свойств начало раздражать, и мы вынесли повторяющиеся куски кода в отдельные переиспользуемые функции. Но я задумался о том, что возможно кто-то уже реализовал подобное до нас и наверняка более красиво и универсально. Начал гуглить и нашел styled system.
Styled-System предоставляет набор стилевых функций. Каждая функция стиля предоставляет собственный набор свойств, которые стилизуют элементы на основе значений, определенных в теме приложения. styled system имеет богатый API с функциями для большинства свойств CSS.
Пример использования styled system на основе styled-components
import { space, width, fontSize, color } from 'styled-system';
import styled, { ThemeProvider } from 'styled-components';
import theme from './theme';
const Box = styled.div`
${space}
${width}
${fontSize}
${color}
`;
render(
<ThemeProvider theme={theme}>
<Box p={3} bg="whites.10" color="orange">
This is a Box
</Box>
</ThemeProvider>,
);
Основные преимущества
- Добавляет свойства, которые можно использовать в собственных темах
- Быстрая установка отзывчивых font-size, margin, padding, width и других свойств css через props
- Масштабируемость типографики
- Масштабируемость отступов margin и padding
- Поддержка любой цветовой палитры
- Работает с большинством библиотек css-in-js, включая styled-components и emotion
- Используется в Rebass, Rebass Grid, и Priceline Design System
Подключение темы
Выше я приводил пример кода, в котором используется ThemeProvider. Мы передаем в провайдер нашу тему, а styled system обращается к ней через props.
Пример нашей темы
export const theme = {
/** Размер шрифтов */
fontSizes: [
12, 14, 16, 18, 24, 32, 36, 72, 96
],
/** Отступы и границы */
space: [
// margin and padding
0, 4, 8, 16, 32, 64, 128, 256
],
/** Общие цвета */
colors: {
UIClientError: '#ff6c00',
UIServerError: '#ff0000',
UITriggerRed: '#fe3d00',
UITriggerBlue: '#00a9f6',
UIModalFooterLightBlueGray: '#f3f9ff',
UIModalTitleDefault: colorToRgba('#5e6670', 0.4),
UICheckboxIconCopy: colorToRgba('#909cac', 0.2)
},
/** Размеры кнопок */
buttonSizes: {
xs: `
height: 16px;
padding: 0 16px;
font-size: 10px;
`,
sm: `
height: 24px;
padding: 0 24px;
font-size: 13px;
`,
md: `
height: 34px;
padding: 0 34px;
font-size: 14px;
letter-spacing: 0.4px;
`,
lg: `
height: 56px;
padding: 0 56px;
font-size: 20px;
`,
default: `
height: 24px;
padding: 0 30px;
font-size: 13px;
`,
},
/** Цвета кнопок */
buttonColors: {
green: `
background-color: #a2d628;
color: ${colorToRgba('#a2d628', 0.5)};
`,
blue: `
background-color: #507bfc;
color: ${colorToRgba('#507bfc', 0.5)};
`,
lightBlue: `
background-color: #10aee7;
color: ${colorToRgba('#10aee7', 0.5)};
`,
default: `
background-color: #cccccc;
color: ${colorToRgba('#cccccc', 0.5)};
`
}
}
styled system попытается найти значение в объекте темы на основе переданных свойств компонента. Поддерживается глубокая вложенность свойств, если переданное значение не найдено в теме, то значение интерпретируется как есть.
Например мы передали компоненту color=«red». В объекте темы нет значения color.red, но значение red будет транслироваться в css как red. Таким образом после транспиляции в инспекторе мы увидим
color: red;
Другие примеры использования значений темы
// font-size: 24px (theme.fontSizes[4])
<Box fontSize={4} />
// margin: 16px (theme.space[3])
<Box m={3} />
// color: #ff6c00 (theme.colors.UIClientError)
<Box color="UIClientError" />
// background color (theme.colors.UITriggerBlue)
<Box bg="UITriggerBlue" />
// width: 50%
<Box width={1/2} />
Responsive styles
Для быстрого описания отзывчивых свойств достаточно передать массив значений
<Box
width={[
1, // 100% below the smallest breakpoint
1/2, // 50% from the next breakpoint and up
1/4 // 25% from the next breakpoint and up
]}
/>
// responsive font size
<Box fontSize={[ 1, 2, 3, 4 ]} />
// responsive margin
<Box m={[ 1, 2, 3, 4 ]} />
// responsive padding
<Box p={[ 1, 2, 3, 4 ]} />
Variants
styled system позволяет нам определять переиспользуемые объекты в нашей теме, которые содержат наборы цветов, стили текста и тп. Например в нашей теме, представленной выше, мы
используем варианты размеров и цветов кнопок.
/** Размеры кнопок */
buttonSizes: {
xs: `
height: 16px;
padding: 0 16px;
font-size: 10px;
`,
sm: `
height: 24px;
padding: 0 24px;
font-size: 13px;
`,
default: `
height: 24px;
padding: 0 30px;
font-size: 13px;
`,
},
/** Цвета кнопок */
buttonColors: {
green: `
background-color: #a2d628;
color: ${colorToRgba('#a2d628', 0.5)};
`,
blue: `
background-color: #507bfc;
color: ${colorToRgba('#507bfc', 0.5)};
`,
lightBlue: `
background-color: #10aee7;
color: ${colorToRgba('#10aee7', 0.5)};
`,
default: `
background-color: #cccccc;
color: ${colorToRgba('#cccccc', 0.5)};
`
}
Реализация варианта:
/** Для размеров кнопок */
export const buttonSize = variant({
/** Свойство компонента */
prop: 'size',
/** Свойство темы*/
key: 'buttonSizes'
});
/** Для цветов кнопок */
export const buttonColor = variant({
/** Свойство компонента */
prop: 'colors',
/** Свойство темы*/
key: 'buttonColors'
});
Компонент Button
/** Описание компонента */
export const Button = styled(Box.withComponent('button'))`
${buttonSize}
${buttonColor}
`;
Button.propTypes = {
...buttonSize.propTypes,
...buttonColor.propTypes,
}
Пример использования кнопки размера medium синего цвета
<Button
size="md"
colors="blue"
/>
Более подробное описание и документация styled system на оф. странице в github
UPD: во время написания статьи styled system обзавелся собственной страницей с документацией и примерами https://styled-system.com/.