DevGang
Авторизоваться

Начните делать ЭТО, чтобы улучшить свою архитектуру CSS

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

Сегодня я здесь, чтобы поговорить с вами об одном из лучших решений, которые я принял в отношении CSS, и которое теперь включаю во все свои проекты (если только я не выберу такую библиотеку, как Tailwind). Я говорю о модулях CSS.

style.module.css
/* style.module.css */

.saveButton {
    color: green;
}
form.jsx
// form.jsx

import styles from "./styles.module.css"

export const Form = () => {
    // ...
    return (
        <form onSubmit={handleOnSubmit}>
            <input name="email" />
            <button className={styles.saveButton} />
        </form>
    )
}

Конфликты между именами классов

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

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

Итак, что же нам в этом помогают модули CSS?

CSS-модули или как изолировать стили

Использование модулей CSS позволяет решить три основные задачи:

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

Давайте углубимся в каждый из них более подробно:

Как избежать столкновений

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

Например:

/* style.module.css */

.title {
    font-weight: bolder;
}
// header.jsx

import styles from "./styles.module.css"

export const Header = () => {
    // ...
    return (
        <div>
            <h1 className={styles.title}>Hello world!</h1> {/* ✅ Style applied */}
            <h2 className="title">This is my first post</h2> {/* ❌ Style NOT applied */}
        </div>
    )
}

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

Вход:

/* ProgressBar.module.css */

.background, .bar {
    height: 4px;
    border-radius: 999px;
}

.background {
    background-color: var(--color-secondary);
    width: 100%;
}

.bar {
    background-color: var(--color-primary);
}
// ProgressBar.tsx

import styles from "./ProgressBar.module.css";

interface Props {
  percentage: number;
}

export const ProgressBar = ({ percentage }: Props) => {
  return (
    <div className={styles.background}>
      <div className={styles.bar} style={{ width: `${percentage}%` }} />
    </div>
  );
};

Выход:

<div class="ProgressBar_background__v_qdp">
    <div class="ProgressBar_bar__YFKLn" style="width: 50%;"></div>
</div>

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

Но, как упоминалось ранее, это пример для Next.JS; он будет работать по-другому с другими платформами или конфигурациями.

Простой рефакторинг

Поскольку мы рассматриваем файлы CSS как модули, а имена классов — как переменные, экспортируемые этими модулями, переименование классов или выявление неиспользуемых стало проще, чем когда-либо.

Однако, слово предостережения! ⚠️ Очень важно, чтобы, даже если конфликтов имен классов не возникало, именование классов все равно должно соответствовать соглашению. Хотя БЭМ, возможно, больше не представляет особой ценности, вашей команде важно установить соглашение об именах, которое подойдет вам. Модули CSS не решают проблемы с именованием.

Например, что если мы захотим изменить наш компонент Button на ActionButton? Давайте сначала посмотрим на пример с БЭМ:

/* (BEFORE) Button.css */

.Button_label {
    text-transform: uppercase;
}

/* (AFTER) ActionButton.css */

.ActionButton_label {
    text-transform: uppercase;
}
// (BEFORE) Button.tsx

import "./Button.css";

export const Button = ({ label }) => {
  return (
    <button>
        <span className="Button_label">{label}</span>
    </button>
  );
};

// (AFTER) ActionButton.tsx

import "./ActionButton.css";
import Icon from "icons"

export const ActionButton = ({ label }) => {
  return (
    <button>
        <Icon />
        <span className="ActionButton_label">{label}</span>
    </button>
  );
};

Как видите, изменить имя компонента непросто, потому что вам придется изменить все имена классов (и нам повезло, что в данном случае только одно). Несмотря на то, что современные IDE имеют мощные инструменты поиска и замены, всегда проще, когда имена классов не связаны с именем компонента.

Теперь давайте посмотрим на пример с использованием модулей CSS:

/* (BEFORE) Button.module.css */

.label {
    text-transform: uppercase;
}

/* (AFTER) ActionButton.module.css */

.label {
    text-transform: uppercase;
}
// (BEFORE) Button.tsx

import styles from "./Button.module.css";

export const Button = ({ label }) => {
  return (
    <button>
        <span className={style.label}>{label}</span>
    </button>
  );
};

// (AFTER) ActionButton.tsx

import styles from "./ActionButton.module.css";
import Icon from "icons"

export const ActionButton = ({ label }) => {
  return (
    <button>
        <Icon />
        <span className={style.label}>{label}</span>
    </button>
  );
};

Как видите, отсутствие ссылок на имена компонентов делает их более несвязанными, и такие изменения легче вносить.

Как избежать анти-шаблонов

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

Давайте поговорим о компонентизации — практике, которая стала чрезвычайно популярной с появлением веб-фреймворков и библиотек, таких как Angular, React или Vue. Это крайне важно для достижения возможности повторного использования в вашем приложении (хотя, как и во всем, вам необходимо определить предел объема рефакторинга).

Модули CSS побуждают нас иметь файл стилей для каждого компонента, причем эти стили всегда идут рука об руку с изменениями в именах компонентов. Другими словами, не имеет значения, будет ли компонент называться из Button в ActionButton; стили разделены, поскольку они указаны в области видимости.

Начало работы с модулями CSS

В отличие от стандартного CSS, модули CSS могут потребовать некоторой подготовки перед использованием. Это зависит от вашего сборщика, препроцессоров и от того, используете ли вы TypeScript в своем проекте или нет:

  • Webpack: это один из случаев, требующих дополнительной документации, но, к счастью, вы найдете несколько шаблонов, подобных этому.
  • Next.JS: модный веб-фреймворк имеет встроенную поддержку модулей CSS. Вам просто нужно начать создавать файлы .module.css
  • Vite: Модули CSS также изначально совместимы с Vite, поэтому вам не придется делать ничего особенного, чтобы начать их использовать.

Источник:

#CSS #React
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу