5 способов стилизовать ваше приложение React с помощью CSS (2021)

Когда дело доходит до стиля вашего приложения React, у вас есть масса различных вариантов. Что вы выбираете?

Я разбил 5 основных способов, которыми вы должны выбирать при написании CSS в своем приложении React.

Не существует способа №1 для написания стилей в React для каждого проекта. Каждый проект уникален и имеет разные потребности.

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

Давайте начнем!

Хотите стать профессиональным разработчиком React, создавая потрясающие проекты? Ознакомьтесь с Учебным курсом React.

Что мы будем кодировать

Чтобы увидеть, как код для каждого из этих подходов к стилю сравнивается друг с другом, мы создадим один и тот же пример: простую, но чистую карточку с отзывами.

Хотите кодировать вместе с каждым из этих примеров? Перейдите на react.new, чтобы мгновенно создать новое приложение React ✨

Встроенные стили

Встроенные стили — это самый прямой способ стилизовать любое приложение React.

Встроенные элементы стиля не требуют создания отдельной таблицы стилей.

Стиль, применяемый непосредственно к элементам, по сравнению со стилями в таблице стилей, также имеет более высокий приоритет. Это означает, что они «отменяют» другие правила стиля, которые могут быть применены к элементу.

Вот наша карточка отзыва со встроенными стилями:

export default function App() {
  return (
    <section
      style={{
        fontFamily: '-apple-system',
        fontSize: "1rem",
        fontWeight: 1.5,
        lineHeight: 1.5,
        color: "#292b2c",
        backgroundColor: "#fff",
        padding: "0 2em"
      }}
    >
      <div
        style={{
          textAlign: "center",
          maxWidth: "950px",
          margin: "0 auto",
          border: "1px solid #e6e6e6",
          padding: "40px 25px",
          marginTop: "50px"
        }}
      >
        <img
          src="https://randomuser.me/api/portraits/women/48.jpg"
          alt="Tammy Stevens"
          style={{
            margin: "-90px auto 30px",
            width: "100px",
            borderRadius: "50%",
            objectFit: "cover",
            marginBottom: "0"
          }}
        />
        <div>
          <p
            style={{
              lineHeight: 1.5,
              fontWeight: 300,
              marginBottom: "25px",
              fontSize: "1.375rem"
            }}
          >
            This is one of the best developer blogs on the planet! I read it daily to improve my skills.
          </p>
        </div>
        <p
          style={{
            marginBottom: "0",
            fontWeight: 600,
            fontSize: "1rem"
          }}
        >
          Tammy Stevens
          <span style={{ fontWeight: 400 }}> · Front End Developer</span>
        </p>
      </div>
    </section>
  );
}

Несмотря на несколько быстрых преимуществ, встроенные стили являются приемлемым выбором только для очень маленьких приложений. Трудности со встроенными стилями становятся очевидными по мере того, как ваша кодовая база увеличивается даже незначительно.

Как видно из приведенного выше примера кода, даже такой небольшой компонент становится очень громоздким, если все стили встроены.

Однако есть один быстрый прием — поместить встроенные стили в повторно используемые переменные, которые можно хранить в отдельном файле:

const styles = {
  section: {
    fontFamily: "-apple-system",
    fontSize: "1rem",
    fontWeight: 1.5,
    lineHeight: 1.5,
    color: "#292b2c",
    backgroundColor: "#fff",
    padding: "0 2em"
  },
  wrapper: {
    textAlign: "center",
    maxWidth: "950px",
    margin: "0 auto",
    border: "1px solid #e6e6e6",
    padding: "40px 25px",
    marginTop: "50px"
  },
  avatar: {
    margin: "-90px auto 30px",
    width: "100px",
    borderRadius: "50%",
    objectFit: "cover",
    marginBottom: "0"
  },
  quote: {
    lineHeight: 1.5,
    fontWeight: 300,
    marginBottom: "25px",
    fontSize: "1.375rem"
  },
  name: {
    marginBottom: "0",
    fontWeight: 600,
    fontSize: "1rem"
  },
  position: { fontWeight: 400 }
};

export default function App() {
  return (
    <section style={styles.section}>
      <div style={styles.wrapper}>
        <img
          src="https://randomuser.me/api/portraits/women/48.jpg"
          alt="Tammy Stevens"
          style={styles.avatar}
        />
        <div>
          <p style={styles.quote}>
            This is one of the best developer blogs on the planet! I read it
            daily to improve my skills.
          </p>
        </div>
        <p style={styles.name}>
          Tammy Stevens
          <span style={styles.position}> · Front End Developer</span>
        </p>
      </div>
    </section>
  );
}

Несмотря на это улучшение, встроенные стили не имеют ряда важных функций, которые могла бы обеспечить любая простая таблица стилей CSS.

Например, вы не можете написать анимацию, стили для вложенных элементов (т.е. все дочерние элементы, первый дочерний элемент, последний дочерний элемент), псевдоклассы (т.е. :hover) и псевдоэлементы (::first-line) для именования немного.

Если вы создаете прототип приложения, встроенные стили отлично подходят. Однако по мере того, как вы продвигаетесь вперед, вам нужно будет переключиться на другой вариант стиля CSS, чтобы предоставить вам основные функции CSS.

Плюсы: 👍

  • Самый быстрый способ написать стили
  • Подходит для прототипирования (напишите встроенные стили, а затем перейдите в таблицу стилей)
  • Имеет большие предпочтения (может переопределять стили из таблицы стилей)

Минусы: 👎

  • Утомительно преобразовывать простой CSS во встроенные стили.
  • Множество встроенных стилей делают JSX нечитаемым
  • Вы не можете использовать основные функции CSS, такие как анимация, селекторы и т. д.
  • Плохо масштабируется

Обычный CSS

Вместо использования встроенных стилей обычно импортируют таблицу стилей CSS для стилизации элементов компонента.

Написание CSS в таблице стилей, вероятно, является наиболее распространенным и базовым подходом к стилизации приложения React, но его не следует так просто игнорировать.

Написание стилей в «простых» таблицах стилей CSS постоянно совершенствуется благодаря растущему набору функций, доступных в стандарте CSS.

Сюда входят такие функции, как переменные CSS для хранения динамических значений, всевозможные расширенные селекторы для точного выбора дочерних элементов и новые псевдоклассы, такие как :is и :where.

Вот наша карточка с отзывами, написанная на простом CSS и импортированная в верхнюю часть нашего приложения React:

/* src/styles.css */

body {
  font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  margin: 0;
  font-size: 1rem;
  font-weight: 1.5;
  line-height: 1.5;
  color: #292b2c;
  background-color: #fff;
}
.testimonial {
  margin: 0 auto;
  padding: 0 2em;
}
.testimonial-wrapper {
  text-align: center;
  max-width: 950px;
  margin: 0 auto;
  border: 1px solid #e6e6e6;
  padding: 40px 25px;
  margin-top: 50px;
}
.testimonial-quote p {
  line-height: 1.5;
  font-weight: 300;
  margin-bottom: 25px;
  font-size: 1.375rem;
}
.testimonial-avatar {
  margin: -90px auto 30px;
  width: 100px;
  border-radius: 50%;
  object-fit: cover;
  margin-bottom: 0;
}
.testimonial-name {
  margin-bottom: 0;
  font-weight: 600;
  font-size: 1rem;
}
.testimonial-name span {
  font-weight: 400;
}
// src/App.js

import "./styles.css";

export default function App() {
  return (
    <section className="testimonial">
      <div className="testimonial-wrapper">
        <img
          className="testimonial-avatar"
          src="https://randomuser.me/api/portraits/women/48.jpg"
          alt="Tammy Stevens"
        />
        <div className="testimonial-quote">
          <p>
            This is one of the best developer blogs on the planet! I read it daily to improve my skills.
          </p>
        </div>
        <p className="testimonial-name">
          Tammy Stevens<span> · Front End Developer</span>
        </p>
      </div>
    </section>
  );
}

Обратите внимание, что для нашей карточки с отзывами мы создаем классы, которые будут применяться к каждому отдельному элементу. Все эти классы начинаются с одного и того же имени testimonial-.

CSS, написанный в таблице стилей, — отличный первый выбор для вашего приложения. В отличие от встроенных стилей, он может стилизовать ваше приложение практически любым способом, который вам нужен.

