Лучшие CSS-утилиты для проектов на React: Практические фрагменты стилизации
В этой статье я хочу поделиться с вами некоторыми из наиболее полезных CSS-утилит, которые я использую в своих проектах на React. Думаю, что многие из них помогут вам не только сэкономить время, но и пригодятся в ваших проектах. Все эти функции и фрагменты можно найти в папке css
в пакете ui
в репозитории ReactKit.
centerContent - центрирование содержимого внутри
Одним из наиболее практичных сниппетов является centerContent
. Он делает родительским элементом flexbox и центрирует дочерние элементы внутри него.
import { css } from "styled-components"
export const centerContent = css`
display: flex;
align-items: center;
justify-content: center;
`
Например, этот флажок имеет заданную ширину и высоту и позиционирует значок флажка внутри с помощью centerContent
:
const Box = styled.div<{ isChecked: boolean }>`
${sameDimensions(28)}
${centerContent};
sameDimensions - ширина и высота устанавливаются в одно и то же значение
Мы использовали функцию sameDimensions
, чтобы придать блоку одинаковую ширину и высоту:
import { css } from "styled-components"
import { toSizeUnit } from "./toSizeUnit"
export const sameDimensions = (size: string | number) => {
const value = toSizeUnit(size)
return css`
width: ${value};
height: ${value};
min-width: ${value};
min-height: ${value};
`
}
Как ширина, так и высота, а также минимальная ширина и минимальная высота устанавливаются этой функцией в одно и то же значение. В эту функцию можно передать строку или число. Если передается число, то оно будет преобразовано в пиксели с помощью функции toSizeUnit
:
export const toSizeUnit = (value: number | string) =>
typeof value === "number" ? `${value}px` : value
verticalPadding, horizontalPadding, verticalMargin, horizontalMargin - Отступы и поля устанавливаются в одно и то же значение
Функции verticalPadding
, horizontalPadding
, verticalMargin
и horizontalMargin
также весьма удобны. Часто нам необходимо установить одинаковое значение для верхней и нижней границы, левой и правой. Чтобы не повторять код, можно воспользоваться этими функциями:
import { css } from "styled-components"
import { toSizeUnit } from "./toSizeUnit"
export const verticalPadding = (value: string | number) => css`
padding-top: ${toSizeUnit(value)};
padding-bottom: ${toSizeUnit(value)};
`
export const horizontalPadding = (value: string | number) => css`
padding-left: ${toSizeUnit(value)};
padding-right: ${toSizeUnit(value)};
`
export const verticalMargin = (value: string | number) => css`
margin-top: ${toSizeUnit(value)};
margin-bottom: ${toSizeUnit(value)};
`
export const horizontalMargin = (value: string | number) => css`
margin-left: ${toSizeUnit(value)};
margin-right: ${toSizeUnit(value)};
`
За примером далеко ходить не надо. Здесь мы используем их для определения горизонтальной границы для кнопки. Это избавляет нас от излишеств при определении различных отступов для разных вариантов размеров:
${({ size }) =>
match(size, {
xs: () => css`
${horizontalPadding(8)}
height: 28px;
font-size: 14px;
`,
s: () => css`
${horizontalPadding(16)}
height: 36px;
font-size: 14px;
`,
m: () => css`
${horizontalPadding(20)}
height: 40px;
font-size: 16px;
`,
l: () => css`
${horizontalPadding(20)}
height: 48px;
font-size: 16px;
`,
xl: () => css`
${horizontalPadding(40)}
height: 56px;
font-size: 18px;
`,
})}
cropText - Обрезка текста с многоточием
Мы не хотим, чтобы текст выходил за границы своего блока. Для этого можно использовать функцию cropText
, которая добавит многоточие в конце текста, если он не помещается.
import { css } from "styled-components"
export const cropText = css`
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
Приведем пример, когда один из вариантов имеет длинное название и обрезается многоточием:
maxTextLines - Обрезка текста с многоточием после заданного количества строк
Аналогичную задачу решает функция maxTextLines
. Мы можем передать 3 в функцию maxTextLines
, и она обеспечит обрезку текста с многоточием после трех строк.
import { css } from "styled-components"
export const maxTextLines = (number: number) => css`
display: -webkit-box;
-webkit-line-clamp: ${number};
-webkit-box-orient: vertical;
overflow: hidden;
`
absoluteOutline - Элемент контура с абсолютным положением
Следующая функция предназначена для более продвинутого использования.
import { css } from "styled-components"
import { toSizeUnit } from "./toSizeUnit"
export const absoluteOutline = (
horizontalOffset: number | string,
verticalOffset: number | string
) => {
return css`
pointer-events: none;
position: absolute;
left: -${toSizeUnit(horizontalOffset)};
top: -${toSizeUnit(verticalOffset)};
width: calc(100% + ${toSizeUnit(horizontalOffset)} * 2);
height: calc(100% + ${toSizeUnit(verticalOffset)} * 2);
`
}
Я использую её в Increaser в табло для обводки текущего пользователя:
И на сегодняшней временной шкале для выделения текущего времени:
В ReactKit он используется для многократно используемого компонента Hoverable, создающего эффект выделения при наведении.
takeWholeSpace и takeWholeSpaceAbsolutely - заполнение всего пространства родительского блока
TakeWholeSpace
- это небольшая вспомогательная функция, которая устанавливает, что элемент будет занимать 100% ширины и высоты родительского элемента.
import { css } from "styled-components"
export const takeWholeSpace = css`
width: 100%;
height: 100%;
`
TakeWholeSpaceAbsolutely
выполняет ту же задачу, но с абсолютным положением.
import { css } from "styled-components"
import { takeWholeSpace } from "./takeWholeSpace"
export const takeWholeSpaceAbsolutely = css`
position: absolute;
left: 0;
top: 0;
${takeWholeSpace};
Практическое применение этой функции от Increaser - отображение оверлея над пусковой установкой сеанса фокусировки по окончании рабочего дня.
hideScrollbars и themedScrollbars - скрытие полос прокрутки и их стилизация
В ситуациях, подобных этой горизонтальной навигации, нам иногда требуется скрыть полосы прокрутки, что легко сделать с помощью функции hideScrollbars
:
import { css } from "styled-components"
export const hideScrollbars = css`
&::-webkit-scrollbar {
display: none;
}
-ms-overflow-style: none;
scrollbar-width: none;
Чтобы настроить внешний вид полос прокрутки в соответствии с темой нашего приложения, мы можем использовать тематические полосы прокрутки (themedScrollbars
). Они могут быть размещены в глобальных стилях один раз.
import { css } from "styled-components"
import { round } from "./round"
import { getColor } from "../ui/theme/getters"
export const themedScrollbars = css`
&::-webkit-scrollbar {
width: 8px;
}
&::-webkit-scrollbar-track {
background-color: transparent;
}
&::-webkit-scrollbar-thumb {
${round}
cursor: pointer;
background-color: ${getColor("mist")};
:hover {
background-color: ${getColor("mistExtra")};
}
}
`
interactive, round - Сделать элемент интерактивным и округлым
Последние два фрагмента, которыми я хочу поделиться: interactive, который добавляет указатель курсора и убирает выделение пользователя, чтобы пользователь случайно не выделил часть текста кнопки:
import { css } from "styled-components"
export const interactive = css`
cursor: pointer;
user-select: none;
`
Фрагмент round
округляет элемент, устанавливая border-radius
в произвольно большое число:
import { css } from "styled-components"
export const round = css`
border-radius: 1000px;
`
На этом пока всё! Благодарим за чтение! В следующих статьях мы рассмотрим полезные абстрактные компоненты React.