Blazor における CSS 分離の問題

Blazor における CSS 分離の問題

1. 環境

VS 2019 16.9.0 プレビュー 1.0

.NET SDK 5.0.100

2. はじめに

CSS が有効になると、グローバルに適用されるため、競合が発生する可能性があります。この問題を解決するために、CSS 分離が誕生しました。 Blazor は 2018 年に誕生しました。つまり、2 年以上前のことです。ただし、CSS 分離は .NET 5 までサポートされていませんでした。

3. Razorコンポーネント間の分離

Razor コンポーネント間の CSS 分離は、CSS 分離を使用する最もシンプルで便利な方法です。 Razor コンポーネント間の CSS 分離を実現するのは非常に簡単です。コンポーネントが配置されているディレクトリに同じ名前の ".razor.css" ファイルを作成するだけです。フォルダー A に "Component.razor" という名前のコンポーネントがある場合、フォルダー A に "Component.razor.css" を作成するだけで、他のコンポーネントに影響を与えずに "Component.razor" コンポーネントに別のスタイルを設定できます。

デフォルトのテンプレートを例に、次の内容の新しい「Index.razor.css」を作成します。

h1 {
    フォントサイズ: 48px;
    フォントの太さ: 太字;
}

次の内容で新しい「Counter.razor.css」を作成します。

h1 {
    フォントサイズ: 16px;
    フォントの太さ: 400;
}

効果は以下のとおりです。

上記のコンポーネント CSS ファイルは、「プロジェクト名.styles.css」ファイルとして生成され、.NET 5 ではデフォルトで「index.html」に追加されます。上記の 2 つの CSS ファイルは、次の結果にコンパイルされます。

/* /Pages/Counter.razor.rz.scp.css */
h1[b-g5zg69lne1] {
    フォントサイズ: 16px;
    フォントの太さ: 400;
}
/* /Pages/Index.razor.rz.scp.css */
h1[b-f3rb2cn7la] {
    フォントサイズ: 48px;
    フォントの太さ: 太字;
}

ブラウザで DOM 要素を表示すると、結果は次のようになります。

<h1 b-f3rb2cn7la>こんにちは、世界!</h1>

<h1 b-g5zg69lne1>カウンター</h1>

つまり、これら 2 つのコンポーネントの DOM に、「b-」で始まり、ランダムな 10 文字が続く属性が追加されます。これは Angular に似ているようです (私は使用したことはありませんが、ブラウザーで同様のものを見たことがあります)。 Blazor での CSS の分離は、ランダムなプロパティ名によって実現されるようです。では、id と class を使用して style.css を生成するとどうなるでしょうか?これもランダムな属性名によって実現されます。たとえば、次のコンポーネント CSS ファイル:

#zxyao-a {
    フォントサイズ: 48px;
    フォントの太さ: 太字;
}

#zxyao-b {
    フォントサイズ: 24px;
    フォントの太さ: 太字;
    背景色: #ff0000;
    パディング: 16px;
}

.zxyao-cls {
    フォントサイズ: 24px;
    フォントの太さ: 太字;
    背景色: #000;
    色: #fff;
    パディング: 16px;
}

次のような結果にコンパイルされます。

/* /Pages/Index.razor.rz.scp.css */
#zxyao-a[b-f3rb2cn7la] {
    フォントサイズ: 48px;
    フォントの太さ: 太字;
}

#zxyao-b[b-f3rb2cn7la] {
    フォントサイズ: 24px;
    フォントの太さ: 太字;
    背景色: #ff0000;
    パディング: 16px;
}

.zxyao-cls[b-f3rb2cn7la] {
    フォントサイズ: 24px;
    フォントの太さ: 太字;
    背景色: #000;
    色: #fff;
    パディング: 16px;
}

結果は次のとおりです。

つまり、コンポーネント CSS ファイルのサマリーがどのように記述されていても、CSS セレクタ [ランダム属性] の形式に変換されます。

4. CSS 分離サブコンポーネントのサポート

デフォルトでは、コンポーネント CSS は現在のコンポーネントにのみ適用されます。たとえば、次の 2 つのコンポーネントがあります。

/* Index.razor */
<div class="my-text">
    新しいアプリへようこそ。
    <CssIsolation.Components.Child />
</div>

/* コンポーネント/Child.razor */
<h1>子供</h1>
<div class="my-text">
    これは子コンポーネントです</div>

「Index.razor.css」のスタイルが次のようになっている場合、

.my-text {
    境界線:2px実線 #000;
    パディング: 16px;
}

そうすると、「Index.razor」に対してのみ機能し、境界線は最も外側の Index コンポーネントに表示されます。

このコンポーネントとそのサブコンポーネント「.my-text」要素で動作させたい場合は、「::deep」を使用してマークすることができます。

