第三章 组件(10)- CSS隔离

Blazor项目中,支持将CSS样式隔离到各个组件(也就是将指定的CSS样式只在作用在指定的组件上),以简化 CSS 并避免与其他组件或库发生冲突。

启用CSS隔离

若要定义组件特定的样式,可以在同一个文件夹中创建一个 .razor.css 文件,该文件与组件的 .razor 文件的名称相匹配。.razor.css 文件是限定范围的 CSS 文件。

例如,对于 Example.razor 文件中的 Example 组件,可以在同文件夹下创建一个名为 Example.razor.css 的文件。

  • Example.razor

    csharp 复制代码
    @page "/example"
    
    <h1>Scoped CSS Example</h1>
  • Example.razor.css

    css 复制代码
    h1 { 
        color: brown;
        font-family: Tahoma, Geneva, Verdana, sans-serif;
    }


Example.razor.css 中定义的样式仅应用于 Example 组件的渲染输出。 CSS 隔离适用于匹配的 Razor 文件中的 HTML 元素。 在应用的其他位置定义的任何 h1 CSS 声明都不会与 Example 组件的样式冲突。

CSS 隔离捆绑

当使用 Visual Studio 或 .NET CLI 通过 blazor 模板创建一个新的 Blazor 项目时,项目模板会默认在 App.razor 文件中自动添加一个特定的 <link> 标签,用来引用 Blazor 自动生成的 CSS 隔离文件。

  • 其中{ASSEMBLY NAME} 是项目程序集名称
  • Blazor 在编译时会扫描每个组件的 .razor.css 文件(如 Counter.razor.css)。重写这些 CSS 选择器,使其仅作用于对应组件的 HTML 范围,然后将所有处理后的 CSS 合并到 {ASSEMBLY NAME}.styles.css 文件中
css 复制代码
<link href="{ASSEMBLY NAME}.styles.css" rel="stylesheet">

注意,为了保证发生捆绑时的样式隔离,不支持在 Razor 代码块中导入 CSS。

在捆绑的文件中,每个组件都与范围标识符关联,组件中所有的元素都会追加属性,即该组件对应的范围标识符b-{STRING},其中 {STRING} 占位符是框架生成的十个字符的字符串,标识符具有唯一性。

例如,对Counter.razor组件使用css样式隔离

  • Counter.razor.css

    css 复制代码
    h1{
        color: red
    }
    p{
        color:blue
    }

渲染后,可以看到h1p元素中自动追加了该组件的范围标识符

其项目捆绑包位于obj/{CONFIGURATION}/{TARGET FRAMEWORK}/scopedcss/projectbundle/{ASSEMBLY NAME}.bundle.scp.css

  • {CONFIGURATION}:应用的生成配置(例如 DebugRelease)。
  • {TARGET FRAMEWORK}:目标框架(例如 net6.0)。
  • {ASSEMBLY NAME}:应用的程序集名称(例如 BlazorSample)。

CSS隔离样式的传递

默认情况下,CSS 隔离仅应用于与 {COMPONENT NAME}.razor.css 格式关联的组件,若要让子组件也应用隔离的样式。可以在父组件的 .razor.css 文件中,对目标元素使用 ::deep::deep 会选择具有范围标识符的元素的后代元素。

  • 注意,::deep 只作用于具有样式范围标识符元素的后代元素
  • 限定范围的 CSS 仅适用于 HTML 元素,不适用于 Razor 组件或标记帮助程序,包括应用了标记帮助程序的元素

例如,有Parent.razor和Child.razor组件如下:

csharp 复制代码
@page "/parent"

<h1>这里是爸爸</h1>
<Child />
csharp 复制代码
<h1>我只是个孩子啊</h1>

现在,设置如下隔离样式,Parent.razor.css

css 复制代码
::deep h1 {
    color: red
}

由于::deep h1只作用于具有样式范围标识符元素的后代元素,所以两个h1元素都没有使用样式。

现在,将Parent.razor修改如下:

csharp 复制代码
@page "/parent"

<div>
    <h1>这里是爸爸</h1>
    <Child />
</div>

