Malcolm Laing
Malcolm LaingJavaScript Consultant

Jak korzystać z modułów CSS z Create-React-App

Sprawdź, jak możesz wykorzystywać moduły CSS, w celu uniknięcia kolizji nazw klas w CSS i React.
25.07.20194 min
Jak korzystać z modułów CSS z Create-React-App

"Jak zorganizowałbyś CSS w dużym projekcie?" - to pytanie, które zawsze zadaję, kiedy przeprowadzam rozmowy o pracę z młodszymi programistami. Zdziwiłbyś się, jak wielu developerów nie ma na nie odpowiedzi.

Wraz z rozwojem naszych aplikacji wzrasta również ryzyko kolizji nazw klas.

Spójrzmy na konkretny przykład:

.container {
  width: 50%;
  display: flex;
  border: 1px solid black;
}
.container {
  width: 100%;
  height: 200px;
}


Tutaj użyliśmy nazwy klasy container w dwóch różnych plikach CSS. Teraz elementy, którym nadajemy nazwę klasy container będą miały wymieszane style, czego przecież nie chcemy.

W tym akurat przykładzie wygląda to całkiem trywialnie i łatwo takiej sytuacji uniknąć. Ale nie jest to już takie łatwe do uniknięcia, gdy pracujesz z wieloma osobami nad dużym projektem.

Jak zorganizować CSS w dużym projekcie?

W przeszłości programiści radzili sobie z globalnym charakterem CSS, opierając się na konwencjach nazewnictwa. Najpopularniejszym rozwiązaniem był BEM (Block Element Modifier). Wszystkie te rozwiązania miały jednak to samo ograniczenie: opierają się na staranności programistów, aby uniknąć kolizji nazw.

Co by było, gdybyśmy zamiast polegać na developerach używających unikalnych nazw klas, moglibyśmy polegać na narzędziu, które generuje dla nas nazwy klas podczas tworzenia? Na szczęście dla nas, to narzędzie już istnieje i nazywa się CSS Modules.

CSS Modules jest plikiem CSS, w którym wszystkie nazwy klas i nazwy animacji domyślnie mają zasięg lokalny.

Korzystanie z modułów CSS z Create-react-app

Na szczęście dla nas, moduły CSS są obsługiwane przez Create-react-app domyślnie. Jedyne, co mamy do zrobienia, to nadanie odpowiedniej nazwy naszym plikom CSS. Jeśli zaimportujemy plik z rozszerzeniem .module.css, to createe-react-app automatycznie potraktuje go jako moduł CSS.

npx create-react-app css-modules-app


Otwórz projekt w swoim ulubionym edytorze. Zmień nazwę pliku App.css na App.module.css. Następnie zmień nazwę importu z import './App.css' na import styles from './App.modules.css. Wreszcie, gdziekolwiek używasz className, upewnij się, że używasz obiektu styles zamiast bezpośredniego wstawiania nazwy klasy.

Więc zamiast pisać className="App" napisałbyś className={styles['App']}.

import React from "react";
import logo from "./logo.svg";
import styles from "./App.module.css";

function App() {
  return (
    <div className={styles["App"]}>
      <header className={styles["App-header"]}>
        <img src={logo} className={styles["App-logo"]} alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className={styles["App-link"]}
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;


Następnie uruchom aplikację i sprawdź, co otrzymasz. Zauważysz, że moduły CSS wygenerowały dla nas nazwy klas.

Nazwa klasy App-header to teraz App_App-header__xLkWl. Prefiks jest nazwą pliku App.module.css. Następnie dodano podkreślenie i naszą oryginalną nazwę klasy: App-header. Na koniec dodano wygenerowany hash xLkWl. Pomaga to zapewnić, że nasza nazwa klasy pozostanie unikalna.

Pisanie stylów globalnych

Czasami trzeba pisać globalne style. Jest to szczególnie ważne, gdy trzeba zastąpić style z zewnętrznych komponentów. Robienie tego za pomocą modułów CSS jest bardzo proste. Wystarczy użyć selektora :Global, aby przełączyć się z zasięgu lokalnego na globalny.

.container {
  height: 200px;
  width: 100%;
}

:global .React_Select {
  border-color: green;
}

Komponowanie stylów warunkowych

Moduły CSS świetnie sprawdzają się w stylach warunkowych. Często musimy tworzyć komponenty, które mają różne oblicza w oparciu o ich propsy. Weźmy na przykład prosty komponent TextInput.

Aby ułatwić sobie życie, zainstaluj zależność w postaci classnames.

yarn add classnames

Następnie tworzymy dwa nowe pliki text-input.js i text-input-module.css.

Kod jest poniżej:

import React from "react";
import classNames from "classnames";
import styles from "./text-input.module.css";

const TextInput = props => {
  return (
    <input
      className={classNames({
        [styles["text-input"]]: true,
        [styles["warning"]]: props.hasWarning,
        [styles["error"]]: props.hasError,
      })}
      type="text"
    />
  );
};

export default TextInput;
.text-input {
  height: 32px;
  width: 100%;
  border: 1px solid black;
}

.warning {
  border-color: orange;
}

.error {
  border-color: red;
}


Gdy do TextInput są przekazywane właściwości hasWarning lub hasError, zostaną dodane odpowiednie nazwy klasy.

Podsumowując

Korzystanie z modułów CSS pozwala nam na pisanie stylów o zasięgu lokalnym. Pomaga nam to uniknąć kolizji nazw pomiędzy naszymi nazwami klas. Zważając że wsparcie dla modułów CSS jest wbudowane w create-react-app, nie musimy nawet wykonać komendy eject, aby wykorzystać moduły CSS.


Oryginał tekstu w języku angielskim przeczytasz tutaj.

<p>Loading...</p>