Одной небольшой проблемой может быть ваше соглашение об именах. Когда у вас есть очень хорошо разработанное приложение, становится сложнее придумывать уникальные имена классов для ваших элементов, особенно когда у вас есть 5 div, заключенных друг в друга.

Если у вас нет соглашения об именах, в котором вы уверены (например, БЭМ), можно легко допустить ошибку, а также создать несколько классов с одним и тем же именем, что приведет к конфликтам.

Кроме того, написание обычного CSS может быть более подробным и повторяющимся, чем в более новых инструментах, таких как SASS/SCSS. В результате написание стилей в CSS может занять немного больше времени, чем в таких инструментах, как SCSS или библиотека CSS-in-JS.

Кроме того, важно отметить, что, поскольку CSS распространяется на все дочерние элементы, если вы применяете таблицу стилей CSS к компоненту, она не ограничивается только этим компонентом. Все его объявленные правила будут переданы любым элементам, которые являются дочерними элементами вашего стилизованного компонента.

Если вы хорошо разбираетесь в CSS, это, безусловно, хороший выбор для стилизации любого приложения React.

При этом существует ряд библиотек CSS, которые дают нам всю мощь CSS с меньшим количеством кода и включают множество дополнительных функций, которых CSS никогда не будет иметь самостоятельно (например, стили с областью действия и автоматические префиксы поставщиков).

Плюсы: 👍

  • Дает нам все инструменты современного CSS (переменные, расширенные селекторы, новые псевдоклассы и т. д.)
  • Помогает нам очистить наши файлы компонентов от встроенных стилей

Минусы: 👎

  • Необходимо настроить префикс поставщика, чтобы последние функции работали для всех пользователей.
  • Требует больше набора текста и шаблонов, чем другие библиотеки CSS (например, SASS)
  • Любая таблица стилей распространяется на компонент и все дочерние элементы; не ограничен
  • Необходимо использовать надежное соглашение об именах, чтобы стили не конфликтовали.

SASS/SCSS

Что такое САСС? SASS — это аббревиатура, расшифровывающаяся как Syntactically Awesome Style Sheets.

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

SASS позволяет нам писать стили в таблицах стилей двух разных типов с расширениями .scss и .sass.

Синтаксис стилей SCSS аналогичен синтаксису обычного CSS, однако стили SASS не требуют использования открывающих и закрывающих скобок при написании правил стиля.

Вот краткий пример таблицы стилей SCSS с некоторыми вложенными стилями:

/* styles.scss */

nav {
  ul {
    margin: 0;
    padding: 0;
    list-style: none;
  }

  li { display: inline-block; }

  a {
    display: block;
    padding: 6px 12px;
    text-decoration: none;
  }
}

Сравните это с тем же кодом, написанным в таблице стилей SASS:

/* styles.sass */

nav
  ul
    margin: 0
    padding: 0
    list-style: none

  li
    display: inline-block

  a
    display: block
    padding: 6px 12px
    text-decoration: none

Поскольку это не обычный CSS, его необходимо скомпилировать из SASS в обычный CSS. Для этого в наших проектах React вы можете использовать такую ​​библиотеку, как node-sass.

Если вы используете проект Create React App, чтобы начать использовать файлы .scss и .sass, вы можете установить node-sass с помощью npm:

npm install node-sass

Вот наша карточка с отзывами, оформленная с помощью SCSS:

/* src/styles.scss */

$font-stack: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
$text-color: #292b2c;

%font-basic {
  font-size: 1rem;
}

body {
  @extend %font-basic;
  font-family: $font-stack;
  color: $text-color;
  margin: 0;
  font-size: 1rem;
  font-weight: 1.5;
  line-height: 1.5;
  background-color: #fff;
}

/* unchanged rules skipped */

.testimonial-name {
  @extend %font-basic;
  margin-bottom: 0;
  font-weight: 600;

  span {
    font-weight: 400;
  }
}

Эти стили дают нам следующие возможности: переменные, расширяющие стили и вложенные стили.

Переменные. Вы можете использовать динамические значения, записывая переменные, как и в JavaScript, объявляя их с помощью $ в начале.

Есть две переменные, которые можно использовать в нескольких правилах: $font-stack, $text-color.