::deep .my-text {
    境界線:2px実線 #000;
    パディング: 16px;
} 

このコンポーネントの「.my-text」の境界線が消えていることに気づきましたか?前述したように、ここでは ::deep がランダムな属性に置き換えられます。つまり、コンパイル結果は次のようになります。

/* /Pages/Index.razor.rz.scp.css */
[b-f3rb2cn7la] .my-text {
    境界線:2px実線 #000;
    パディング: 16px;
}

このうち、b-f3rb2cn7la は、図に示すように、このコンポーネントのルート要素を参照します。

このグループ内に一意の親要素タグがない場合、このグループ内の各ネイティブ HTML タグは同じランダム属性を持ちます。たとえば、以下のコンポーネントでは、「div」と「h1」の両方が同じランダム属性を持ち、「::deep」フラグがこの属性に置き換えられます。 「子」コンポーネント内の要素にはランダムな属性はありません。

<div class="my-text">
    新しいアプリへようこそ。
</div>
<h1>
    新しいアプリへようこそ。
</h1>
<CssIsolation.Components.Child />

一部のコンポーネント ライブラリでは、Ant Design Blazor などの「テンプレート」などのコンポーネントが提供されています。次のように、コンポーネントを使用してすべての要素をラップするとします。

<AntDesign.テンプレート>
    <div class="my-text">
        新しいアプリへようこそ。
        <CssIsolation.Components.Child />
    </div>
</AntDesign.テンプレート>

Blazor は、このグループ内の最初のネイティブ HTML 要素が見つかるまで外側のコンポーネントを無視し、その後、このレイヤー内のすべてのネイティブ HTML 要素にランダムな属性を追加します。

したがって、このコンポーネントのルート要素に、サブコンポーネントでスタイルを設定する必要がある要素と同じ CSS セレクターがある場合、このコンポーネントとサブコンポーネントの両方にスタイルを適用するように分離するには、このグループとサブコンポーネントの CSS スタイルを同時に記述する方法と、すべてのコンポーネントと要素を 1 つの要素でラップする、つまりルート要素を変更する方法の 2 つの方法があります。

5. CSSプリプロセッサのサポート

多くの場合、スタイル ファイルの作成には SCSS または LESS を使用します。Blazor はこれらのプリプロセッサをネイティブにサポートしていません。プロジェクトが生成される前にタスク ランナー リソース マネージャーを使用して SCSS または LESS をコンパイルするか、Microsoft が言及している Delegate.SassBuilder などのサードパーティ ライブラリを使用してサポートすることができます。 Delegate.SassBuilder を試してみました。使い方が間違っていたせいか、CSS ファイルの生成がプロジェクトの生成より遅く、初めてプログラムを生成したときに CSS ファイルをコンパイルできませんでした。次に、別の方法を紹介します。「タスク ランナー エクスプローラー」を使用する方法です。

ここでは、単に「node-sass」を使用し、Gulp や Webpack などの高度なツールを使用せずに、コマンドラインから直接コンパイルしました。解決手順は次のとおりです (node-sass のインストールについてはここでは説明しません)。

拡張機能「Command Task Runner」をダウンロードしてインストールします

SCSSファイルのコンパイルコマンドラインプログラム「scss.bat」を記述します。

プロジェクトのルート ディレクトリに新しい scss.bat ファイルを作成します。

そして、以下のコマンドを記述します。

node-sass -r ./ -o ./ --source-map true --source-map-contents sass --output-style 圧縮

このコマンドは、SCSS ファイルをコンパイルし、圧縮された CSS ファイルと対応するソース マップ ファイルを生成します。

タスクランナーにbatファイルを追加する

scss.bat ファイルを右クリックし、「タスク ランナーに追加」オプションを選択します。

バインド実行タスク

[表示] | [その他のウィンドウ] | [タスク ランナー エクスプローラー] を開き、scss コマンドを見つけて右クリックし、[バインド] | [生成前] を選択します。バインド後、右側の [バインド] ウィンドウの [生成前] の下にコマンドが表示されます。

タスク ランナーを有効にすると、ソリューション ディレクトリに「commands.json」ファイルが生成されます。ファイルの内容は次のとおりです。「-vs-binding」オプションは、タスク バインディングのランタイムの場所を示します。

{
  「コマンド」: {
    "scss": {
      "ファイル名": "cmd.exe",
      "作業ディレクトリ": ".",
      "引数": "/c scss.bat"
    }
  },
  "-vs-binding": { "BeforeBuild": [ "scss" ] }
}

次に、プログラムを直接実行して効果を確認します。

もちろん、SCSS では「::deep」タグも使用でき、これも正しく表示できます。次に例を示します。