此时,由于h1和Child组件都属于div的后代,而div具有范围标识符,所以两个h1都使用了样式。

选择器的范围

默认情况下,在隔离的CSS文件中定义选择器时,范围默认应用于最右侧的元素,例如div > a 转换为 div > a[b-{STRING}]。如果希望规则应用于其他选择器,可以改为 div ::deep > a 转换为 div[b-{STRING}] > a

CSS 隔离配置

CSS 隔离开箱即用,也可在某些高级场景(例如依赖于现有工具或工作流)下进行配置。对于CSS隔离的配置,基本上都在项目文件中进行。

一、自定义范围标识符格式

默认情况下,范围标识符使用格式 b-{STRING},其中 {STRING} 占位符是框架生成的十个字符的字符串。 若要自定义范围标识符格式,可以将项目文件更新为所需模式:

指定单个CSS隔离文件的范围标识符

xml 复制代码
<ItemGroup>
  <None Update="Components/Pages/Example.razor.css" CssScope="custom-scope-identifier" />
</ItemGroup>

在上面的示例中,为 Example.razor.css 生成的 CSS 将其范围标识符从 b-{STRING} 更改为了 custom-scope-identifier

CSS隔离文件的继承

可以通过范围标识符实现CSS文件的继承,在下面的项目文件示例中,BaseComponent.razor.css 文件包含跨组件的通用样式, DerivedComponent.razor.css 文件继承了这些样式。

xml 复制代码
<ItemGroup>
  <None Update="Components/Pages/BaseComponent.razor.css" CssScope="custom-scope-identifier" />
  <None Update="Components/Pages/DerivedComponent.razor.css" CssScope="custom-scope-identifier" />
</ItemGroup>

共享范围标识符

可以使用通配符 (*) 运算符跨多个文件共享范围标识符

xml 复制代码
<ItemGroup>
  <None Update="Components/Pages/*.razor.css" CssScope="custom-scope-identifier" />
</ItemGroup>

二、更改静态 Web 资产的基路径

默认情况下,scoped.styles.css 文件在应用的根目录生成。 可以通过在项目文件中,使用 <StaticWebAssetBasePath> 属性来更改默认路径。 例如,将 scoped.styles.css 文件以及应用的其余资产放在 _content 路径:

xml 复制代码
<PropertyGroup>
  <StaticWebAssetBasePath>_content/$(PackageId)</StaticWebAssetBasePath>
</PropertyGroup>

三、禁用自动捆绑

若要禁用 Blazor 在运行时发布和加载限定范围的文件,可以使用 DisableScopedCssBundling 属性。 使用此属性时,意味着将由其他工具或进程从 obj 目录中捕获隔离的 CSS 文件,并在运行时发布和加载这些文件:

xml 复制代码
<PropertyGroup>
  <DisableScopedCssBundling>true</DisableScopedCssBundling>
</PropertyGroup>

四、禁用 CSS 隔离

可以通过在应用的项目文件中将 <ScopedCssEnabled> 属性设置为 false 来禁用项目的 CSS 隔离:

xml 复制代码
<ScopedCssEnabled>false</ScopedCssEnabled>
相关推荐
尽一份心出一份力43 分钟前
dify-dashboard 用Windsurf和Claude耗时两天开发的 DIFY 辅助项目
前端·claude·windsurf
mqwguardain1 小时前
DOM 事件 & HTML 标签属性速查手册
前端·javascript·python·html
李奶酪1 小时前
WebSocket相关技术
前端
m0_748241701 小时前
rust web框架actix和axum比较
前端·人工智能·rust
心灵宝贝2 小时前
用DeepSeek生成批量删除处理 PDF第一页工具
开发语言·microsoft·c#
AC-PEACE2 小时前
React 项目创建与文件基础结构关系
前端·javascript·react.js
IT、木易2 小时前
白话React第九章React 前沿技术与企业级应用实战
前端·react.js·前端框架
xuxiaoxie2 小时前
安装electron 提示RequestError: certificate has expired
前端·javascript·electron
做怪小疯子3 小时前
三个小时学完vue3(一)
前端·javascript·vue.js
LXY202305043 小时前
利用props实现子传父组件
java·服务器·前端