ASP.NET Core Blazor CSS 隔離
注意
這不是這篇文章的最新版本。 如需目前的版本,請參閱 本文的 .NET 9 版本。
警告
不再支援此版本的 ASP.NET Core。 如需詳細資訊,請參閱 .NET 和 .NET Core 支援原則。 如需目前版本,請參閱本文的 .NET 8 版本。
作者:Dave Brock
本文說明 CSS 隔離如何將 CSS 範圍設為 Razor 元件,以簡化 CSS 且避免與其他元件或程式庫發生衝突。
將 CSS 樣式隔離至個別頁面、檢視和元件,以減少或避免:
- 相依於可能難以維護的全域樣式。
- 巢狀內容中的樣式衝突。
啟用 CSS 隔離
若要定義元件特定的樣式,請建立 .razor.css
檔案,其符合相同資料夾中元件的 .razor
檔案名稱。 .razor.css
檔案是限定範圍的 CSS 檔案。
對於 Example.razor
檔案中的 Example
元件,請在名為 Example.razor.css
的元件旁邊建立一個檔案。 Example.razor.css
檔案必須位於與 Example
元件 (Example.razor
) 相同的資料夾中。 檔案的 "Example
" 基底名稱不區分大小寫。
Example.razor
:
@page "/example"
<h1>Scoped CSS Example</h1>
Example.razor.css
:
h1 {
color: brown;
font-family: Tahoma, Geneva, Verdana, sans-serif;
}
Example.razor.css
中定義的樣式只會套用至 Example
元件的轉譯輸出。 CSS 隔離會套用至相符 Razor 檔案中的 HTML 元素。 應用程式中定義於別處的任何 h1
CSS 宣告不會與 Example
元件的樣式發生衝突。
注意
為了在統合發生時保證樣式隔離,不支援在 Razor 程式碼區塊中匯入 CSS。
CSS 隔離統合
在建置時會發生 CSS 隔離。 Blazor 會重寫 CSS 選取器,以符合元件所轉譯的標記。 重寫的 CSS 樣式會組合並產生為靜態資產。 樣式表會在 <head>
標籤 (<head>
內容的位置)內參考。 下列 <link>
元素會新增至從 Blazor 專案範本建立的應用程式:
Blazor Web App:
<link href="@Assets["{ASSEMBLY NAME}.styles.css"]" rel="stylesheet">
獨立 Blazor WebAssembly 應用程式:
<link href="{ASSEMBLY NAME}.styles.css" rel="stylesheet">
<link href="{ASSEMBLY NAME}.styles.css" rel="stylesheet">
{ASSEMBLY NAME}
預留位置是專案的組件名稱。
下列範例來自裝載的 Blazor WebAssemblyClient 應用程式。 應用程式的組件名稱為 BlazorSample.Client
,而 <link>
是使用 Hosted 選項 (使用 .NET CLI 的 -ho|--hosted
選項,或或使用 Visual Studio 的 [已裝載 ASP.NET Core] 核取方塊) 建立專案時由 Blazor WebAssembly 專案範本所新增:
<link href="BlazorSample.Client.styles.css" rel="stylesheet">
在配套的檔案中,每個元件都會與範圍識別碼相關聯。 針對每個有樣式的元件,HTML 屬性會附加格式 b-{STRING}
,其中 {STRING}
預留位置是架構所產生的十個字元字串。 識別碼對於每個應用程式而言都是唯一的。 在轉譯的 Counter
元件中,Blazor 將範圍識別碼附加至 h1
元素:
<h1 b-3xxtam6d07>
{ASSEMBLY NAME}.styles.css
檔案會使用範圍識別碼,將樣式宣告與其元件分組。 下列範例提供上述 <h1>
元素的樣式:
/* /Components/Pages/Counter.razor.rz.scp.css */
h1[b-3xxtam6d07] {
color: brown;
}
在建置階段,會使用慣例 obj/{CONFIGURATION}/{TARGET FRAMEWORK}/scopedcss/projectbundle/{ASSEMBLY NAME}.bundle.scp.css
建立專案配套,其中預留位置為:
{CONFIGURATION}
:應用程式的組建組態(例如Debug
、Release
)。{TARGET FRAMEWORK}
:目標架構 (例如net6.0
)。{ASSEMBLY NAME}
:應用程式的組件名稱 (例如BlazorSample
)。
子系元件支援
CSS 隔離僅適用於您與格式 {COMPONENT NAME}.razor.css
相關聯的元件,其中 {COMPONENT NAME}
預留位置通常是元件名稱。 若要將變更套用至子系元件,請在父代元件的 .razor.css
檔案中使用任何後代元素的::deep
虛擬元素。 ::deep
虛擬元素選取的元素是元素生成範圍識別碼的「後代」。
下列範例顯示名為 Parent
的父代元件,其子系元件稱為 Child
。
Parent.razor
:
@page "/parent"
<div>
<h1>Parent component</h1>
<Child />
</div>
Child.razor
:
<h1>Child Component</h1>
使用 ::deep
虛擬元素來更新 Parent.razor.css
中的 h1
宣告,以表示 h1
樣式宣告必須套用至父代元件及其子系。
Parent.razor.css
:
::deep h1 {
color: red;
}
h1
樣式現在適用於 Parent
和 Child
元件,而不需要為子系元件建立個別的限定範圍 CSS 檔案。
::deep
虛擬元素只適用於後代元素。 下列標記會如預期般將 h1
樣式套用至元件。 父代元件的範圍識別碼會套用至 div
元素,因此瀏覽器知道要繼承父代元件的樣式。
Parent.razor
:
<div>
<h1>Parent</h1>
<Child />
</div>
不過,排除 div
元素會移除後代關聯性。 在下列範例中,樣式不會套用至子系元件。
Parent.razor
:
<h1>Parent</h1>
<Child />
::deep
虛擬元素會影響範圍屬性套用至規則的位置。 當您在限定範圍的 CSS 檔案中定義 CSS 規則時,範圍會套用至最右邊的元素。 例如:div > a
會轉換成 div > a[b-{STRING}]
,其中 {STRING}
預留位置是架構所產生的十個字元字串 (例如 b-3xxtam6d07
)。 如果您想要將規則套用至不同的選取器,::deep
虛擬元素可讓您這麼做。 例如,div ::deep > a
會轉換成 div[b-{STRING}] > a
(例如 div[b-3xxtam6d07] > a
)。
將 ::deep
虛擬元素附加至任何 HTML 元素的功能,可讓您建立限定範圍的 CSS 樣式,以在您可判斷已轉譯 HTML 標籤的結構時影響其他元件所轉譯的元素。 對於轉譯另一個元件內的超連結標記 (<a>
) 的元件,請確定此元件已包裝在 div
(或任何其他元素) 中,並使用 ::deep > a
規則來建立樣式,而該樣式只會在父代元件轉譯時套用至該元件。
重要
限定範圍的 CSS 僅適用於 HTML 元素,不適用於 Razor 元件或標籤協助程式,包括已套用標籤協助程式的元素,例如 <input asp-for="..." />
。
CSS 前置處理器支援
CSS 前置處理器可用來利用變數、巢狀、模組、混合和繼承等功能來改善 CSS 開發。 雖然 CSS 隔離原生不支援 Sass 或 Less 等 CSS 前置處理器,但只要 Blazor 在建置程序期間重寫 CSS 選取器之前進行前置處理器編譯,整合 CSS 前置處理器就會很順暢。 例如,使用 Visual Studio,在 Visual Studio 工作執行器總管中將現有的前置處理器編譯設定為 [建置之前] 工作。
許多第三方 NuGet 套件 (例如 AspNetCore.SassCompiler
) 可以在 CSS 隔離發生之前,先在建置程序開始時編譯 SASS/SCSS 檔案。
CSS 隔離設定
CSS 隔離的設計訴求是要現成可用,但會提供某些進階案例的組態,例如當現有工具或工作流程有相依性時。
自訂範圍識別碼格式
範圍識別碼會使用 b-{STRING}
格式,其中 {STRING}
預留位置是架構所產生的十個字元字串。 若要自訂範圍識別碼格式,請將專案檔更新為所需的模式:
<ItemGroup>
<None Update="Components/Pages/Example.razor.css" CssScope="custom-scope-identifier" />
</ItemGroup>
在上述範例中,針對 Example.razor.css
產生的 CSS 會將其範圍識別碼從 b-{STRING}
變更為 custom-scope-identifier
。
使用範圍識別碼來達到限定範圍 CSS 檔案的繼承。 在下列專案檔範例中,BaseComponent.razor.css
檔案包含跨元件的通用樣式。 DerivedComponent.razor.css
檔案會繼承這些樣式。
<ItemGroup>
<None Update="Components/Pages/BaseComponent.razor.css" CssScope="custom-scope-identifier" />
<None Update="Components/Pages/DerivedComponent.razor.css" CssScope="custom-scope-identifier" />
</ItemGroup>
使用萬用字元 (*
) 運算子,跨多個檔案共用範圍識別碼:
<ItemGroup>
<None Update="Components/Pages/*.razor.css" CssScope="custom-scope-identifier" />
</ItemGroup>
範圍識別碼會使用 b-{STRING}
格式,其中 {STRING}
預留位置是架構所產生的十個字元字串。 若要自訂範圍識別碼格式,請將專案檔更新為所需的模式:
<ItemGroup>
<None Update="Pages/Example.razor.css" CssScope="custom-scope-identifier" />
</ItemGroup>
在上述範例中,針對 Example.razor.css
產生的 CSS 會將其範圍識別碼從 b-{STRING}
變更為 custom-scope-identifier
。
使用範圍識別碼來達到限定範圍 CSS 檔案的繼承。 在下列專案檔範例中,BaseComponent.razor.css
檔案包含跨元件的通用樣式。 DerivedComponent.razor.css
檔案會繼承這些樣式。
<ItemGroup>
<None Update="Pages/BaseComponent.razor.css" CssScope="custom-scope-identifier" />
<None Update="Pages/DerivedComponent.razor.css" CssScope="custom-scope-identifier" />
</ItemGroup>
使用萬用字元 (*
) 運算子,跨多個檔案共用範圍識別碼:
<ItemGroup>
<None Update="Pages/*.razor.css" CssScope="custom-scope-identifier" />
</ItemGroup>
變更靜態 Web 資產的基底路徑
scoped.styles.css
檔案會在應用程式的根目錄產生。 在專案檔中,使用 <StaticWebAssetBasePath>
屬性來變更預設路徑。 下列範例會將 scoped.styles.css
檔案和應用程式資產的 rest 放在 _content
路徑上:
<PropertyGroup>
<StaticWebAssetBasePath>_content/$(PackageId)</StaticWebAssetBasePath>
</PropertyGroup>
停用自動組合
若要退出 Blazor 在執行階段發佈及載入限定範圍檔案的方式,請使用 DisableScopedCssBundling
屬性。 使用此屬性時,這表示其他工具或程序會負責從 obj
目錄取得隔離的 CSS 檔案,並在執行階段將其發佈及載入:
<PropertyGroup>
<DisableScopedCssBundling>true</DisableScopedCssBundling>
</PropertyGroup>
停用 CSS 隔離
在應用程式的專案檔中將 <ScopedCssEnabled>
屬性設定為 false
,以停用專案的 CSS 隔離:
<ScopedCssEnabled>false</ScopedCssEnabled>
Razor 類別庫 (RCL) 支援
NuGet 套件或 Razor 類別庫 (RCL) 中元件的隔離樣式會自動組合:
應用程式會使用 CSS 匯入來參考 RCL 的配套樣式。 針對名為
ClassLib
的類別庫,以及具有BlazorSample.styles.css
樣式表的 Blazor 應用程式,RCL 的樣式表會在應用程式的樣式表頂端匯入:@import '_content/ClassLib/ClassLib.bundle.scp.css';
RCL 的配套樣式不會發佈為取用樣式的應用程式靜態 Web 資產。
如需有關 RCL 的詳細資訊,請參閱下列文件: