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。

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