ホームページ >ウェブフロントエンド >CSSチュートリアル >BEM CSS アーキテクチャについて知っておくべきことすべて

BEM CSS アーキテクチャについて知っておくべきことすべて

DDD
DDDオリジナル
2024-10-02 06:12:02311ブラウズ

私は一般には聞かれない BEM に関する質問に答えることを目的としてこの記事を書きましたが、答えの欠如はアーキテクチャの開発と理解に影響を与えます。

この記事は、CSS についてよく理解し始めている初心者や、CSS クラスの命名規則に一度も触れたことのない初心者を対象としたものではありません。 これに該当する場合は、ソースセクションに進んでください

レガシー BEM CSS の公式 Web サイトから適合したヘッダー

  • CSS アーキテクチャとは何ですか?
  • BEM CSS とは何ですか?
    • UI 要素を結合に応じて分類する
    • コンポーネントの関係を CSS で表現する
    • 複雑なコンポーネント関係
  • BEM による特異性制御
  • CSS の再利用
  • ベムとサス
  • 他のアーキテクチャとの相互作用
  • 出典

? CSS アーキテクチャとは何ですか?

植物と同じように、コードがどのように成長し繁栄するかは、コードをどのように作成し、維持し、どこに配置するかによって決まります。

規格、場所、管理について異なるニーズを持つ規格があるのと同じように、土壌、処理、水、日光に対して異なるニーズを持つ植物があります。

CSS はページを読み込む際の重要な要素です。レンダリング プロセスは、ブラウザーがすべての HTML と CSS をリクエスト、ダウンロードして DOM と CSSOM に変換し、レンダー ツリーを組み立てるまで開始されません。 CSS が少ないほど、パフォーマンスが向上し、CSS がより組織化され、標準化され、堅牢になり、維持、管理、拡張、圧縮が向上します。

CSS セレクターの名前の付け方は、ルールの範囲、特異性、場所、セマンティクスに影響を与え、開発プロセスを加速または悪化させます。複数の人が CSS を作成するプロジェクトでは、言語スキルのレベルが異なり、習慣や個人基準も異なるため、管理しないとルールやバグが過度に繰り返される可能性があります。


? BEM CSS とは何ですか?

BEM は styleguide に焦点を当てた CSS アーキテクチャであり、CSS ルールの分類と作成の標準を定義します。 BEM は、1 つまたは少数のスタイル シートで管理される複数のページを含むアプリケーションのコンテキストで Yandex で作成されました。

BEM は、ブロック、要素、モディファイア の頭字語です。これらの各エンティティは、CSS で直接表現されるインターフェイス要素のカテゴリを表します。

Tudo o que você precisa saber sobre a arquitetura BEM CSS

視覚的に分離されたインターフェイス コンポーネントの表現、出典: BEM CSS 公式 Web サイト


? UI 要素を結合に応じて分類する

ブロックは独立した UI 要素を表し、ヘッダーにナビゲーション リンクがあるように子を持つことができ、これらの子が独立している場合はブロックにもなり得ます。

インターフェースコンポーネントの独立性の概念は、次の公理によって定義できます

「コンポーネントが特定のコンテキスト内でのみ意味をなす場合、そのコンポーネントはそのコンテキストの要素でなければなりません。複数のコンテキストに存在できる場合は、独立したブロックでなければなりません。」

要素は、別のより大きな要素を構成し、それに属するコンポーネントです。このコンポーネントが存在せず、適用されるコンテキストのみに依存しない場合は、ブロックである可能性があります。 BEM では、ブロック に他のブロックを含めることができます。要素要素 を含める必要がある場合、それもおそらくブロックです。

ブロックと要素の関係は、二重アンダースコア block__element で表されます。

ブロックと要素には、同じコンテキスト内で美的またはレイアウトのバリエーションが含まれる場合があります。このために、修飾子があります。これらのクラスは、同じコンポーネントの異なる状態またはバリアントを表すことができます。要素などの修飾子はブロックに依存し、そこからのみ派生します。

ブロックまたは要素とその修飾子の間の関係は、二重ダッシュ block--modifier または block__element--modifier で表されます。

