Рубріки: Теорія

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.

Останні статті

У КПІ будуть викладати «Програмування комп’ютерних ігор» за підтримки GSC Game World

Київський політехнічний інститут (КПІ) та найвідоміша українська геймдев-студія GSC Game World, розробник гри S.T.A.L.K.E.R. 2:…

28.11.2025

Хакери модифікували GPT для розробки шкідливих скриптів та проведення фішингових атак

Дослідники Unit42 з Palo Alto Networks проаналізували дві кастомні LLM-моделі, створені на базі GPT: WormGPT…

28.11.2025

Команда мови програмування Zig відмовляється від GitHub на користь Codeberg

Репозиторій мови Zig мігрує з GitHub до Codeberg, некомерційної компанії з хостингу Git, яка базується…

28.11.2025

Google обмежує безкоштовний доступ до Gemini 3 Pro через «високий попит»

Google запроваджує обмеження для безкоштовних користувачів на доступ до LLM-моделі Gemini 3 Pro та генератора…

28.11.2025

Українським IT-фахівцям треба готуватись до збільшення податків: уряд погодився на умови МВФ

Кабінет міністрів України погодився з пропозицією скасувати податкові пільги в обмін на новий пакет фінансування…

28.11.2025

Microsoft працює над новим способом оновлення програм із Microsoft Store

Останні preview-збірки Windows 11 демонструють, що Microsoft готує новий спосіб оновлення програм з каталогу Microsoft…

27.11.2025