Работа с CSS Modules в React-приложении
Пробуем использовать CSS-модули.
Для начала создаем новый проект React (с помощью утилиты create-react-app). Ничего особенного, всего один компонент PokemonCard. У этого компонента есть собственный файл стилей, подключенный обычным импортом (
Если попробовать импортировать из этого файла стили в виде объекта, как обещались мне статьи по CSS-модулям, то ничего не получится (в консоль выводится пустой объект, созданных CSS-классов там нет).
Посмотреть:
https://codesandbox.io/s/css-modules-start-react-junior-264oh?file=/src/components/PokemonCard/index.js:0-56
Нужно ли что-то настраивать? Нет, не нужно.
create-react-app из коробки поддерживает использование CSS модулей. Для этого просто нужно добавлять к css-файлам суффикс module. То есть вместо style.css должно быть style.module.css.
Посмотреть:
https://codesandbox.io/s/css-modules-1-react-junior-uhdec?file=/src/components/PokemonCard/index.js:0-63
Теперь в консоль выводится объект формата:
Если все же хочется копнуть поглубже или использовать модули вне create-react-app, то вся магия заключена в css-loader для webpack. У него есть опция modules, которую просто нужно включить.
#стили #примерыкода
Пробуем использовать CSS-модули.
Для начала создаем новый проект React (с помощью утилиты create-react-app). Ничего особенного, всего один компонент PokemonCard. У этого компонента есть собственный файл стилей, подключенный обычным импортом (
import style.css
).Если попробовать импортировать из этого файла стили в виде объекта, как обещались мне статьи по CSS-модулям, то ничего не получится (в консоль выводится пустой объект, созданных CSS-классов там нет).
Посмотреть:
https://codesandbox.io/s/css-modules-start-react-junior-264oh?file=/src/components/PokemonCard/index.js:0-56
Нужно ли что-то настраивать? Нет, не нужно.
create-react-app из коробки поддерживает использование CSS модулей. Для этого просто нужно добавлять к css-файлам суффикс module. То есть вместо style.css должно быть style.module.css.
Посмотреть:
https://codesandbox.io/s/css-modules-1-react-junior-uhdec?file=/src/components/PokemonCard/index.js:0-63
Теперь в консоль выводится объект формата:
{То есть каждому имени класса, которое было объявлено в файле стилей, сопоставлена уникальная строка. Эту строку нужно подставить вместо обычного класса.
card: "_src_components_PokemonCard_style_module__card",
cardImg: "_src_components_PokemonCard_style_module__cardImg",
cardHeader: "_src_components_PokemonCard_style_module__cardHeader",
cardData: "_src_components_PokemonCard_style_module__cardData",
cardFooter: "_src_components_PokemonCard_style_module__cardFooter,
}
className="cardImg"превращается в
className={styles.cardImg}Оказалось, что все очень просто и даже не нужно ничего настраивать.
Если все же хочется копнуть поглубже или использовать модули вне create-react-app, то вся магия заключена в css-loader для webpack. У него есть опция modules, которую просто нужно включить.
#стили #примерыкода
Изолированность CSS-модулей
Демонстрация изолированности модулей друг от друга:
https://codesandbox.io/s/css-modules-2-react-junior-z002o?file=/src/App.js
В приложении есть два компонента - ProductCard и UserCard. В их файлах стилей объявлены абсолютно одинаковые классы - .card, .title, .description, .img.
Но так как мы заменяем эти классы на уникальные строки, никаких конфликтов стилей не происходит.
#стили #примерыкода
Демонстрация изолированности модулей друг от друга:
https://codesandbox.io/s/css-modules-2-react-junior-z002o?file=/src/App.js
В приложении есть два компонента - ProductCard и UserCard. В их файлах стилей объявлены абсолютно одинаковые классы - .card, .title, .description, .img.
Но так как мы заменяем эти классы на уникальные строки, никаких конфликтов стилей не происходит.
#стили #примерыкода
CSS-модули + препроцессоры
CSS-модули можно сочетать с CSS-препроцессорами.
В create-react-app для этого могут понадобиться дополнительные настройки. Например, чтобы использовать SCSS, пришлось установить пакет node-sass, но дальше все пошло как по маслу - достаточно было поменять расширение файла.
#стили
CSS-модули можно сочетать с CSS-препроцессорами.
В create-react-app для этого могут понадобиться дополнительные настройки. Например, чтобы использовать SCSS, пришлось установить пакет node-sass, но дальше все пошло как по маслу - достаточно было поменять расширение файла.
#стили
Примеси в CSS-модулях
В CSS-модулях даже есть примеси (композиция классов). Один класс можно включить в другой с помощью свойства composes.
Смотреть:
https://codesandbox.io/s/css-modules-3-react-junior-mxojc?file=/src/styles.module.css
Есть два блока - .block1 и .block2 со своими стилями, а также класс .redBorder, который добавляет красную рамку. Добавляем рамку каждому блоку:
Можно даже примешивать классы из других файлов с помощью ключевого слова from:
К сожалению, codesandbox не хочет это демонстрировать.
#стили #примерыкода
В CSS-модулях даже есть примеси (композиция классов). Один класс можно включить в другой с помощью свойства composes.
Смотреть:
https://codesandbox.io/s/css-modules-3-react-junior-mxojc?file=/src/styles.module.css
Есть два блока - .block1 и .block2 со своими стилями, а также класс .redBorder, который добавляет красную рамку. Добавляем рамку каждому блоку:
.redBorder {
border: 5px solid red;
}
.block1 {
composes: redBorder;
width: 600px;
}
.block2 {
composes: redBorder;
width: 300px;
}
Можно даже примешивать классы из других файлов с помощью ключевого слова from:
composes: className from "./style.css";
К сожалению, codesandbox не хочет это демонстрировать.
#стили #примерыкода
CodeSandbox
CSS Modules 3. React Junior - CodeSandbox
CSS Modules 3. React Junior by furrycat.web using react, react-dom, react-scripts
Итак, CSS-модули оказались очень простой и скучной вещью, поэтому завязываем с ними.
Подведя итог: модули - это неплохо, но не то, чтобы прям прорыв.
Из недостатков: требуются настройки для работы с ними, дополнительная сборка (интересно, это достаточно эффективно?) и конечный DOM получается довольно сложным из-за уникальных имен, но БЭМ тоже здорово перегружает верстку.
Из достоинств: исходный код становится проще, хотя ничто не помешает его снова усложнить, если руки достаточно кривые. Еще есть примеси.
#стили
Подведя итог: модули - это неплохо, но не то, чтобы прям прорыв.
Из недостатков: требуются настройки для работы с ними, дополнительная сборка (интересно, это достаточно эффективно?) и конечный DOM получается довольно сложным из-за уникальных имен, но БЭМ тоже здорово перегружает верстку.
Из достоинств: исходный код становится проще, хотя ничто не помешает его снова усложнить, если руки достаточно кривые. Еще есть примеси.
#стили
Styled Components
Библиотека Styled Components позволяет создавать React-компоненты сразу со стилями. Тут акцент именно на стилях, у этих компонентов нет никакой логики, только оформление.
Пример создания компонента на картинке. Для этого используется синтаксис шаблонных строк. После styled указывается имя тега, который будет корневым элементом компонента, в данном случае это кнопка button. А дальше в обратных кавычках пишется привычный CSS.
Теперь компонент Button можно использовать привычным образом внутри React-приложения.
Смотреть: https://codesandbox.io/s/styled-components-1-react-junior-kkncf?file=/src/App.js
#стили #styledcomponents #примерыкода
Библиотека Styled Components позволяет создавать React-компоненты сразу со стилями. Тут акцент именно на стилях, у этих компонентов нет никакой логики, только оформление.
Пример создания компонента на картинке. Для этого используется синтаксис шаблонных строк. После styled указывается имя тега, который будет корневым элементом компонента, в данном случае это кнопка button. А дальше в обратных кавычках пишется привычный CSS.
Теперь компонент Button можно использовать привычным образом внутри React-приложения.
Смотреть: https://codesandbox.io/s/styled-components-1-react-junior-kkncf?file=/src/App.js
#стили #styledcomponents #примерыкода
Передача пропсов в Styled Components
На первый взгляд похоже, что styled - это просто какая-то вариация document.createElement, которая сразу добавляет созданному элементу стили. Но это все-так компонент React, а значит, мы можем передать ему пропсы.
Чтобы свойство было динамическим (основывалось на значении пропсов), нужно оформить его как функцию. А чтобы вставить функцию в шаблонную строку, нужно использовать синтаксис интерполяции.
С помощью интерполяции можно вставлять не только значение свойств, но и целиком правило (имя свойства + значение), и даже несколько правил. В общем, так как стили передаются в виде строки, любой ее фрагмент можно заменить на динамическое выражение.
Вообще для подобных ситуаций (когда нужно сделать динамическими целые правила), предназначена функция css из того же пакета, которая тоже является теговым шаблоном.
Да, мы используем одну функцию-тег (css) внутри другой (styled.button).
Смотреть:
https://codesandbox.io/s/styled-components-2-react-junior-6zw60?file=/src/App.js
Подробнее о теговых шаблонах на MDN
#стили #styledcomponents #примерыкода
На первый взгляд похоже, что styled - это просто какая-то вариация document.createElement, которая сразу добавляет созданному элементу стили. Но это все-так компонент React, а значит, мы можем передать ему пропсы.
Чтобы свойство было динамическим (основывалось на значении пропсов), нужно оформить его как функцию. А чтобы вставить функцию в шаблонную строку, нужно использовать синтаксис интерполяции.
height: ${(props) => (props.size || 38) + "px"};
С помощью интерполяции можно вставлять не только значение свойств, но и целиком правило (имя свойства + значение), и даже несколько правил. В общем, так как стили передаются в виде строки, любой ее фрагмент можно заменить на динамическое выражение.
${props => props.border && "border-color: " + props.border};
Вообще для подобных ситуаций (когда нужно сделать динамическими целые правила), предназначена функция css из того же пакета, которая тоже является теговым шаблоном.
Да, мы используем одну функцию-тег (css) внутри другой (styled.button).
Смотреть:
https://codesandbox.io/s/styled-components-2-react-junior-6zw60?file=/src/App.js
Подробнее о теговых шаблонах на MDN
#стили #styledcomponents #примерыкода
CodeSandbox
Styled Components 2. React Junior - CodeSandbox
Styled Components 2. React Junior by furrycat.web using react, react-dom, react-scripts, styled-components
Медиа-запросы и динамические состояния в Styled Components
Сразу же возник вопрос, как определять различные динамические состояния стилизованного компонента (ховеры, адаптив). Очень просто, прямо в шаблонной строке стилей, которую мы отдаем в функцию styled.tagName:
Смотреть: https://codesandbox.io/s/styled-components-3-react-junior-cte6s?file=/src/App.js&resolutionWidth=400&resolutionHeight=130
#стили #styledcomponents #примерыкода
Сразу же возник вопрос, как определять различные динамические состояния стилизованного компонента (ховеры, адаптив). Очень просто, прямо в шаблонной строке стилей, которую мы отдаем в функцию styled.tagName:
Смотреть: https://codesandbox.io/s/styled-components-3-react-junior-cte6s?file=/src/App.js&resolutionWidth=400&resolutionHeight=130
#стили #styledcomponents #примерыкода
Наследование в StyledComponent
Можно создавать новый стилизованный компонент, который будет наследовать стили от другого компонента. Для этого нужно передать родительский компонент в функцию styled и получить новую функцию-тег, которой можно передать новые стили.
#стили #styledcomponents
Можно создавать новый стилизованный компонент, который будет наследовать стили от другого компонента. Для этого нужно передать родительский компонент в функцию styled и получить новую функцию-тег, которой можно передать новые стили.
#стили #styledcomponents
Внезапно оказалось, что styled.div/styled.a и прочие свойства функции styled - это не более чем псевдонимы. Нужный тег (или компонент) можно передать прямо в функцию styled и получить нужную шаблонную строку.
#важно #стили #styledcomponents
#важно #стили #styledcomponents
StyledComponents с кастомными React-компонентами
До сих пор мы создавали стилизованные компоненты только на базе обычных HTML-тегов. Оказывается, можно использовать для этого и React-компоненты.
Нужно просто передать кастомный компонент в функцию styled, и он будет использован как базовый.
Важно: внутри кастомного компонента обязательно нужно использовать проп className, иначе стили не применятся.
Смотреть: https://codesandbox.io/s/styled-components-5-react-junior-yeds8?file=/src/App.js
Вот мы ненароком и узнали, как работают styledComponents. Они генерируют уникальное имя класса, к которому и привязываются стили (похоже на CSS Модули).
#стили #styledcomponents #примерыкода #важно
До сих пор мы создавали стилизованные компоненты только на базе обычных HTML-тегов. Оказывается, можно использовать для этого и React-компоненты.
Нужно просто передать кастомный компонент в функцию styled, и он будет использован как базовый.
Важно: внутри кастомного компонента обязательно нужно использовать проп className, иначе стили не применятся.
Смотреть: https://codesandbox.io/s/styled-components-5-react-junior-yeds8?file=/src/App.js
Вот мы ненароком и узнали, как работают styledComponents. Они генерируют уникальное имя класса, к которому и привязываются стили (похоже на CSS Модули).
#стили #styledcomponents #примерыкода #важно
CodeSandbox
Styled Components 5. React Junior - CodeSandbox
Styled Components 5. React Junior by furrycat.web using react, react-dom, react-scripts, styled-components
Изменение тега
При создании компонента мы сразу определяем тег, который будет его представлять: styled.div или styled.button. А что делать, если одинаковые стили нужны и для кнопки, и для ссылки? Дублировать их?
К счастью, нет. Тег, к которому будут применены стили можно подменить динамически с помощью пропа as.
В него можно передать либо валидное имя тега в виде строки, либо даже имя кастомного React-компонента. Главное внутри этого компонента использовать полученный проп className, иначе стили не будут применены.
Смотреть: https://codesandbox.io/s/styled-components-4-react-junior-7xpq2?file=/src/App.js
#стили #styledcomponents #примерыкода
При создании компонента мы сразу определяем тег, который будет его представлять: styled.div или styled.button. А что делать, если одинаковые стили нужны и для кнопки, и для ссылки? Дублировать их?
К счастью, нет. Тег, к которому будут применены стили можно подменить динамически с помощью пропа as.
В него можно передать либо валидное имя тега в виде строки, либо даже имя кастомного React-компонента. Главное внутри этого компонента использовать полученный проп className, иначе стили не будут применены.
Смотреть: https://codesandbox.io/s/styled-components-4-react-junior-7xpq2?file=/src/App.js
#стили #styledcomponents #примерыкода
CodeSandbox
Styled Components 4. React Junior - CodeSandbox
Styled Components 4. React Junior by furrycat.web using react, react-dom, react-scripts, styled-components
Глобальные стили
В каждом приложении есть глобальные стили вроде семейства шрифтов или сброса стилей. Казалось бы, их невозможно оформить в виде компонента, но у StyledComponents другое мнение.
Чтобы определить глобальные стили, нужно создать новый стилизованный компонент с помощью функции createGlobalStyle, а затем вставить его наверху проекта.
#стили #styledcomponents #примерыкода
В каждом приложении есть глобальные стили вроде семейства шрифтов или сброса стилей. Казалось бы, их невозможно оформить в виде компонента, но у StyledComponents другое мнение.
Чтобы определить глобальные стили, нужно создать новый стилизованный компонент с помощью функции createGlobalStyle, а затем вставить его наверху проекта.
#стили #styledcomponents #примерыкода
Создание анимации с помощью StyledComponents
ДЛя создания анимаций используется теговая функция keyframes из пакета styled-components. Она принимает тот же самый CSS-код, который вы обычно помещаете в конструкцию @keyframes, а возвращает имя созданное анимации.
Это имя нужно вставить в CSS-свойство animation-name в вашем стилизованном компоненте.
#стили #styledcomponents #примерыкода
ДЛя создания анимаций используется теговая функция keyframes из пакета styled-components. Она принимает тот же самый CSS-код, который вы обычно помещаете в конструкцию @keyframes, а возвращает имя созданное анимации.
Это имя нужно вставить в CSS-свойство animation-name в вашем стилизованном компоненте.
#стили #styledcomponents #примерыкода
Настройка атрибутов
Так как StyledComponents - это настоящие компоненты, у них могут быть атрибуты. Некоторые из них мы устанавливаем с помощью пропсов, а другие, которые не изменяются, можно установить сразу.
Для этого предназначен метод attrs, которые принимает объект с именами и значениями нужных атрибутов.
#стили #styledcomponents #примерыкода
Так как StyledComponents - это настоящие компоненты, у них могут быть атрибуты. Некоторые из них мы устанавливаем с помощью пропсов, а другие, которые не изменяются, можно установить сразу.
Для этого предназначен метод attrs, которые принимает объект с именами и значениями нужных атрибутов.
#стили #styledcomponents #примерыкода
Первое знакомство со StyledComponents состоялось. Источником знаний выступили в основном статьи, первыми попавшиеся в поисковике. Из самых подробных (на русском):
- Знакомство со Styled components
- Как использовать стилизованные компоненты в React
Пора переходить к фундаментальным источникам: документации (англ.).
А вот здесь есть песочница для экспериментов со стилизованными компонентами.
#ссылки #стили #styledcomponents
- Знакомство со Styled components
- Как использовать стилизованные компоненты в React
Пора переходить к фундаментальным источникам: документации (англ.).
А вот здесь есть песочница для экспериментов со стилизованными компонентами.
#ссылки #стили #styledcomponents
Frontend Stuff
Знакомство со Styled components
Что такое Styled components и как его использовать.
Пропсы и атрибуты
👉 Все пропсы, которые являются стандартными HTML-атрибутами пробрасываются до HTML-контейнера стилизованного компонента.
👉 Можно установить атрибуты прямо внутри конструктора стилизованного компонента с помощью метода attrs, который может принимать как объект, так и функцию.
👉 Если один стилизованный компонент "наследует" от другого, то стили и атрибуты наследника переопределяют стили и атрибуты родителя (логично).
https://codesandbox.io/s/styled-components-5-react-junior-l4cn6?file=/src/App.js
#стили #styledcomponents #документация
👉 Все пропсы, которые являются стандартными HTML-атрибутами пробрасываются до HTML-контейнера стилизованного компонента.
👉 Можно установить атрибуты прямо внутри конструктора стилизованного компонента с помощью метода attrs, который может принимать как объект, так и функцию.
👉 Если один стилизованный компонент "наследует" от другого, то стили и атрибуты наследника переопределяют стили и атрибуты родителя (логично).
https://codesandbox.io/s/styled-components-5-react-junior-l4cn6?file=/src/App.js
#стили #styledcomponents #документация
Заинтересовал этот фрагмент. Что тут особенного:
1. В качестве селектора можно использовать не только &, который, как и в Scss, указывает на сам элемент, но и &&.
После обработки & заменяется на уникальное имя класса, сгенерированное для компонента, например, на
А вместо && соответственно будет
2. Если стилизованный компонент привести к строке (метод toString), то мы получим его селектор -
#стили #styledcomponents #документация
1. В качестве селектора можно использовать не только &, который, как и в Scss, указывает на сам элемент, но и &&.
После обработки & заменяется на уникальное имя класса, сгенерированное для компонента, например, на
.srTxsd
.А вместо && соответственно будет
.srTxsd.srTxsd
. То есть это нужно для повышения специфичности селектора.2. Если стилизованный компонент привести к строке (метод toString), то мы получим его селектор -
.srTxsd
, который можно использовать, например, в глобальных стилях.#стили #styledcomponents #документация
Анимации по требованию
Еще один любопытный момент, начиная с 4 версии анимации, созданные функцией keyframes загружаются динамически, поэтому мы не можем использовать их с помощью обычной интерполяции. Например, чтобы сохранить отдельно сниппет стиля.
Чтобы все сработало, нужно использовать именно теговую строку (функция css).
#стили #styledcomponents #документация
Еще один любопытный момент, начиная с 4 версии анимации, созданные функцией keyframes загружаются динамически, поэтому мы не можем использовать их с помощью обычной интерполяции. Например, чтобы сохранить отдельно сниппет стиля.
Чтобы все сработало, нужно использовать именно теговую строку (функция css).
#стили #styledcomponents #документация