Referência Descrição
Tudo o que você precisa saber sobre a arquitetura BEM CSS Um checkbox é independente, pode ser aplicado dentro de outros componentes como
,
ou , por exemplo.
Tudo o que você precisa saber sobre a arquitetura BEM CSS Uma label pode ser considerada um bloco independente se ela for igualmente aplicada nos inputs da aplicação. Se a diferença entre labels for estética, ela pode ser um bloco que contém diversas variantes (modifiers), se a diferença entre as labels do input for estrutural (no template), faz sentido ela ser o elemento de um bloco
Tudo o que você precisa saber sobre a arquitetura BEM CSS Um card pode ser incluído em qualquer container, em diferentes contextos, podendo ser considerado independente (block). Se a imagem e textos dentro dos cards tiverem características que só faz sentido no contexto do card, elas podem ser consideradas elements
Tudo o que você precisa saber sobre a arquitetura BEM CSS Um botão pode ser administrado em qualquer lugar, inclusive mais de uma variante no mesmo lugar. Cada variante pode ser representada pela classe modificadora derivada do mesmo bloco ou elemento.

?コンポーネント間の関係をCSSで表現する

チェックボックスの例を使用すると、コンポーネントを構築し、その責任を定義する方法が、ブロック、要素、または修飾子になり得るものに影響します。この意思決定は次のテンプレートから始まります:

<div class="form-field">
  <input
   class="form-field__input form-field__input--checkbox" 
   type="checkbox"
   value=""
   id="checkbox"
  />
  <label class="form-field__label" for="checkbox">
    Default checkbox
  </label>
</div>

このテンプレートには、ブロックとして .form-field コンポーネントがあり、これには常に .form-field__input 入力と .form-field__label クラス ラベルが含まれます。ブロック(.form-field)と要素(ラベルまたは入力)の関係は二重の下線で表されます。この記述は、CSS を通じて次のことを理解していることを意味します:

  • form-field は独立したエンティティであり、スタイルが機能するかどうかはコンポーネントや親コンテナのコンテキストに依存しません。どのフォームでも .form-field

  • 型のフィールドを受け取ることができます。
  • 次に、フォーム フィールドには __input と __label を含めることができ、そのレイアウトと外観はフォーム フィールド コンテナーによって異なります

.form-field {}
  .form-field__input {}
  .form-field__input--checkbox {}
  .form-field__label {}

テンプレート内の関係を変更すると、CSS クラスのトポグラフィーが変更されます。以下の例では、inputlabel は別個のエンティティです:

<div class="column">
  <label class="label" for="checkbox">
    Default checkbox
  </label>
  <input
   class="input input--checkbox"
   type="checkbox"
   value=""
   id="checkbox"
  />
</div>
  • この場合の .column は、ブロックとしても、単なるユーティリティ クラスとしても見ることができます。他の CSS アーキテクチャに加えて、独自の規則に従うものを含むユーティリティ クラスで BEM を使用することができます。
  • .input はすべての入力を参照するブロックであり、.label の存在に関係なく動作する .column コンテナまたはその他のコンテナ内で使用できます。これには、:checked のステータスなど、チェックボックス タイプの入力に特定のスタイルをロードする --checkbox バリアントがあります。
  • .label は、レイアウトと外観が入力に依存しないブロックであり、子要素として .input を持つこともできます。

CSS で表現すると次のようになります:

.column {}

.input {}
.input--checkbox {}
.input--checkbox:checked {}

.label {}

BEM はコンポーネントの独立性に重点を置いています。HTML 内でコンポーネントの位置を変更してもそのレイアウトに影響を与えるべきではなく、コンポーネントの CSS を変更しても他のコンポーネントに影響を与えるべきではありません。要素を作成するとき、そのブロックを変更したときに何が影響を受けるかのリストを示します。このようにして、コンポーネントとその部品が結合されたもの、および完全に独立したモジュールがどのようになるかを可視化できます。従来のドキュメントで引用されているように:

2006 年に、私たちは最初の大規模プロジェクトである Yandex.Music と Ya.Ru に取り組み始めました。数十ページにわたるこれらのプロジェクトでは、現在の開発アプローチの主な欠点が明らかになりました。

  • あるページのコードを変更すると、他のページのコードに影響を与えました。
  • クラス名を決めるのは難しかったです。

翻訳

