HTMLセマンティクスと関連するフロントエンドフレームワークの詳細な分析

HTMLセマンティクスと関連するフロントエンドフレームワークの詳細な分析

セマンティクスについて

意味論は、記号やシンボルとそれらが表す意味との関係を研究する学問です。言語学では、言語におけるトークン(単語、フレーズ、音など)の意味を研究します。フロントエンド開発の分野では、セマンティクスは主に HTML 要素、属性、属性値(Microdata などの拡張機能を含む)の合意された意味を指します。仕様書でよく使用されるこれらの正式に合意されたセマンティクスは、プログラマー (およびその後の開発者) が Web サイトのさまざまな側面をよりよく理解するのに役立ちます。ただし、これらの要素、属性、および属性値のセマンティクスは形式化されていますが、開発者の利便性と集合的な選択に左右されます。これにより、正式に合意されたセマンティクスが将来変更される可能性があります (これは HTML の設計原則の 1 つです)。
さまざまな種類のHTMLセマンティクスを区別する

「セマンティック HTML」を記述するという原則に従うことは、現代のプロフェッショナルなフロントエンド開発の基礎の 1 つです。ほとんどのセマンティクスは、現在のコンテンツまたは予想されるコンテンツの性質に関連しています (例: h1 要素、lang 属性、type 属性のメール値、マイクロデータ)。

ただし、すべてのセマンティクスがコンテンツ指向である必要はありません。クラス名は「セマンティックフリー」にすることはできません。どのような名前が付けられるにせよ、意味と目的がなければなりません。クラス名のセマンティクスは HTML 要素のセマンティクスとは異なる場合があります。 HTML 要素、特定の HTML 属性、マイクロデータなどの「グローバル」セマンティクスを使用し、Web サイトまたはアプリケーションの「ローカル」固有のセマンティクスを使用してそれらを区別することができます。これらの固有のセマンティクスは通常、class 属性などの属性値に含まれています。

この「ベストプラクティス」は、HTML5 仕様の class 属性のセクションで繰り返し述べられていますが...

…開発者がクラス属性値を使用して、目的のコンテンツではなく実際のコンテンツを記述することを推奨します。

…そうする本質的な理由はありません。実際、このアプローチを大規模な Web サイトやアプリケーションで使用すると、障害になることがよくあります。

HTML要素やその他の属性はすでにコンテンツレベルでセマンティクスを提供している
クラス名は、機械や人間の訪問者にとって有用な意味情報をほとんど、あるいはまったく提供しません。ただし、合意された少数の名前セット(機械可読)の 1 つである場合は除きます - Mircoformats
クラス名の主な用途は、CSS と JavaScript へのフックになることです。ページにプレゼンテーションや動作を追加する必要がない場合は、HTML にクラスを追加する必要はおそらくありません。
クラス名は開発者にとって有用な情報を伝えるものである必要があります。 DOM スニペットを読むときは、特定のクラス名が何を行うかを理解すると役立ちます。特に複数人からなる開発チームでは、HTML コンポーネントを扱うのはフロントエンド開発者だけではありません。

非常に簡単な例を見てみましょう。

XML/HTML コードコンテンツをクリップボードにコピー
  1. < div  クラス= "ニュース" >   
  2.      < h2 >ニュース</ h2 >   
  3. 【ニュース内容】
  4. </div>   

内容が明らかでない場合は、クラス名のニュースでは何もわかりません。コンポーネントの全体的な構造については何も示されず、コンテンツが「ニュース」ではなくなったら、このクラスを使用するのは適切な選択ではありません。クラス名のセマンティクスがコンテンツに近すぎるため、アーキテクチャの拡張が容易ではなく、他の開発者が使用するのも容易ではありません。
コンテンツに関連しないクラス名

より良いアプローチは、デザイン パターンの構造と機能からクラス名のセマンティクスを抽出することです。クラス名がコンテンツと関係のないコンポーネントは、再利用性が高くなります。

クラス名を使用して特定のコンテンツを厳密に反映するのではなく、レイヤー間の関係を明確かつ明示的にすることを恐れてはなりません。これを行うと、クラス名が「セマンティクスフリー」になるわけではなく、単にそのセマンティクスがコンテンツに依存しないことを意味するだけです。また、より強力で柔軟性があり、再利用可能なコンポーネントを作成するのに役立つ限り、追加の HTML 要素を使用することを恐れてはいけません。これを行うと、HTML が「意味をなさなくなる」わけではなく、コンテンツをマークアップするために最小限の数を超える要素を使用していることを意味するだけです。
フロントエンドアーキテクチャ

コンポーネント、テンプレート、およびオブジェクト指向アーキテクチャの目的は、さまざまなコンテンツ タイプを含むことができる、限られた数の再利用可能なコンポーネントを開発できるようにすることです。大規模なアプリケーションでは、クラス名のセマンティクスに関する最も重要な点は、クラス名のセマンティクスを実用的に使用して、その主な目的、つまり、開発者がプレゼンテーションや動作に使用できる、意味があり、柔軟性があり、再利用可能なフックを提供できることです。
再利用可能で構成可能なコンポーネント

一般に、拡張可能な HTML/CSS は、再利用可能なコンポーネントを作成するために HTML 内のクラスに依存する必要があります。 DOM ツリーの特定の部分に依存しない、または特定のタイプの要素の使用を必要としない、柔軟で再利用可能なコンポーネント。さまざまなコンテナーに適応し、簡単にテーマを変更できる必要があります。必要に応じて、追加の HTML 要素 (コンテンツをマークアップするために必要なもの以外) により、コンポーネントをより堅牢にすることができます。 Nicole Sullivan のメディア オブジェクトは良い例です。

型セレクターを避けてクラスを使用すると、コンポーネントのマージが容易になります。次の例では、btn コンポーネントと uilist コンポーネントを簡単にマージすることはできません。問題は、.btn の重みが .uilist a (共有プロパティを上書きする) よりも小さいことです。また、ulist コンポーネントには子ノードとしてアンカーが必要です。

XML/HTML コードコンテンツをクリップボードにコピー
  1. .btn { /* スタイル */ }
  2. .uilist { /* スタイル */ }
  3. .uilist a { /* スタイル */ }
  4.   
  5. <ナビゲーション クラス= "uilist" >   
  6.      <   href = "#" >ホーム</ a >   
  7.      <   href = "#" >について</ a >   
  8.      <  クラス= "btn"   href = "#" >ログイン</ a >   
  9. </ナビ>   

uilist コンポーネントを他のコンポーネントと簡単に組み合わせる方法の 1 つは、クラスを使用して uilist の子 DOM 要素にスタイルを追加することです。これにより重量は軽減されますが、主な利点は、子ノードの任意の構造スタイルを処理できるオプションが提供されることです。

XML/HTML コードコンテンツをクリップボードにコピー
  1. .btn { /* スタイル */ }
  2. .uilist { /* スタイル */ }
  3. .uilist-item { /* スタイル */ }
  4.   
  5. <ナビゲーション クラス= "uilist" >   
  6.      <  クラス= "uilist-item"   href = "#" >ホーム</ a >   
  7.      <  クラス= "uilist-item"   href = "#" >について</ a >   
  8.      <スパン クラス= "uilist-item" >   
  9.          <  クラス= "btn"   href = "#" >ログイン</ a >   
  10.      </スパン>   
  11. </ナビ>   

JavaScript固有のクラス

何らかの形式の JavaScript 固有のクラスを使用すると、コンポーネントのスタイルや構造の変更によって JavaScript が壊れるリスクを軽減できます。私がうまく機能するとわかった方法は、JavaScript フック専用の特定のクラス (js-*) を使用し、クラス名に説明を追加しないことです。

XML/HTML コードコンテンツをクリップボードにコピー
  1. <   href = "/ログイン"  クラス= "btn btn-primary js-login" > </ a >   

このアプローチにより、コンポーネントの構造やスタイルを変更するときに、必要な JavaScript の動作や複雑な機能が誤って壊れてしまう可能性が低くなります。
コンポーネント修飾子

多くの場合、コンポーネントにはベース コンポーネントとわずかに異なるバリアントが存在します。たとえば、異なる背景色や境界線などです。これらのコンポーネントのバリエーションを作成するための主なモードは 2 つあります。私はこれを「単一クラス名」パターンと「複数クラス名」パターンと呼んでいます。

単一クラス名モード

XML/HTML コードコンテンツをクリップボードにコピー
  1. .btn, .btn-primary { /* ボタンテンプレートのスタイル */ }
  2. .btn-primary { /* プライマリボタンの特別なスタイル */ }
  3.   
  4. <ボタン  class = "btn" >デフォルト</ button >   
  5. <ボタン  class = "btn-primary" >ログイン</ button >   