/* ページ/Index.razor.scss */
.my-text {
    境界線: 2px実線 #000;
    パディング: 16px;

    ::深い {
           .my-text {
            境界線: 2px 実線 #ff0000;
            背景色: #000;
            色: #fff;
        }
    }
}

/* コンポーネント/Child.razor.scss */
h1 {
    背景色: #efefef;
    フォントの太さ: 700;
}

対応する Razor コンポーネントは次のとおりです。

/* ページ/インデックス.razor */
@ページ "/"

<div class="my-text">
    新しいアプリへようこそ。
    <CssIsolation.Components.Child />
</div>

/* コンポーネント/Child.razor */
<h1>子供</h1>
<div class="my-text">
    これは子コンポーネントです</div>

操作効果は以下のとおりです。

ただし、SCSS で「::deep」タグを使用すると、少し混乱する可能性があると個人的には感じています。「::deep」タグを使用しないか、以下に示すように「::deep」タグを最外層に配置することをお勧めします。

// いくつかの SCSS スタイル コード...


::深い {
	// サブコンポーネント用のいくつかの SCSS スタイル コード ...
}


// いくつかの SCSS スタイル コード...

6. ランダム属性識別を変更する

前述のように、Blazor によって生成されるランダム属性名のデフォルト形式は、「b-」に続く 10 個のランダムな文字で始まります。Microsoft の公式ドキュメントには、これを変更できることが示されています。これは、独自のアプリケーションにとってより使いやすいものです。たとえば、Xiaomi は「mi」で始まるランダム属性フォームを定義でき、Taobao は「tb」で始まるランダム属性フォームを定義できます。しかし、この機能には問題があるようです。誰かが Github で問題を提起しました - カスタム CSS スコープ識別子が機能しない。Blazor がますます完璧になることを願っています。

Blazor での CSS 分離に関するこの記事はこれで終わりです。Blazor での CSS 分離の詳細については、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

<<:  HTML で水平ナビゲーション構造を設定する方法

>>:  MySQL 8.0はJSONを扱えるようになりました

推薦する

Navicat を使用して MySQL データベースをエクスポートおよびインポートする方法

MySql は、私たちが頻繁に使用するデータ ソースです。開発者が練習、小規模なプライベート ゲーム...

大規模な Vue.js プロジェクトの構築と維持のための 10 のベスト プラクティス

目次1. スロットを使用してコンポーネントを理解しやすくし、より強力にする2. Vuexストアを正し...

MySQLカスケードレプリケーションの実装方法の例

いわゆるカスケード レプリケーションでは、マスター サーバーが 1 つのスレーブ サーバーにのみデー...

MySQLは2つの日付間の日数、月数、年数を計算します

MySQL 組み込みの日付関数 TIMESTAMPDIFF は、2 つの日付間の秒数、分数、時間数、...

MySQL プロジェクトでトランザクション分離レベルを選択する方法

導入コンテンツから始めましょう。誰もが次のような面接のシナリオに遭遇したことがあると思います。インタ...

レスポンシブレイアウトについて知っておくべきこと

1. はじめにレスポンシブ Web デザインにより、Web サイトは複数のデバイスと複数の画面に同時...

Vue は、デスクトップから Web ページにファイルをドラッグするためのサンプル コードを実装します (画像/オーディオ/ビデオを表示できます)

効果使用する場合は、コードとスタイルを自分で最適化してください。画像を表示しない/ビデオとオーディオ...

Linux の GRUB ブート プログラムの暗号化の概要

目次1. GRUB暗号化とは何か2. grub暗号化手順3. grub暗号化のロック属性1. GRU...

CentOS 8 システム FTP サーバーのインストールとパッシブ モードの設定の詳細なチュートリアル

目次1. 基本を理解する2. システム環境を確認する3. ftpコマンドをインストールする[オプショ...

CSS フォント、テキスト、リストのプロパティの詳細な紹介

1. フォントのプロパティcolorは、div{color:red;}のようにテキストの色を指定しま...

MySQLクエリ文の実行プロセスの詳細な説明

目次1. クライアントとサーバー間の通信方法2. クエリキャッシュ3. クエリ最適化処理4. クエリ...

Docker Compose を使用して nginx のロード バランシングを実装する方法

Dockerネットワーク管理とコンテナIP設定に基づいてNginxロードバランシングを実装するすべて...

Vue コンポーネントはどのように解析され、レンダリングされるのでしょうか?

序文この記事では、Vue コンポーネントがどのように解析され、レンダリングされるかを説明します。 V...

sbinディレクトリを生成せずにNginxをインストールするソリューション

エラーの説明: 1. Linux (CentOS 7 64) システムに Nginx (1.18.0...

HTML タグのリストと使用方法

HTMLタグのリストマークタイプ名前または意味効果述べるファイルのタグ付け<HTML> ...