2006 年に、私たちは最初の大きなプロジェクト、Yandex.Music と Ya.Ru に取り組み始めました。数十ページに及ぶこれらのプロジェクトは、現在の開発アプローチの欠点であることが明らかになりました。

  • あるページのコードを変更すると、他のページにも影響します。
  • クラスに名前を付ける方法を決めるのが難しかったです。

?複雑なコンポーネントの関係

2010 年に BEM がオープンソースになり、Web サイトになったとき、各 UI 要素は「コンポーネント」であるという考えは、アトミック デザイン (Brad Frost、2013) よりも前からすでに存在しており、一貫性を維持するという課題に対応していました。同じコンポーネントが異なるページにあります。たとえば、BEM が Yandex で作成されたとき、彼らはいくつかの HTML ファイルと 1 つの CSS ファイルと 1 つの Javascript ファイルだけを使用しました。

各ページがブロックであり、その要素がそのページのコンテキストに依存している場合、ページ間で一貫性のあるコードはすべて複製されます。 UI を小さなコンポーネントに分割することで、どのページで使用されているかに関係なく、これらのパーツを再利用できるようになりました。

この再利用の概念を例示するには、ヘッダーなどのより複雑なコンポーネントを使用できます。

Tudo o que você precisa saber sobre a arquitetura BEM CSS

このヘッダーは次のように記述できます (短い HTML):

<nav class="navbar">
  <div class="navbar__container">
    <a class="navbar__logo" href="#">Navbar</a>
    <button class="navbar__toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar__toggler-icon"></span>
    </button>
    <div class="navbar__collapse" id="navbarSupportedContent">
      <ul class="navbar__list">
        <li class="navbar__item">
          <a class="navbar__link active" aria-current="page" href="#">Home</a>
        </li>
        <!-- etc -->
        <li class="navbar__item navbar__dropdown">
          <a class="navbar__dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
            Dropdown
          </a>
          <ul class="navbar__dropdown-menu">
            <li>
              <a class="navbar__dropdown-item" href="#">
                Action
              </a>
            </li>
            <!-- etc -->
          </ul>
        </li>
        <!-- etc -->
      </ul>
      <form class="navbar__form" role="search">
        <input class="navbar__form-input" type="search" placeholder="Search" aria-label="Search">
        <button class="navbar__form-btn" type="submit">
          Search
        </button>
      </form>
    </div>
  </div>
</nav>

この例では、navbar 全体が 1 つの大きなブロックとして宣言されており、それに含まれるすべてのものは navbar要素 とみなされていることに注意してください。その結果、再利用の機会がいくつか失われます。

Oportunidade Descrição
Tudo o que você precisa saber sobre a arquitetura BEM CSS O logotipo dentro de .navbar__logo é representado por um link contendo imagem ou texto. Existem diversos elementos que podem ser 'envelopados' em um link, como ícones back to top ou cards clicáveis. Esse código poderia pertencer a um bloco .link ou .media
Tudo o que você precisa saber sobre a arquitetura BEM CSS Os itens .navbar__list e .navbar__item nada mais são que uma lista desordenada no formato de linha ao invés de coluna. Isso poderia reutilizado representando-a pelo bloco .list com o modificador .list--row. O dropdown por sua vez pode ter o mesmo funcionamento fora do navbar, dentro do seu próprio bloco .dropdown, com seus elementos .dropdown__toggle e, como ele renderiza uma lista, podemos reutilizar .list e, se necessário, complementar com um modificador
Tudo o que você precisa saber sobre a arquitetura BEM CSS Esse componente de busca pode ser representado de forma mais "fechada" com um bloco .search e elementos .search__input, search__label e .search__trigger ou de forma mais "aberta" como .form-field, .input--text, .label e .button--outline

 

Ainda pensando nessa relação de componentes "abertos" e "fechados", podemos representar o componente de busca usado no último exemplo das duas forma usando CSS.

Componente de busca "fechado"
Os elementos input, label e button são acoplados ao bloco search, mudanças no componente ou no HTML de search influenciam nos seus elementos.

.search {}
  .search__input {}
  .search__label {}
  .search__button {}

Componente de busca "aberto"
Os elementos input, label e button são independentes do bloco de search, ele apenas organiza os blocos já existentes que compõe esse componente.

.form-field {}

.input {}
.input--text {}

.label {}

.button {}
.button--outline {}

? Controle da especificidade com BEM

