Styled Components — стилізація React-додатків
Зміст
Сьогодні ми розглянемо зручну бібліотеку для React – Styled Components. Вона призначена для реалізації стилів у файлах JavaScript на основі вхідних даних React-компонентів — пропсів (props).
Особливості Styled Components
React – це чудовий спосіб писати великі та швидкі JavaScript-додатки. При розробці динамічних програм з цим інструментом часто доводиться стилізувати контент. Через низку причин використання стандартних засобів CSS для цього не зовсім зручне. Бібліотека Styled Components дає можливість виконати стилізацію React-програми, спростивши і прискоривши написання коду. Styled Components дозволяє працювати зі стилями прямо в JavaScript – це компонент, який в стилі підсовує функцію від якихось аргументів. У Styled Components ви звертаєтеся до функції і вона, по суті, може робити будь-що, повертаючи будь-яке рядкове значення для стилю цього компонента.
Переваги та недоліки Styled Components у React-додатках
Раніше до появи Styled Components, якщо потрібно було зробити динамічні стилі, їх потрібно було виносити в inline або писати багато className
. Але з цією бібліотекою ви більше не стилізуєте елементи HTML або компоненти на основі їхнього класу чи HTML-елемента. Відпадає необхідність у тернарних операторах, немає потреби вдаватися до className
. Натомість використовуються пропси всередині компонент, із зазначенням стилів, а класи генеруються автоматично (до речі, проблема колізії імен відсутня як така). Звернення до стилів CSS відбувається прямо в JavaScript, завдяки чому їм легко керувати, він зрозумілий, немає необхідності вивчати якийсь додатковий синтаксис.
Стилі легко відстежувати. Припустимо, ви написали якийсь компонент, а потім його прибрали, а стилі залишилися – їх потрібно позбутися, щоб вони зайвий раз не грузилися на клієнт. Така проблема зі Styled Components вирішується автоматично – видалили компонент, видалились стилі. Також до переваг Styled Components можна віднести наявність серверного рендерингу та модульних тестів.
Очевидний недолік Styled Components – прив’язка до React. Крім того, ми не повинні використовувати для вхідних даних React-компонентів зарезервовані назви (height, width, background-color тощо) . Ще один мінус цієї бібліотеки – стилі не зберігаються в кеші, стиль з’являється лише тоді, коли виконується JavaScript. Це дещо впливає на продуктивність.
Установка Styled Components
Для початку розберемося із встановленням Styled Components. Бібліотеку можна встановити так:
# менеджер пакетів npm
npm install --save styled-components
Альтернативний варіант з yarn:
# через yarn
yarn add styled-components
Стилизація компонентів виконується наступним чином. Замість того, щоб описувати стилі HTML на основі класу:
<button className="btn">Knopka</button>
Та
button.btn { background-color: #1dcde0;
color: white;
font-size: 22px;
margin: 11px;
padding: 5px 20px;
border: 4px solid black;
border-radius: 8px;}
Вказуються компоненти, які містять власні інкапсульовані набори стилів:
const Knopka = styled.button`
background-color: #1dcde0;
color: white;
font-size: 22px;
margin: 11px;
padding: 5px 20px;
border: 4px solid black;
border-radius: 8px;`;
За допомогою утиліти create-react-app створимо новий додаток, видалимо все зайве, залишивши програму повністю порожньою. Після встановлення пакета переходимо в компонент App і імпортуємо цей модуль styled-component. Створимо стилізований компонент – обгортку програми, грубо кажучи, кореневий блок div.
Усередині шаблонних літералів пишемо стилі, які збираємося використовувати: ширина на 100 відсотків, мінімальна висота – на всю висоту вікна браузера, padding у два rem (розмір щодо шрифту) та чорний колір фону програми.
Щоб побачити стилі, тепер обернемо наш додаток до обгортки:
const App = () => {
return (
<AppWrapper>
Some text
</AppWrapper>
);
};
Управління глобальними стилями
Оскільки за замовчуванням у браузері завжди є зовнішні-внутрішні відступи (через що з’явилася смуга прокручування), їх слід усунути глобальними стилями. Для цього в коді index.js із модуля styled-components імпортуємо функцію GlobalStyle і, за аналогією з попереднім прикладом, створюємо компонент, викликаємо цю функцію, вказуючи шаблонні літерали та стилі. Використовуючи універсальний селектор для кожного елемента на сторінці за замовчуванням, приберемо зовнішні та внутрішні відступи, параметр box-sizing (визначає як обчислюється загальна ширина та висота елемента) поставимо як border-box. Тепер цей компонент можна помістити в будь-яку ділянку коду, і ці стилі функціонуватимуть. Зазвичай, їх поміщають у корінь програми, або компоненту app. Згортаємо все в react-фрагмент і додамо наш додаток App-компоненту та глобальні стилі:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import styled, {createGlobalStyle} from "styled-components";
const Global = createGlobalStyle`
* {
margin:0;
padding:0;
box-sizing:border-box;
}`
ReactDOM.render(
<>
<Global/>
<App />
</>,
document.getElementById( 'root')
);
Відступи зникли, отже, глобальні стилі працюють. У стилях підключимо шрифт.
font-family: consolas;
Робота з пропсами
Щоб упорядкувати компоненти, створимо окрему директорію, назвемо її компоненти. Створимо там перший компонент – Title.js. Швидко розгортаємо React-компонент (можна через сніппет, набравши rsc
) і зробимо стилізований заголовок, прописавши в шаблонних літералах стилі:
import React from 'react';
import styled from "styled-components";
const StyledTitle = styled.h1`
color: white;
`
const Title = () => {
return <StyledTitle>
</StyledTitle>
};
export default Title;
Повернемося до App.js та додамо його на сторінку. Замість Some text додаємо
<Title>Highload.tech </Title>
Якщо оновити сторінку у браузері, ми побачимо чорний колір.
Щоб React зрозумів, що текст потрібно додати всередину стилізованого заголовка, використовуємо пропс, який називається {children}
. Додаємо цей пропс і поміщаємо його всередину.
import React from 'react';
import styled from "styled-components";
const StyledTitle = styled.h1`
color: white;
`
const Title = ({children}) => {
return <StyledTitle>
{children}
</StyledTitle>
};
export default Title;
Припустимо, під час роботи програми, нам необхідно динамічно змінювати колір заголовка. За допомогою наступного синтаксису залежно від пропсу, який приймає компонент, можна змінювати ті чи інші властивості:
color: ${props => props.color};
Повернемося в компонент App і додамо нашому заголовку пропс color, додавши, скажімо, синій колір:
<Title color={"blue"}>Highload.tech </Title>
Якщо зараз ми відкриємо браузер, то нічого не побачимо, оскільки передали пропс не в StyledTitle, а просто в Title. Тому в Title.js цей пропс потрібно прийняти та передати до StyledTitle:
const Title = ({children, color}) => {
return <StyledTitle color={color}>
Відкриваємо браузер і бачимо, що колір змінився – таким чином можна міняти колір заголовка передаючи різні пропси .
Однак такий запис є досить незручним. Адже якщо у нас буде з десяток різних пропсів, вручну їх перераховуват незручно. Є більш лаконічний синтаксис, що дозволяє в StyledTitle розгорнути всі пропси:
import React from 'react';
import styled from "styled-components";
const StyledTitle = styled.h1`
color: ${props => props.color};
`
const Title = (props) => {
return <StyledTitle {...props}/>
};
export default Title;
Все, що ми будемо передавати в Title, буде автоматично передаватися і в StyledTitle.
Створимо ще один компонент, назвемо його Flex.js. Це буде також свого роду обгортка, яка прийматиме напрямок Flex-контейнера, align-items і justify-content, щоб вирівнювати щодо контейнера всі внутрішні елементи.
import React from 'react';
import styled from 'styled-components'
const StyledFlex = styled.div`
display: flex;
flex-direction: ${props => props.direction || 'row'};
align-items: ${props => props.align || 'stretch'};
justify-content: ${props => props.justify || 'stretch'};
margin: ${({margin}) => margin || '0'};
`
const Flex = (props) => {
return <StyledFlex {...props}/>
};
export default Flex;
Кожна з перерахованих властивостей прийматиме значення, залежно від того, який пропс ми прокинули. Так, якщо ми передали props.direction
, то він буде присвоєний властивості flex-direction
. У протилежному випадку буде надано значення 'row'
.
Повертаємося в App.js – тепер можемо користуватися компонентом Flex і помістити в нього наш Title, центруючи його посередині.
import Title from "./components/Title";
import Flex from "./components/Flex";
const AppWrapper = styled.div`
width: 100% ;
min-height: 100vh;
padding: 2rem;
background: black;
`
const App = () => {
return (
<AppWrapper>
<Flex justify = "center">
<Title color={"blue"}>Highload.tech </Title>
</Flex>
</AppWrapper>
);
};
export default App;
Щоб розібратися в цій темі, зробимо щось на зразок симулятора вікна командного рядка. Перейдемо до верстки вікна терміналу – створюємо компонент Console.js. Поле текста розтягнемо на всю ширину, висоту – 80% від висоти вікна браузера, прокинемо в компонент пропси і повернемо з цього компонента нашу стилізовану консоль.
import React from 'react';
import styled from "styled-components";
const StyledConsole = styled.textarea`
width:100%;
height:80vh;
`
const Console = (props) => {
return <StyledConsole {...props}/>
};
export default Console;
У компоненті Flex.js додамо цю консоль
const App = () => {
return (
<AppWrapper>
<Flex justify = "center">
<Title color={"blue"}>Highload.tech </Title>
</Flex>
<Console/>
</AppWrapper>
Налаштуємо зовнішній вигляд консолі
color: ${({color}) => color || "red"
Псевдокласи
На прикладі фокусу розглянемо, як працювати з псевдокласами. Використовуємо знак &, який замінює селектор поточного елемента та вказуємо, щоб рамка поля при виділенні не малювалася:
&:focus{
outline: none;
}
Додамо кнопку і, на прикладі цього елемента, розглянемо як можна робити різні стилі залежно від пропса. Створюємо та розгортаємо новий компонент Button.js:
import React from 'react';
import styled from "styled-components";
const StyledButton = styled.button`
border:none;
padding:10px 15px;
font-size:26px;
cursor: pointer;
& focus {
outline:none;
}
`
const Button = (props) => {
return <StyledButton{...props}/>
};
export default Button;
Повертаємося до App.js і додаємо під консоль цю кнопку:
.. <AppWrapper>
<Flex justify = "center">
<Title color={"blue"}>Highload.tech </Title>
</Flex>
<Console/>
<Button>Publish</Button>
</AppWrapper>
Перемістимо кнопку праворуч. Консоль і кнопку обернемо у <Flex>
і додамо пропс для того, щоб змістити кнопку праворуч:
<AppWrapper>
<Flex justify = "center">
<Title color={"blue"}>Highload.tech </Title>
</Flex >
<Flex direction="column">
<Console/>
<Button align="flex-end">Publish</Button>
</Flex>
</AppWrapper>
У Button.js додаємо властивість align-self, що дозволяє вирівняти якийсь елемент усередині флекс-контейнера. Значення отримуватимемо з пропсів, а якщо такого немає, за замовчуванням встановимо stretch.
align-self: ${props => props.align || 'stretch'}
Угруповання стилів на основі пропсів
Тепер займемося стилями. Щоб згрупувати декілька властивостей, залежно від пропсів, використовується наступна конструкція. Вона складається з логічного “І” (&&) і вказаного в шаблонних літералах стилів, які застосовуються, якщо ми передали компонент цей пропс. Ставимо код у Button.js
import React from 'react';
import styled from "styled-components";
const StyledButton = styled.button`
border:none;
padding:10px 15px;
font-size:26px;
cursor: pointer;
& focus {
outline:none;
}
align-self: ${props => props.align || 'stretch'};
${props => props.primary && `
color: ${props => props.color ||'white'};
background: ${props => props.background||'white'};
`}
`
const Button = (props) => {
return <StyledButton{...props}/>
};
export default Button;
Перейдемо в компонент App і передамо пропс primary.
Button primary background={‘green’} color={'red'} align="flex-end">Publish</Button>
Змінюємо color={'green'}
і переконуємося, що колір кнопки став червоним на зеленому фоні.
Тепер зробимо стиль кнопки з обведенням
${props => props.outlined && css`
color: ${props => props.color || 'white'};
border: 1px solid ${props => props.color || "white"};
background: transparent;
`}
Повертаємося в App.js та передаємо пропсам outlined
<Button outlined align="flex-end">Publish</Button>
Створимо кнопку, яка буде мати ті самі стилі, що і Styled button, але більше в розмірах. Викликаємо Styled, параметром передаємо компонент, від якого хочемо успадковуватися, збільшуємо розмір шрифту.
const LargeButton = styled(StyledButton)`
font-size: 32px;
Тепер кнопка стала більшою, але вона зберегла всі стилі, які є у StyledButton. Грубо кажучи – LargeButton успадковується від StyledButton. Таким чином, стилі можна розширювати на основі існуючих компонентів.
Анімація
Принцип анімації той самий, що й у CSS. Щоб додати анімацію, необхідно використовувати функцію keyframes. Для підключення використовуємо псевдоклас hover.
import React from 'react';
import styled, {css, keyframes} from 'styled-components'
const rotateAnimation = keyframes`
0% {
transform: rotateZ(0deg);
}
100% {
transform: rotateZ(360deg);
}
`const StyledButton = styled.button.attrs(props => ({
outlined: true,
}))`
border: none;
padding: 10px 15px;
font-size: 18px;
cursor: pointer;
&:focus {
outline: none;
}
&: hover {
animation: ${rotateAnimation} 1s infinite linear;
}
align-self: ${props => props.align || 'stretch'};
${props => props.primary && css`
color: ${props => props.color || 'white'};
background: ${props => props.background || 'white'};
`}
${props => props.outlined && css`
color: ${props => props.color || 'white'};
border: 1px solid ${props => props.color || "white"};
background: transparent;
`}
`const LargeButton = styled(StyledButton)`
font-size: 32px;
`const Button = (props) => {
return <StyledButton {...props}/>
};
export default Button;
Висновок
Ми розібралися з бібліотекою Styled Components та розглянули основні прийоми роботи з нею. Для більш детального вивчення даної теми рекомендуємо вам переглянути відео, де автор використовуючи Styled Components проведе майстер клас зі створення SPA-додатка з вибором теми REST API запитами, пошуком, фільтрацією SPA-проект с темізацією на React та styled-components.
Favbet Tech – це ІТ-компанія зі 100% українською ДНК, що створює досконалі сервіси для iGaming і Betting з використанням передових технологій та надає доступ до них. Favbet Tech розробляє інноваційне програмне забезпечення через складну багатокомпонентну платформу, яка здатна витримувати величезні навантаження та створювати унікальний досвід для гравців.
Сообщить об опечатке
Текст, который будет отправлен нашим редакторам: