(15/30)大家一起學Blazor:CSS isolation(隔離)

(15/30)大家一起學Blazor:CSS isolation(隔離)

有時候會想對不同 Component 做個別樣式設定,但如果把 class 都寫在`wwwroot/css/site.css`,或是針對某個元素改動樣式,可能導致改一個就影響全部 Component,這種全域衝突是必須避免的,但應該怎麼做?

最後更新 2021/12/18 下午10:35
StrayaWorker
預計閱讀 3 分鐘
分類
Blazor
專題
一起學Blazor系列
標籤
.NET C# ASP.NET Core Blazor

CSS 隔離介紹

有時候會想對不同 Component 做個別樣式設定,但如果把 class 都寫在 wwwroot/css/site.css,或是針對某個元素改動樣式,可能導致改一個就影響全部 Component,這種全域衝突是必須避免的,但應該怎麼做?

.NET 5 推出了 CSS isolation (CSS 隔離),建立 Component 個別的 css 檔案,命名規則為 {Component name}.razor.css,檔案會自動跟 {Component name}.razor 合併在一起,且名稱不分大小寫。下圖可以看到不論是 Blog.razor.css 還是 blog.razor.css 都會跟 Blog.razor 被視為同一組。

CSS isolation 會在建置時被處理,Blazor 會改寫 CSS 選擇器並產生一個 {Project name}.style.css 檔案,可以在 wwwroot/index.html (Blazor WebAssembly) 或是 Pages/_Layout.cshtml (Blazor Server)<head> 標籤內找到引用路徑,由於這是建置時才會產生,所以在專案內是看不到的,我們打開瀏覽器的 Dev tool 並切換到 Sources 頁籤,就能看到這檔案。

有人可能會發現為何 class 後面連接著沒有看過的內容,例如 .page[b-mxoy4q7bj7] 或是 .main[b-mxoy4q7bj7],這是 Blazor 用來辨識 CSS 選擇器作用在哪個 Component 的區域識別碼,格式為 b-10 位數字及英文字母,每個 Component 的區域識別碼都是獨一無二的,可知這裡的 .main.page class 只作用於 [b-mxoy4q7bj7] 對應的 Component,註解寫著 /* _content/BlazorServer/Shared/MainLayout.razor.rz.scp.css */,打開 Shared/MainLayout.razor.css,的確看到了 .main.page class,rz.scp.css 副檔名是用來辨識 CSS 選擇器屬於哪個 Component。

我們在 Blog.razor.css 加上一段針對 label 的樣式修改,按下 ctrl + shift + B 建置專案,再看網頁就能看到文字顏色改變了,BlazorServer.style.css 也能看到 Blog.razor.rz.scp.css 的樣式區塊多了一段 label[b-0ae5hiw99t]

套用樣式到 Child Component

如果想對 Post Component 的 label 元素套用相同樣式,又不想分別建立 razor.css 檔案呢?Blazor 提供了方便的做法,只要在 CSS 選擇器前面加上 ::deep 即可,我們在 Blog.razor.css 的 label 前面加上 ::deep,就能看到 Post 的 label 元素顏色都改變了,BlazorServer.style.css 的 class 也從 label[b-0ae5hiw99t] 變成了 [b-0ae5hiw99t] label

不過要注意的是,必須有父子關係 ::deep 才能生效,Parent Component 的區域識別碼僅作用於 <div> 標籤,如果 Child Component 沒有被 <div> 標籤包住就不會生效。我們把 Blog.razor 中包住 Post Component 的 <div> 標籤都註解,儲存後再去網頁看,發現 <label> 文字顏色都變回黑色了,但 BlazorServer.style.css 的 class 仍舊是 [b-0ae5hiw99t] label

參考資料:

  1. ASP.NET Core Blazor CSS isolation

註:本文程式碼透過 .NET 6 + Visual Studio 2022 重構,可點擊原文連結與重構後程式碼比較學習,謝謝閱讀,支持原作者

繼續探索

延伸閱讀

更多文章
同分類 / 同標籤 2021/12/25

(29/30)大家一起學Blazor:Blazor單元測試

開發一個系統最無聊的過程大概就是解決 Bug 了,尤其是那種嘗試對 null 物件取值的錯誤(`Object reference not set to an instance of an object.`),這應該是大部分人剛踏入程式設計領域最常碰到的問題,為了從枯燥的解決 Bug 過程解脫,這篇就來介紹`單元測試`。

繼續閱讀
同分類 / 同標籤 2021/12/25

(28/30)大家一起學Blazor:Policy-based authorization

之前有說到`ASP.NET Core Identity` 使用的是基於`Claim` 的驗證,其實`ASP.NET Core Identity` 有不同類型的授權方式,最簡單的`登入授權`、`角色授權`、`Claim 授權`,但上述幾種都是以一種方式實現:原則授權(`Policy-based authorization`)。

繼續閱讀