Um dos problemas citados pela galera do Yandex é que mudanças no CSS podiam afetar partes indesejadas. No caso deles era utilizada uma folha de estilo pra todas as páginas da aplicação, e você pode achar que não é um problema pra ti se você usa algum processador como Sass ou diversos arquivos de CSS, mas é uma dor de cabeça ainda maior quando seletores de diferentes abrangências moram em múltiplos arquivos.

A forma que o BEM encontrou de contornar esse problema além da modularização de blocos é a especificidade. BEM só utiliza classes por motivos bem claros:

  • Classes podem ser reaproveitadas
  • Como você se refere diretamente aos elementos usando as classes, a especificidade tende a ser sempre muito próxima de 0,1,0
  • Pra alterar ou sobrescrever uma regra, basta adicionar outra classe
  • Regras que se referem à seletores mais globais como de resets ou normalizers são facilmente sobrescritas pelas classes.

Abaixo vemos um accordion que mantém uma diversidade de seletores, pra nos referirmos, por exemplo ao h2 desse accordion, temos que explicitamente dizer #accordion-item > h2:

<div id="accordion-item">
  <h2>
    <button class="btn">
      Accordion Item #1
    </button>
  </h2>
  <div class="collapse show">
    <div>
      <strong>This is the first item's accordion body.</strong>
    </div>
  </div>
</div>

 

Pra estilizar todos os elementos desse componente, precisamos estabelecer as seguintes relações:

/* 1,0,0 */
#accordion-item {}

/* 1,0,1 */
#accordion-item > h2 {}

/* 1,1,0 */
#accordion-item .btn {}

/* 1,1,0 */
#accordion-item .collapse {}

/* 1,2,0 */
#accordion-item > .collapse.show {}

/* 1,1,1 */
#accordion-item > .collapse > div {}

/* 1,1,2 */
#accordion-item > .collapse strong {}

Esse exemplo assume que .collapse por não se referir diretamente ao accordion (não é um .accordion-collapse, por exemplo) pode existir em outros lugares do código ou até em outros lugares de #accordion-item. Isso obriga a gente a deixar explícita sua relação com #accordion-item.

A regra #accordion-item > .collapse > div existe pois o estilo não pode impactar qualquer div, nem qualquer .collapse, pra alterar apenas aquilo que existe dentro do bloco #accordion-item precisamos adicionar muito mais complexidade e especificidade, além de que qualquer mudança no HTML desse componente causa bugs imprevisíveis.

<div class="accordion-item">
  <h2 class="title">
    <button class="button">
      Accordion Item #1
    </button>
  </h2>
  <div class="accordion-item__collapse">
    <div class="accordion-item__wrapper">
      <strong>This is the first item's accordion body.</strong>
    </div>
  </div>
</div>

No HTML acima estabelecemos as relações entre o .accordion-item e o .accordion-item__collapse sem adicionar especificidade. Ao nos referirmos diretamente aos elementos pela classe e não compondo seletores, quando alteramos o .accordion-item podemos quebrar o .accordion-item__collapse, mas ao alterar .accordion-item__collapse, o .accordion-item dificilmente será influenciado.

.title e .button serem blocos independentes faz com que alterarmos o HTML desse componente ou o CSS dessas classes não cause nenhum bug, pois elas existem de forma independente do bloco do accordion. Em relação à especificidade, a relação passa a ser da seguinte forma:

/* 0,1,0 */
.accordion-item {}

/* 0,1,0 */
.accordion-item__collapse {}

/* 0,1,0 */
.accordion-item__wrapper {}

/* 0,1,0 */
.title {}

/* 0,1,0 */
.button {}

 

A especificidade dessas regras é muito mais previsível, tanto que se eu quiser adicionar uma variante ao .accordion-item__wrapper basta eu criar uma classe com as regras e incluir no elemento no HTML, sem precisar criar no CSS um seletor .accordion-item__wrapper.accordion-item__wrapper--vertical.


? Reuso de CSS

Quando me refiro a reuso de CSS, não falo apenas de blocos que podem ser reaplicados em diferentes componentes, à nível de seletores, mas também à conjuntos de regras que realizam as mesmas ações. No exemplo abaixo, temos 3 componentes diferentes e mesmo se escritos na convenção do BEM haverá repetição de conjuntos de regras:

Elemento Regras
Tudo o que você precisa saber sobre a arquitetura BEM CSS
.alert {
  display: flex;
  gap: 0.5rem;
  /* etc... */
}
Tudo o que você precisa saber sobre a arquitetura BEM CSS
.nav {
  display: flex;
  gap: 1rem;
  /* etc... */
}
Tudo o que você precisa saber sobre a arquitetura BEM CSS
.breadcrumb {
  display: flex;
  gap: 0.5rem;
  /* etc... */
}

 

Percebe como todos os elementos que tem a disposição de 'linha' muito provavelmente terão um grupo de regras de display: flex o configura dessa forma, terão um gap: npx e provavelmente um flex-wrap: wrap quando fizer sentido pro layout 'quebrar' pra linha de baixo?

Usando o breadcrumb como exemplo, podemos criar um bloco que represente uma linha ou coluna genérica e que seja configurável à partir de variantes.

<ol class="breadcrumb">
  <li class="breadcrumb__item">Home</li>
  <li class="breadcrumb__item active">Library</li>
</ol>

Ao invés de repetir o conjunto de regras que configura uma coluna, podemos adicionar à classe .breadcrumb o bloco de .row. Não há restrições sobre o mesmo elemento ser representado por dois blocos distintos, pois o conceito de bloco é acoplado com seus elementos, não com componentes específicos.

/* Breadcrumb deixa de configurar o layout e passa apenas a implementar estilos estéticos */
.breadcrumb {
  font: 200 1rem Poppins;
  line-height: 1.45;
}

/* Row se torna responsável pelo layout */
.row {
  display: flex;
  gap: 1rem;
}

/* E pode ter variantes na convenção BEM caso conveniente */
.row--flexible {
  flex-wrap: wrap;
}

Nesse caso o gap de .row é estático, mas os elementos apresentados nos exemplos tem diferentes valores nessa propriedade, de quem é a responsabilidade? Se você possuí uma estrutura de CSS utilitário, a responsabilidade pode ser de .row que será configurada pelo CSS utilitário .gap-0.5 ou .gap-sm.

Se você não usa CSS utilitário, o gap pode ser configurado pelo próprio componente breadcrumb:

/* Ao implementar o gap com variáveis CSS temos um valor
default e um valor configurável */
.row {
  --row__gap-default: 1rem;
  display: flex;
  gap: var(--row__gap, var(--row__gap-default));
}

/* Dessa forma podemos configurar o gap pelo breadcrumb.
A row ainda não depende dele, mas caso ele seja aplicado com
uma row, ele a configura */
.breadcrumb {
  --row__gap: 0.5rem;
  font: 200 1rem Poppins;
  line-height: 1.45;
}

Separar os estilos de layout dos de aparência é uma prática do OOCSS (link do artigo na Smashing Magazine, em inglês). Categorizar o CSS em skin e structure vem do entendimento de que a estrutura e layout de um elemento ou componente é mais reaproveitável e ubíqua do que a aparência de um componente.

Usando a convenção BEM é possível criar blocos que se referem à estruturas e modificadores que se referem à aparência, sendo ela apenas uma convenção de escrita de classes, a categorização e separação dessas classes pode ficar na responsabilidade de outro tipo de arquitetura.


? BEM e Sass

Sass foi criado em 2009, um ano antes de BEM se tornar open source, a interação entre eles funciona extremamente bem (rsrs) por dois motivos:

  • Sass permite a criação de múltiplas folhas de estilo e a co-locação dos estilos de acordo com as necessidades do projeto,logo podemos criar uma folha pra cada bloco ou conjunto de blocos que se referem a um componente ou contexto.
  • Sass tem suporte à concatenação de string, o que torna ainda mais visual a relação da classe com seus elementos e modificadores. Pensando no exemplo do bloco .search citado anteriormente:
.search {
  &__input {}
  &__label {}
  &__button {}
}

 

Com CSS a relação de blocos e elementos se dá pelo prefixo do bloco, ex: .search__, no Sass os elementos são declarados dentro do bloco.

Um problema muito comum com Sass é o 'overnesting', que é quando aninhamos múltiplas classes em um bloco. Essa abordagem além de dificultar a legibilidade do bloco cria especificidade sem necessidade e acopla os elementos ao bloco mais do que o necessário.

