Что-то слышали о CSS в языке JS, но так и не разобрались? Возможно, зря. Мы подготовили статью про работу с этой технологией. Читайте.
Вероятно, вы слышали такие термины, как CSS в языке JS, Styled Components, Radium, Aphrodite, и, скорее всего, решили, что это всё ненужные штуки. В этой статье я расскажу про их суть. Сразу следует оговориться, что нижесказанное – всего лишь частное мнение, и его не обязательно придерживаться.
Мне всегда было неудобно работать с огромной папкой стилей. Я пробовал разные подходы к решению этой проблемы, и на данный момент считаю CSS в JS наиболее оптимальным.
Давайте посмотрим, что может CSS в JS.

Что такое CSS в языке JS?
Имейте в виду, что стили Inline и CSS в JS – не одно и то же! Ниже краткая демонстрация различий.
Как работают встроенные стили?
const textStyles = {
color: white,
backgroundColor: black
}
<p style={textStyles}>inline style!</p>
В браузере это будет привязано к узлу DOM следующим образом:
<p style="color: white; backgrond-color: black;">inline style!</p>
Как работают CSS в JS?
import styled from 'styled-components'; const Text = styled.div` color: white, background: black ` <Text>Hello CSS-in-JS</Text>
В браузере это будет привязано к DOM, например вот так:
<style>
.hash136s21 {
background-color: black;
color: white;
}
</style>
<p class="hash136s21">Hello CSS-in-JS</p>
Различия
Увидели разницу? CSS в языке JS приложил тег <style> поверх DOM, а встроенные стили просто привязали свойства к узлу DOM.
Ну и почему это важно?
Не все CSS-функции корректно работают с обработчиками событий JavaScript, многие псевдоселекторы (например disabled, before, nth-child) невозможны, не поддерживаются html и body, а также другие неприятные вещи.
Используя эту технологию, все возможности CSS остаются у вас под рукой. Поскольку создается фактический CSS, вы можете использовать каждый медиа-запрос и псевдоселектор. Некоторые библиотеки (например, jss, styled-components) даже добавляют поддержку функций, не связанных с CSS, и это круто!
Если хотите ещё подробнее, можно почитать в этом блоге.
CSS никогда не использовался для компонентных подходов. CSS в JS решают именно эту проблему.
В чём преимущества использования?
- Вам больше не нужно поддерживать набор стилей. CSS в JS абстрагируют модель CSS на уровне компонентов, а не на уровне документа (это называется модульность).
- Данная технология использует всю мощь экосистемы JavaScript для улучшения CSS.
- Ограниченных селекторов недостаточно. CSS имеет свойства, которые автоматически наследуются от родительского элемента, если они явно не определены. Благодаря плагину jss-isolate, правила JSS не наследуют свойства.
- Невозможно избежать селекторных столкновений в нетривиальных приложениях. Соглашения об именах, таких как BEM, могут помочь в рамках одного проекта, но не будут использоваться при интеграции стороннего кода. При компиляции JSS генерирует уникальные имена классов по умолчанию JSON-представления в CSS.
- Правила CSS автоматически начинаются с префикса, поэтому вам не нужно об этом думать.
- Легкое разделение констант и функций между JS и CSS (для тех кто не понял, это про совместное использование кода).
- В DOM находятся те же стили, которые в настоящее время используются на вашем экране.
- Удаление кода.
- Юнит-тесты для CSS.
В чём недостатки использования?
- Не так просто освоить.
- Новые зависимости, к которым нужно привыкать.
- Новичкам сложнее адаптироваться к кодовой базе.
Короче, если всё освоить, то недостатков нет.
Наиболее популярные библиотеки
Styled Components

import React, { Component } from 'react';
import styled from 'styled-components';
const Title = styled.h1`
color: white;
`;
const Wrapper = styled.div`
background: black
`
class App extends Component {
render() {
return (
<Wrapper>
<Title>Hello World!</Title>
</Wrapper>
);
}
}
export default App;
JSS-React

import React from 'react'
import injectSheet from 'react-jss'
const styles = {
wrapper: {
background: 'black'
},
title: {
color: 'white'
}
}
const App = ({classes}) => (
<div className={classes.wrapper}>
<h1 className={classes.title}>
Hello JSS-React!
</h1>
</div>
)
export default injectSheet(styles)(App)
glamorous

import React from 'react'
import glamorous from 'glamorous'
const Wrapper = glamorous.div({
backgroundColor: 'black'
})
const Title = glamorous.h1({
color: 'white'
})
const App = () => (
<Wrapper>
<Title> Hello JSS-React!</Title>
</Wrapper>
)
export default App;
Radium

import React, { Component } from 'react';
import Radium from 'radium';
@Radium // decorator
class App extends Component {
render() {
const styles = {
wrapper: {
background: 'blue',
}
title: {
color: 'white'
}
};
return (
<div style={styles.wrapper}>
<h1 style={styles.title}>Hello Radium!</h1>
</div>
);
}
}
export default Radium(App);
Внимание: Radium использует декораторы!
Aphrodite
import React, { Component } from 'react';
import { StyleSheet, css } from 'aphrodite';
const styles = StyleSheet.create({
wrapper: {
backgroundColor: 'red'
},
title: {
backgroundColor: 'blue'
}
});
class App extends Component {
render() {
return (
<div className={css(styles.wrapper)}>
<h1 className={css(styles.title)}>Hello Aphrodite!<h1>
</div>;
)
}
}
Stylotron

import React, { Component } from 'react';
import { styled } from 'styletron-react';
const Wrapper = styled('div', {
backgroundColor: 'black'
})
const Title = styled('h1', {
color: 'white'
})
class App extends Component {
render() {
return (
<Wrapper>
<Title>Hello Styletron!<Titleh1>
</Wrapper>;
)
}
}
Это действительно простые примеры, демонстрирующие основные функции. Само собой, все библиотеки имеют гораздо больше функциональных возможностей.
Несколько полезных ссылок
- Обо всех возможностях технологии можно почитать тут;
- Полный список библиотек;
- Если CSS-in-JS не катит, посмотрите на CSS Modules;
- 21 совет профессионалов в CSS.
Комментарии