1. ホーム
  2. Web制作
  3. CSS

[CSSチュートリアル】BlazorでCSSを分離する

2022-02-02 06:42:39

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" ファイルを作成することで簡単にできます。 razor"という名前のコンポーネントがフォルダ A の Component.razor" にある場合、フォルダ A に "Component.razor.css" を作成するだけで、他のコンポーネントに影響を与えずに "Component.razor "のコンポーネントに別のスタイルを設定することが可能です。

デフォルトのテンプレートを例に、以下の内容で新規に"Index.razor.css"を作成します。

h1 {
    font-size: 48px;
    font-weight: bold;
}

以下の内容で、新規に "Counter.razor.css" を作成します。

h1 {
    font-size: 16px;
    font-weight: 400;
}

その効果は次の通りです。

上記のコンポーネント CSS ファイルは "projectname.styles.css" ファイルとして生成され、.NET のデフォルトで "index.html" に追加されます。.NET 5では、デフォルトで"index.html"に追加されます。

/* /Pages/Counter.razor.rz.scp.css */
h1[b-g5zg69lne1] {
    font-size: 16px;
    font-weight: 400;
}
/* /Pages/Index.razor.rz.scp.css */
h1[b-f3rb2cn7la] {
    font-size: 48px;
    font-weight: bold;
}

ブラウザでDOM要素を表示すると、以下のようになります。

<h1 b-f3rb2cn7la>Hello, world!</h1>

<h1 b-g5zg69lne1>Counter</h1>

つまり、この2つのコンポーネント内のDOMに、"b-"で始まるプロパティにランダムな10文字を加えたもので、Angularと似ているようです(使ったことはありませんが、ブラウザで似たものを見ただけです) BlazorのCSS分離は、ランダムなプロパティ名で実現しているようです では、idとclassでstyles.cssを生成するとどうなるか?同じことをランダムなプロパティ名で行っています。例えば、以下のようなコンポーネントCSSファイルです。

#zxyao-a {
    font-size: 48px;
    font-weight: bold;
}

#zxyao-b {
    font-size: 24px;
    font-weight: bold;
    background-color: #ff0000;
    padding: 16px;
}

.zxyao-cls {
    font-size: 24px;
    font-weight: bold;
    background-color: #000;
    color: #fff;
    padding: 16px;
}

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

/* /Pages/Index.razor.rz.scp.css */
#zxyao-a[b-f3rb2cn7la] {
    font-size: 48px;
    font-weight: bold;
}

#zxyao-b[b-f3rb2cn7la] {
    font-size: 24px;
    font-weight: bold;
    background-color: #ff0000;
    padding: 16px;
}

.zxyao-cls[b-f3rb2cn7la] {
    font-size: 24px;
    font-weight: bold;
    background-color: #000;
    color: #fff;
    padding: 16px;
}

結果は次のようになります。

つまり、コンポーネントCSSファイルの概要がどのように書かれていても、CSSセレクタ[ランダムプロパティ]の形式に変換される。

4. CSSで分離されたサブコンポーネントへの対応

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

/* Index.razor */
<div class="my-text">
    Welcome to your new app.
    <CssIsolation.Components.Child />
</div>

/* Components/Child.razor */
<h1>Child</h1>
<div class="my-text">
    This is the child component
</div>

"Index.razor.css"のスタイルが以下のような場合。

.my-text {
    border:2px solid #000;
    padding: 16px;
}

それでは、"Index.razor" に対してのみ動作します。 - ボーダーは、一番外側のIndexコンポーネントに表示されます。

このコンポーネントとその子要素である ".my-text" に対して動作させたい場合は、 "::deep" でマークしてください。

::deep .my-text {
    border:2px solid #000;
    padding: 16px;
}

このコンポーネントから ".my-text" のボーダーが消えていることにお気づきでしょうか?前述したように、ここでは ::dep がランダムな属性に置き換えられるので、以下のようにコンパイルされることになります。

/* /Pages/Index.razor.rz.scp.css */
[b-f3rb2cn7la] .my-text {
    border:2px solid #000;
    padding: 16px;
}

ここで、b-f3rb2cn7laは図のように、このコンポーネントのルート要素です。