複数のクラス名パターン

XML/HTML コードコンテンツをクリップボードにコピー
  1. .btn { /* ボタンテンプレートのスタイル */ }
  2. .btn-primary { /* プライマリボタンの特別なスタイル */ }
  3.   
  4. <ボタン  class = "btn" >デフォルト</ button >   
  5. <ボタン  class = "btn btn-primary" >ログイン</ button >   

プリプロセッサを使用する場合は、Sass の @extend 機能を使用して、「単一クラス名」パターンを使用するときに必要なメンテナンス作業の一部を削減できます。ただし、プリプロセッサの助けを借りても、私は依然として「複数のクラス名」パターンを使用し、HTML 内のクラス名を変更することを好みます。

これはよりスケーラブルなパターンだと思います。たとえば、基本的な btn コンポーネントを実装し、5 種類のボタンと 3 つの追加サイズを追加します。 「複数クラス名」モードを使用する場合は、9 つ​​のクラスのみが必要ですが、「単一クラス名」モードを使用する場合は、24 のクラスが必要です。

また、必要に応じてコンポーネントにコンテキストを適応させることも容易になります。他のコンポーネント内に表示されるボタンに詳細な調整を加える必要がある場合があります。

XML/HTML コードコンテンツをクリップボードにコピー
  1. /* 「複数のクラス名」スタイルの調整 */
  2. .thing .btn { /* スタイルを適宜調整します */ }
  3.   
  4. /* 「単一クラス名」スタイルの調整 */
  5. .もの .btn,
  6. .thing .btn-プライマリ、
  7. .thing .btn-危険、
  8. .thing .btn-etc { /* スタイルを適宜調整する */ }

「複数のクラス名」パターンは、単一の内部コンポーネント セレクターのみを使用して、すべてのタイプの btn 要素のスタイルを変更できることを意味します。 「単一クラス名」パターンは、新しいボタンバリアントを作成するときに、すべての可能なボタンタイプを考慮し、セレクターを調整する必要があることを意味します。
構造クラス名

コンポーネントを作成し、それに「テーマ」を追加する場合、一部のクラスはコンポーネントを区別するために使用され、一部のクラスはコンポーネントの修飾子として使用され、他のクラスは DOM ノードを関連付けるために使用されます。これらはすべて、より大きな抽象コンポーネントに一緒に含まれています。

btn (コンポーネント)、btn-primary (修飾子)、brn-group (コンポーネント)、btn-group-item (コンポーネントの子) は、クラスの目的を明確に表していないため、これらの名前間の関係を判断することが困難です。一貫したパターンはありません。

過去 1 年間、私は、サイトのアーキテクチャを組み立てるために HTML、CSS、JS ファイルを切り替えなくても、DOM フラグメント内のノードの表現間の関係をすばやく理解するのに役立つ命名パターンの実験を行ってきました。このパターンは、BEM システムの命名方法に大きく影響されていますが、より操作しやすい形式に適応されています。


コードをコピー
コードは次のとおりです。
t-テンプレート名
t-テンプレート名--修飾子名
t-テンプレート名__サブオブジェクト
t-テンプレート名__サブオブジェクト--修飾子名</p> <p>コンポーネント名
コンポーネント名--修飾子名
コンポーネント名__サブオブジェクト
コンポーネント名__サブオブジェクト--修飾子名</p> <p>is-state-type</p> <p>js-action-name
js コンポーネント タイプ

私は、いくつかの構造を抽象的な「テンプレート」として扱い、他の構造をより明確なコンポーネント(通常は「テンプレート」の上に構築される)として扱います。しかし、この区別は必ずしも必要ではありません。

これは、これまで私が便利だと感じた命名パターンです。命名パターンは任意の形式にすることができます。しかし、この命名パターンの利点は、(単一の)ハイフン、アンダースコア、またはキャメルケースのみに依存して、あいまいなクラス名を排除できることです。
元のファイルサイズとHTTP圧縮に関する注意事項

モジュール式でスケーラブルな CSS に関する議論では、必然的にファイル サイズと「肥大化」に関する懸念が生じます。ニコール・サリバン氏は、コメントの中でファイルサイズの保存(およびメンテナンスの改善)について頻繁に言及し、Facebook などの企業がこのアプローチを採用した経験についても言及しました。さらに一歩進んで、出力を前処理するときに HTTP 圧縮で行っていることと、HTML クラスを多用しているいくつかのことを共有したいと思います。