Расширение/Наследование. Вы можете добавлять правила стиля, расширяя их. Чтобы расширить правила, вы создаете свой собственный селектор, который можно повторно использовать как переменную. Имена правил, которые вы хотите расширить, начинаются с %.

Переменная %font-basic наследуется по правилам body и .testimonial-name.

Вложенность. Вместо написания нескольких правил, начинающихся с одного и того же селектора, вы можете их вложить.

В .testimonial-name мы используем вложенный селектор для нацеливания на элемент span внутри него.

Вы можете найти рабочую версию приложения React со SCSS здесь.

Плюсы: 👍

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

Минусы: 👎

  • Как и обычный CSS, стили являются глобальными и не привязаны ни к одному компоненту.
  • Таблицы стилей CSS начинают включать в себя ряд функций, которые были исключительно в SASS, например, переменные CSS (не обязательно минус, но стоит отметить).
  • SASS/SCSS часто требует настройки, например, установки библиотеки Node node-sass

CSS-модули

Модули CSS — это еще одна небольшая альтернатива чему-то вроде CSS или SASS.

Что хорошо в модулях CSS, так это то, что их можно использовать как с обычным CSS, так и с SASS. Кроме того, если вы используете приложение Create React, вы можете начать использовать модули CSS вообще без настройки.

Вот наше приложение, написанное с помощью модулей CSS:

/* src/styles.module.css */

body {
  font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  margin: 0;
  font-size: 1rem;
  font-weight: 1.5;
  line-height: 1.5;
  color: #292b2c;
  background-color: #fff;
}

/* styles skipped */

.testimonial-name span {
  font-weight: 400;
}
import styles from './styles.module.css';

export default function App() {
  return (
    <section className={styles.testimonial}>
      <div className={styles['testimonial-wrapper']}>
        <img
          src="https://randomuser.me/api/portraits/women/48.jpg"
          alt="Tammy Stevens"
          className={styles['testimonial-avatar']}
        />
        <div>
          <p className={styles['testimonial-quote']}>
            This is one of the best developer blogs on the planet! I read it
            daily to improve my skills.
          </p>
        </div>
        <p className={styles['testimonial-name']}>
          Tammy Stevens
          <span> · Front End Developer</span>
        </p>
      </div>
    </section>
  );
}

Наш файл CSS имеет имя .module перед расширением .css. Любой файл модуля CSS должен иметь имя «модуль» и заканчиваться соответствующим расширением (если мы используем CSS или SASS/SCSS).

Что интересно отметить, если мы посмотрим на приведенный выше код, так это то, что модули CSS написаны так же, как обычный CSS, но импортируются и используются так, как если бы они были созданы как объекты (встроенные стили).

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

Наши сгенерированные HTML-элементы будут выглядеть так:

<p class="_styles__testimonial-name_309571057">
  Tammy Stevens
</p>

Кроме того, CSS-модули решают проблему глобального масштаба в CSS. По сравнению с нашими обычными таблицами стилей CSS, CSS, объявленный с использованием модулей для отдельных компонентов, не будет каскадироваться на дочерние компоненты.

Поэтому модули CSS лучше использовать вместо CSS и SASS, чтобы убедиться, что классы не конфликтуют, и написать предсказуемые стили, применимые только к тому или иному компоненту.

Плюсы: 👍

  • Стили привязаны к тому или иному компоненту (в отличие от CSS/SASS)
  • Уникальные сгенерированные имена классов гарантируют отсутствие конфликта стилей
  • Можно использовать их сразу без настройки в проектах CRA
  • Может использоваться с SASS/CSS

Минусы: 👎

  • Может быть сложно ссылаться на имена классов
  • Может потребоваться обучение использованию стилей CSS, таких как свойства объекта.

CSS-в-JS

Подобно тому, как React позволил нам писать HTML как JavaScript с помощью JSX, CSS-in-JS сделал нечто подобное с CSS.

CSS-in-JS позволяет нам писать стили CSS непосредственно в файлах javascript (.js) наших компонентов.

Он не только позволяет вам писать правила стилей CSS без создания единого файла .css, но и эти стили применимы к отдельным компонентам.

Другими словами, вы можете добавлять, изменять или удалять CSS без каких-либо сюрпризов. Изменение стилей одного компонента не повлияет на стили остальной части вашего приложения.