このグループの間に固有の親タグがない場合、このグループの各ネイティブ HTML タグは同じランダム属性を持ちます。例えば、次のコンポーネントは "div" と "h1" の両方について同じランダム属性を持ち、"::deep" フラグの代わりに属性を置き換えます。なお、"Child"コンポーネントの要素は、ランダム属性が変更されることはありません。

<div class="my-text">
    Welcome to your new app.
</div>
<h1>
    Welcome to your new app.
</h1>
<CssIsolation.Components.Child />

コンポーネントライブラリの中には、Ant Design Blazor のように "Template" のようなコンポーネントを提供し、それらが使用された場合、すべての要素をラップすることができるものがあります、例えば。

<AntDesign.Template>
    <div class="my-text">
        Welcome to your new app.
        <CssIsolation.Components.Child />
    </div>
</AntDesign.Template>

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

したがって、このコンポーネントのルート要素が、スタイルを設定する必要がある子コンポーネントと同じ要素の CSS セレクタを持つ場合、このコンポーネントと子コンポーネントの両方でスタイルを有効にしたい場合、スタイルを分離する方法は 2 つあります。このインターグループと子コンポーネントの両方に CSS スタイルを記述するか、すべてのコンポーネントと要素をもうひとつの要素、つまり異なるルート要素でラップするかです。

5. CSSプリプロセッサー対応

多くの場合、スタイルファイルを書くために SCSS や LESS を使うことがありますが、Blazor はこれらのプリプロセッサをネイティブでサポートしていないので、プロジェクト生成前に Task Runtime Explorer で SCSS や LESS をコンパイルするか、Microsoft 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 compressed

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

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

scss.batファイルを右クリックし、"Add to Task Runner"オプションを選択します。

バインディングの実行タスク

View|Other Windows|Task Runner Explorerを開き、scssコマンドを見つけ、右クリックしてBind|Before Generateを選択すると、Bindウィンドウの右側にあるBefore Generateの下にコマンドが表示されます。

タスクランナーが有効になると、ソリューションディレクトリに "commands.json" ファイルが生成され、タスクバインドランタイムの場所を示す "-vs-binding" オプションが付いた次のようなファイルが生成されます。

{
  "commands": {
    "scss": {
      "fileName": "cmd.exe",
      "workingDirectory": ". ",
      "arguments": "/c scss.bat"
    }
  },
  "-vs-binding": { "BeforeBuild": [ "scss" ] }
}

次に、プログラムを直接実行するだけで、その効果を確認できます。

もちろんSCSSでは、"::deep"タグを使っても正しく表示されます、例えば。

/* Pages/Index.razor.scss */
.my-text {
    border: 2px solid #000;
    padding: 16px;

    ::deep {
           .my-text {
            border: 2px solid #ff0000;
            background-color: #000;
            color: #fff;
        }
    }
}

/* Components/Child.razor.scss */
h1 {
    background-color: #efefef;
    font-weight: 700;
}

対応するRazorコンポーネントは以下の通りです。

/* Pages/Index.razor */
@page "/"

<div class="my-text">
    Welcome to your new app.
    <CssIsolation.Components.Child />
</div>

/* Components/Child.razor */
<h1>Child</h1>
<div class="my-text">
    This is the child component
</div>

以下のように実行されます。

ただし、個人的にはSCSSで"::deep"タグを使うと少しわかりにくい気がするので、"::deep"タグを使わないか、"::deep"タグを一番外側に置く、つまり以下のような形で使うことをおすすめしています。

// Some SCSS style code
...


::deep {
	// Some SCSS style code for child components
	...
}


// Some SCSS style code for the
...

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

前述の通り、Blazor のデフォルトでは "b-" で始まるランダムな属性名と 10 文字が生成されますが、Microsoft の公式ドキュメントでは変更可能であることが示されています。例えば、Xiaomiは"mi"、Taobaoは"tb"という形でランダムな属性を定義することができるのです。しかし、この機能には問題があるようで、ある人がGithubで問題を提起しています。 カスタムCSSのスコープ識別子が機能しない Blazorが改善されることを望みます。

BlazorにおけるCSSの分離については、この記事がすべてです。BlazorにおけるCSSの分離については、過去の記事を検索するか、以下の記事を引き続きご覧ください。