Что нужно знать о CSS в языке JS: плюсы и минусы

Что-то слышали о 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>;
        )
    }
}

Это действительно простые примеры, демонстрирующие основные функции. Само собой, все библиотеки имеют гораздо больше функциональных возможностей.

Несколько полезных ссылок

Перевод статьи Indrek Lasn

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