/* Esse tipo de nesting ao invés de gerar seletores  0,1,0 */
.search {
  .search__item {}

  .search__label {
    &.search__label--floating {

    }
  }
}

/* Gera o CSS */
/* 0.2.0 */
.search .search__item {}

/* 0.2.0 */
.search .search__label {}

/* 0.3.0 */
.search .search__label.search__label--floating {}

O overnesting geralmente acontece pelo não conhecimento de como o Sass funciona ou pela tentativa de imitar o formato do HTML no CSS.


? Interações com outras arquiteturas

Como naming convention BEM é flexível quando nos apropriamos de outras arquiteturas ou apenas características delas. Como citado na documentação:

No matter what methodology you choose to use in your projects, you will benefit from the advantages of more structured CSS and UI. Some styles are less strict and more flexible, while others are easier to understand and adapt in a team.

Tradução

Não importa qual metodologia você use em seus projetos, vbocê vai se beneficiar das vantagens de uma UI e CSS mais estruturados. Alguns estilos são menos estritos e mais flexíveis, outros sãi fáceis de entender e adaptar em um time.

 

Podemos escrever as regras do tipo block do CUBECSS na convenção do BEM.

A diferença entre os blocos do CUBECSS e do BEM é o seu escopo, no CUBE há uma separação semântica entre estrutura, configuração e aparência. Após declarar a camada de Composition que defini layouts num nível mais macro (Como o object no OOCSS ou ITCSS) e criar classes utilitárias na camada de Utility, sobra pouca configuração a se fazer na cabada do Block, o deixando mais enxuto.

Podemos também criar as diversas camadas propostas pelo ITCSS e criar Objects, Components e Utilities na sintaxe do BEM. O ITCSS não define a forma que criamos modificadores e a relação dos componentes e seus estados/variantes, mas sim a taxonomia e localização dos elementos respeitando seu escopo e dando previsibilidade na sua especificidade e posição na cascata.

Podemos expressar as mesmas relações do SMACSS, por exemplo, declarando states quando esses alteram um módulo específico na sintaxe BEM:

/* Na convenção SMACSS */
.tab {
  background-color: purple;
  color: white;
}

.is-tab-active {
  background-color: white;
  color: black;
}

/* Na convenção BEM */
.tab {
  background-color: purple;
  color: white;
  &__is-active {
    background-color: white;
    color: black;
  }
}

States que não são específicos de um módulo podem ser declarados como classes utilitárias ou blocos independentes.

Há muitas outras formas de se escrever BEM, não necessariamente vinculadas a uma arquitetura, como no exemplo abaixo.


Afinal, BEM é a melhor arquitetura de CSS?

Não existe 'melhor arquitetura'. Todas as metodologias já propostas são claras nos problemas que elas visam resolver, e elas não necessariamente vão resolver todos os problemas da sua organização, time ou codebase. BEM pode resolver seus problemas de acoplamento de classes e especificidade, mas talvez não resolva o de performance ou localização.

O interessante é aumentar seu gabarito de metodologias, convenções e arquiteturas e escolher sua ferramenta de acordo com os problemas que tu visa resolver.

BEM num contexto de aplicação Vue com SFC pode ser incrível quando localizamos o bloco CSS no mesmo lugar que o componente que ele estiliza, mas pode gerar muito CSS duplicado ou inutilizado se não houver uma arquitetura mais voltada pra reuso de estruturas, como OOCSS ou CUBECSS.


? Fontes

  • Artigo BEM: guia definitivo do padrão CSS mais famoso de Tárcio Zemel (DPW), em português (Muito bom)
  • Vídeo BEM: A Convenção CSS Para Um Front End Muito Melhor de Tárcio Zemel (DPW), em português
  • Artigo An Introduction To Object Oriented CSS (OOCSS) na Smashing Magazine, em inglês
  • Artigo MindBEMding – getting your head ’round BEM syntax de Harry Roberts, em inglês
  • Artigo BEMIT: Taking the BEM Naming Convention a Step Further de Harry Roberts, em inglês
  • Artigo Side Effects in CSS de Phillip Walton, em inglês
  • Artigo BEM 101 em Smashing Magazine, em inglês

以上がBEM CSS アーキテクチャについて知っておくべきことすべての詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。