CSS-in-JS часто использует специальный тип функции JavaScript, называемый теговым литералом шаблона. Что хорошо в этом, так это то, что мы все еще можем писать простые правила стиля CSS прямо в нашем JS!

Вот краткий пример популярной библиотеки CSS-in-JS Styled Components:

import styled from "styled-components";

const Button = styled.button`
  color: limegreen;
  border: 2px solid limegreen;
  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border-radius: 3px;

  &:hover {
    opacity: 0.9;
  }
`;

export default function App() {
  return (
    <div>
      <Button>Click me</Button>
    </div>
  );
}

Обратите внимание на несколько вещей здесь:

  1. Вы можете писать обычные стили CSS, но можете включать вложенные стили и псевдоклассы (например, при наведении курсора).
  2. Вы можете связать стили с любым допустимым элементом HTML, например с элементом кнопки выше (см. styled.button).
  3. Вы можете создавать новые компоненты с этими связанными стилями. Посмотрите, как Button используется в нашем компоненте приложения.

Поскольку это компонент, можно ли передать реквизит? Да! Мы можем экспортировать этот компонент и использовать его в любом месте нашего приложения, а также придать ему динамические функции с помощью свойств.

Допустим, вам нужен перевернутый вариант Button выше с перевернутым фоном и текстом. Без проблем.

Передайте реквизит inverted нашей второй кнопке, и в Button вы сможете получить доступ ко всем реквизитам, переданным компоненту, используя синтаксис ${} с внутренней функцией.

import styled from "styled-components";

const Button = styled.button`
  background: ${props => props.inverted ? "limegreen" : "white"};
  color: ${props => props.inverted ? "white" : "limegreen"};
  border: 2px solid limegreen;
  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border-radius: 3px;

  &:hover {
    opacity: 0.9;
  }
`;

export default function App() {
  return (
    <div>
      <Button>Click me</Button>
      <Button inverted>Click me</Button>
    </div>
  );
}

В возврате функции вы можете выбрать реквизит inverted и использовать троицу для условного определения цвета фона и текста.

Вот результат:

Существует гораздо больше преимуществ использования библиотеки CSS-in-JS для оформления ваших приложений React (слишком много, чтобы охватить здесь), некоторые из которых я перечислю ниже.

Обязательно ознакомьтесь с двумя самыми популярными библиотеками CSS-in-JS для React: Emotion и Styled Components.

Одним из недостатков использования библиотек CSS-in-JS является добавление дополнительной библиотеки в ваш проект. Тем не менее, я бы сказал, что это стоит улучшенного опыта разработчика, который вы получаете при стилизации своих приложений React по сравнению с простым CSS.

Плюсы: 👍

  • CSS-in-JS предсказуем — стили привязаны к отдельным компонентам.
  • Поскольку наш CSS теперь JS, мы можем экспортировать, повторно использовать и даже расширять наши стили с помощью свойств.
  • Библиотеки CSS-in-JS обеспечивают отсутствие конфликтов стилей, генерируя уникальные имена классов для написанных вами стилей.
  • Не нужно сосредотачиваться на соглашениях об именах для ваших классов, просто напишите стили!

Минусы: 👎

  • В отличие от обычного CSS, вам нужно будет установить одну или несколько сторонних библиотек JavaScript, что добавит веса вашему созданному проекту.

Вывод

Обратите внимание, что в это сравнение я не включил библиотеки компонентов. Я хотел сосредоточиться в первую очередь на различных способах самостоятельного составления стилей.

Имейте в виду, что выбор библиотеки с готовыми компонентами и стилями, такими как Material UI или Ant Design (назовем пару), является абсолютно правильным выбором для вашего проекта.

Я надеюсь, что это руководство дало вам хорошее представление о том, как стилизовать ваши приложения React, а также о том, какой подход выбрать для вашего следующего проекта.

Хотите остальные? Присоединяйтесь к React Bootcamp

Учебный курс React объединяет все, что вам нужно знать об изучении React, в один комплексный пакет, включая видео, шпаргалки и специальные бонусы.

Получите инсайдерскую информацию, которую уже использовали сотни разработчиков, чтобы освоить React, найти работу своей мечты и взять под контроль свое будущее:

Нажмите здесь, чтобы получить уведомление, когда он откроется