Twitter Bootstrap が初めて登場したとき、コンパイルされた CSS を書き直して、ファイル サイズを手動で実行できるものとより適切に比較しました。すべてのファイルを縮小すると、手動で操作された CSS ファイルはプリプロセッサの出力よりも 10% 小さくなります。しかし、すべてのファイルを gzip 圧縮すると、プリプロセッサの出力 CSS ファイルは手動プロセスよりも 5% 小さくなりました。

ファイル サイズの縮小だけでは全体像がわからないため、HTTP 圧縮後のファイル サイズを比較することの重要性が強調されます。これは、経験豊富な CSS 開発者は、プリプロセッサを使用する場合、コンパイルされた CSS の重複レベルについてあまり心配する必要がないことを意味します。HTTP 圧縮後にサイズが小さくなるためです。プリプロセッサを介した CSS コードの保守性の向上によるメリットは、元の CSS と縮小された出力の見た目やファイル サイズに関する懸念を上回ります。

別の実験では、インターネットから 60 KB の HTML ファイル (多くの再利用可能なコンポーネントで構成) を取得し、そこからすべてのクラス属性を削除しました。この処理により、ファイルサイズは 25KB に縮小されます。元のファイルとリッピングしたファイルの両方を gzip を使用して圧縮すると、サイズはそれぞれ 7.6 KB と 6 KB になり、差はわずか 1.6 KB になります。クラスを多用することによる実際のファイル サイズへの影響は、もはや強調する価値がありません。

<<:  CSS3 のディスプレイのグリッドレイアウトとフレックスレイアウトの詳細な説明

>>:  MySql データベースにおける単一テーブル クエリと複数テーブル結合クエリの効率の比較

推薦する

Linux の操作とメンテナンスの基本的なスワップ パーティションと LVM 管理のチュートリアル

目次1. スワップパーティション SWAP 1.1 スワップファイルを作成する1.2 スワップパーテ...

MySQL の null 可能フィールドは NULL に設定する必要がありますか、それとも NOT NULL に設定する必要がありますか?

MySQL を頻繁に使用する人は、次のような状況に遭遇する可能性があります。 1. フィールド タ...

Mysql トランザクションで Update を実行するとテーブルがロックされますか?

2つのケース: 1. 索引あり 2. 索引なし前提条件:方法: コマンドラインを使用してシミュレー...

HTMLでは、div内のコンテンツが次のサイズを超えたときに自動的にスクロールバーが表示されるように設定します。

HTML ページでは、div 内のコンテンツが制限を超えた後に自動的にスクロール バーを表示する必要...

MySQLでレコードを変更する場合、更新操作フィールド = フィールド + 文字列

シナリオによっては、varchar 型のフィールドを変更する必要があり、変更の結果は 2 つのフィー...

Linux での Redis の永続性、マスター スレーブ同期、Sentinel の詳細な説明

1.0 Redis の永続性Redis はメモリ内データベースです。サーバー プロセスが終了すると、...

Nginx操作応答ヘッダー情報の実装

前提条件: ヘッダー情報操作をサポートするには、ngx_http_headers_module モジ...

MySQL sql_modeクエリと設定の詳細な説明

1. SQLを実行して表示する @@session.sql_mode を選択します。 グローバルレベ...

CSS パフォーマンスの最適化 - will-change の使用方法の詳細な説明

will-change は、要素にどのような変更が行われるかをブラウザに伝え、ブラウザが事前に最適化...

JavaScript 即時実行関数の使用状況分析

一般的に、関数は実行する前に呼び出す必要があることはご存じのとおりです。以下に示すように、関数を定義...

win10にUbuntu18デュアルシステムをインストールするとmmx64.efiが見つからないという問題が発生する

Ubuntu 18のインストール中に、USBディスクからUbuntuのインストールを開始すると、mm...

nginx が複数のプロキシ層を通過して実際の送信元 IP を取得するプロセスの詳細な説明

質問Nginx は $remote_addr を実際の IP アドレスとして受け取りますが、実際には...

Linux ユーザーとグループのコマンド例分析 [切り替え、ユーザーの追加、権限制御など]

この記事では、Linux のユーザーおよびグループのコマンドについて例を挙げて説明します。ご参考まで...

クラウド サーバーを使用して CentOS システムに .NET 6.0 をインストールする

.NET SDK ダウンロード リンクhttps://dotnet.microsoft.com/do...