
Для стилизации 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/.
