Aislamiento de CSS de Blazor de ASP.NET Core
Nota
Esta no es la versión más reciente de este artículo. Para la versión actual, consulte la versión de .NET 9 de este artículo.
Advertencia
Esta versión de ASP.NET Core ya no se admite. Para obtener más información, consulta la Directiva de soporte técnico de .NET y .NET Core. Para la versión actual, consulta la versión .NET 8 de este artículo.
Importante
Esta información hace referencia a un producto en versión preliminar, el cual puede sufrir importantes modificaciones antes de que se publique la versión comercial. Microsoft no proporciona ninguna garantía, expresa o implícita, con respecto a la información proporcionada aquí.
Para la versión actual, consulte la versión de .NET 9 de este artículo.
De Dave Brock
En este artículo se explica cómo el aislamiento de CSS aplica ámbito de CSS a componentes Razor, lo que puede simplificar CSS y evitar conflictos con otros componentes o bibliotecas.
Aísla los estilos CSS a páginas, vistas y componentes individuales para reducir o evitar lo siguiente:
- Dependencias de estilos globales que pueden ser difíciles de mantener.
- Conflictos de estilo en el contenido anidado.
Habilitación del aislamiento de CSS
Para definir estilos específicos de un componente, crea un archivo .razor.css
cuyo nombre coincida con el del archivo .razor
del componente en la misma carpeta. El archivo .razor.css
es un archivo CSS con ámbito.
En un componente Example
de un archivo Example.razor
, crea un archivo junto al componente denominado Example.razor.css
. El archivo Example.razor.css
debe residir en la misma carpeta que el componente Example
(Example.razor
). El nombre base "Example
" del archivo no distingue mayúsculas de minúsculas.
Example.razor
:
@page "/example"
<h1>Scoped CSS Example</h1>
Example.razor.css
:
h1 {
color: brown;
font-family: Tahoma, Geneva, Verdana, sans-serif;
}
Los estilos definidos en Example.razor.css
solo se aplican a la salida representada del componente Example
. El aislamiento de CSS se aplica a los elementos HTML en el archivo Razor coincidente. Cualquier declaración CSS h1
definida en otra ubicación de la aplicación no entra en conflicto con los estilos del componente Example
.
Nota
Para garantizar el aislamiento de estilo en el momento de la unión, no se admite la importación de CSS en bloques de código Razor.
Unión del aislamiento de CSS
El aislamiento de CSS se produce en tiempo de compilación. Durante este proceso, Blazor reescribe los selectores de CSS para que coincidan con el marcado representado por el componente. Estos estilos de CSS reescritos se unen y se generan como un recurso estático. Se hace referencia a la hoja de estilos dentro de la etiqueta <head>
(ubicación del contenido de <head>
). El siguiente elemento <link>
se agrega a una aplicación creada a partir de las plantillas de proyecto Blazor:
Blazor Web App:
<link href="@Assets["{ASSEMBLY NAME}.styles.css"]" rel="stylesheet">
Aplicaciones Blazor WebAssembly independientes:
<link href="{ASSEMBLY NAME}.styles.css" rel="stylesheet">
<link href="{ASSEMBLY NAME}.styles.css" rel="stylesheet">
El nombre del ensamblado del proyecto es el marcador de posición {ASSEMBLY NAME}
.
El ejemplo siguiente es de una aplicación Blazor WebAssemblyClient hospedada. El nombre del ensamblado de la aplicación es BlazorSample.Client
, y la plantilla de proyecto Blazor WebAssembly agrega <link>
cuando el proyecto se crea con la opción Hospedado (opción -ho|--hosted
usando la CLI de .NET o la casilla ASP.NET Core hospedado con Visual Studio):
<link href="BlazorSample.Client.styles.css" rel="stylesheet">
En el archivo unido, cada componente está asociado a un identificador de ámbito. Para cada componente con estilo, se anexa un atributo HTML con el formato b-{STRING}
, donde el marcador de posición {STRING}
es una cadena de diez caracteres generada por el marco. El identificador es único para cada aplicación. En el componente Counter
representado, Blazor anexa un identificador de ámbito al elemento h1
:
<h1 b-3xxtam6d07>
El archivo {ASSEMBLY NAME}.styles.css
usa el identificador de ámbito para agrupar una declaración de estilo con su componente. En el ejemplo siguiente se proporciona el estilo del elemento <h1>
anterior:
/* /Components/Pages/Counter.razor.rz.scp.css */
h1[b-3xxtam6d07] {
color: brown;
}
En tiempo de compilación, se crea un conjunto del proyecto con la convención obj/{CONFIGURATION}/{TARGET FRAMEWORK}/scopedcss/projectbundle/{ASSEMBLY NAME}.bundle.scp.css
, donde los marcadores de posición son:
{CONFIGURATION}
: la configuración de compilación de la aplicación (por ejemplo,Debug
,Release
).{TARGET FRAMEWORK}
: la plataforma de destino (por ejemplo,net6.0
).{ASSEMBLY NAME}
: el nombre del ensamblado de la aplicación (por ejemplo,BlazorSample
).
Compatibilidad de componente secundario
El aislamiento de CSS solo se aplica al componente que se asocia con el formato {COMPONENT NAME}.razor.css
, donde el marcador de posición {COMPONENT NAME}
suele ser el nombre del componente. Para aplicar cambios a un componente secundario, usa el ::deep
seudoelemento con los elementos descendientes del archivo .razor.css
del componente primario. El seudoelemento ::deep
selecciona los elementos que son descendientes del identificador de ámbito generado de un elemento.
En el ejemplo siguiente se muestra un componente primario denominado Parent
con un componente secundario denominado Child
.
Parent.razor
:
@page "/parent"
<div>
<h1>Parent component</h1>
<Child />
</div>
Child.razor
:
<h1>Child Component</h1>
Actualiza la declaración h1
de Parent.razor.css
con el seudoelemento ::deep
para indicar que la declaración de estilo de h1
debe aplicarse al componente primario y a sus elementos secundarios.
Parent.razor.css
:
::deep h1 {
color: red;
}
El estilo de h1
ahora se aplica a los componentes Parent
y Child
sin necesidad de crear un archivo CSS con ámbito independiente para el componente secundario.
El seudoelemento ::deep
solo funciona con elementos descendientes. El marcado siguiente aplica los estilos de h1
a los componentes según lo esperado. El identificador de ámbito del componente primario se aplica al elemento div
, por lo que se sabe que el explorador hereda los estilos del componente primario.
Parent.razor
:
<div>
<h1>Parent</h1>
<Child />
</div>
Sin embargo, si se excluye el elemento div
, se quita la relación descendiente. En el ejemplo siguiente, el estilo no se aplica al componente secundario.
Parent.razor
:
<h1>Parent</h1>
<Child />
El seudoelemento ::deep
afecta al lugar donde se aplica el atributo de ámbito a la regla. Al definir una regla CSS en un archivo CSS con ámbito, el ámbito se aplica al elemento situado más a la derecha. Por ejemplo: div > a
se transforma en div > a[b-{STRING}]
, donde el marcador de posición {STRING}
es una cadena de diez caracteres generada por el marco (por ejemplo, b-3xxtam6d07
). Si en su lugar deseas que la regla se aplique a un selector diferente, el seudoelemento ::deep
te permite hacerlo. Por ejemplo, div ::deep > a
se transforma en div[b-{STRING}] > a
(por ejemplo, div[b-3xxtam6d07] > a
).
La capacidad de asociar el seudoelemento ::deep
a cualquier elemento HTML permite crear estilos CSS con ámbito que afecten a los elementos representados por otros componentes cuando pueda determinar la estructura de las etiquetas HTML representadas. En el caso de un componente que represente una etiqueta de hipervínculo (<a>
) dentro de otro componente, asegúrese de que el componente esté encapsulado en un elemento div
(o cualquier otro elemento) y use la regla ::deep > a
para crear un estilo que solo se aplique a ese componente cuando se represente el componente primario.
Importante
CSS con ámbito solo se aplica a elementos HTML y no a componentes ni aplicaciones auxiliares de etiquetas Razor, incluidos los elementos con una aplicación auxiliar de etiquetas aplicada, como <input asp-for="..." />
.
Compatibilidad del preprocesador de CSS
Los preprocesadores de CSS son útiles para mejorar el desarrollo de CSS mediante el uso de características como variables, anidamiento, módulos, mixins y herencia. Aunque el aislamiento de CSS no admite de forma nativa preprocesadores de CSS como Sass o Less, la integración de preprocesadores de CSS se realiza sin problemas siempre que se produzca la compilación del preprocesador antes de que Blazor reescriba los selectores de CSS durante el proceso de compilación. Con Visual Studio, por ejemplo, configura la compilación del preprocesador existente como una tarea Antes de la compilación en el Explorador del Ejecutor de tareas de Visual Studio.
Muchos paquetes NuGet de terceros, como AspNetCore.SassCompiler
, pueden compilar archivos SASS/SCSS al principio del proceso de compilación antes de que se produzca el aislamiento de CSS.
Configuración del aislamiento de CSS
El aislamiento de CSS está diseñado para poder trabajar de inmediato, pero proporciona configuración para algunos escenarios avanzados, por ejemplo cuando hay dependencias en herramientas o flujos de trabajo existentes.
Personalización del formato del identificador de ámbito
Los identificadores de ámbito usan el formato b-{STRING}
, donde el marcador de posición {STRING}
es una cadena de diez caracteres generada por el marco. Para personalizar el formato de un identificador de ámbito, actualiza el archivo del proyecto a un patrón deseado:
<ItemGroup>
<None Update="Components/Pages/Example.razor.css" CssScope="custom-scope-identifier" />
</ItemGroup>
En el ejemplo anterior, el CSS generado para Example.razor.css
cambia su identificador de ámbito de b-{STRING}
a custom-scope-identifier
.
Usa identificadores de ámbito para lograr la herencia con archivos CSS de ámbito. En el siguiente ejemplo del archivo del proyecto, un archivo BaseComponent.razor.css
contiene estilos comunes en todos los componentes. Un archivo DerivedComponent.razor.css
hereda estos estilos.
<ItemGroup>
<None Update="Components/Pages/BaseComponent.razor.css" CssScope="custom-scope-identifier" />
<None Update="Components/Pages/DerivedComponent.razor.css" CssScope="custom-scope-identifier" />
</ItemGroup>
Usa el operador comodín (*
) para compartir los identificadores de ámbito en varios archivos:
<ItemGroup>
<None Update="Components/Pages/*.razor.css" CssScope="custom-scope-identifier" />
</ItemGroup>
Los identificadores de ámbito usan el formato b-{STRING}
, donde el marcador de posición {STRING}
es una cadena de diez caracteres generada por el marco. Para personalizar el formato de un identificador de ámbito, actualiza el archivo del proyecto a un patrón deseado:
<ItemGroup>
<None Update="Pages/Example.razor.css" CssScope="custom-scope-identifier" />
</ItemGroup>
En el ejemplo anterior, el CSS generado para Example.razor.css
cambia su identificador de ámbito de b-{STRING}
a custom-scope-identifier
.
Usa identificadores de ámbito para lograr la herencia con archivos CSS de ámbito. En el siguiente ejemplo del archivo del proyecto, un archivo BaseComponent.razor.css
contiene estilos comunes en todos los componentes. Un archivo DerivedComponent.razor.css
hereda estos estilos.
<ItemGroup>
<None Update="Pages/BaseComponent.razor.css" CssScope="custom-scope-identifier" />
<None Update="Pages/DerivedComponent.razor.css" CssScope="custom-scope-identifier" />
</ItemGroup>
Usa el operador comodín (*
) para compartir los identificadores de ámbito en varios archivos:
<ItemGroup>
<None Update="Pages/*.razor.css" CssScope="custom-scope-identifier" />
</ItemGroup>
Cambio de la ruta de acceso base de recursos web estáticos
El archivo scoped.styles.css
se genera en la raíz de la aplicación. En el archivo del proyecto, usa la <StaticWebAssetBasePath>
propiedad para cambiar la ruta de acceso predeterminada. En el ejemplo siguiente se coloca el archivo scoped.styles.css
, y el objeto rest de los recursos de la aplicación, en la ruta de acceso _content
:
<PropertyGroup>
<StaticWebAssetBasePath>_content/$(PackageId)</StaticWebAssetBasePath>
</PropertyGroup>
Deshabilitación de la unión automática
Para no usar el modo en que Blazor publica y carga archivos con ámbito en tiempo de ejecución, use la propiedad DisableScopedCssBundling
. Al usar esta propiedad, otras herramientas o procesos son responsables de tomar los archivos CSS aislados del directorio obj
y de publicarlos y cargarlos en tiempo de ejecución:
<PropertyGroup>
<DisableScopedCssBundling>true</DisableScopedCssBundling>
</PropertyGroup>
Deshabilitación del aislamiento de CSS
Deshabilita el aislamiento de CSS para un proyecto estableciendo la propiedad <ScopedCssEnabled>
en false
en el archivo de proyecto de la aplicación:
<ScopedCssEnabled>false</ScopedCssEnabled>
Razor Compatibilidad con la biblioteca de clases (RCL)
Los estilos aislados para los componentes de un paquete NuGet o la biblioteca de clases Razor (RCL) se agrupan automáticamente:
La aplicación usa importaciones CSS para hacer referencia a los estilos agrupados de la RCL. Para una biblioteca de clases denominada
ClassLib
y una aplicación Blazor con una hoja de estilosBlazorSample.styles.css
, la hoja de estilos de la RCL se importa automáticamente en la parte superior de la hoja de estilos de la aplicación:@import '_content/ClassLib/ClassLib.bundle.scp.css';
Los estilos agrupados de la RCL no se publican como recursos web estáticos de la aplicación que consume la biblioteca.
Para obtener más información sobre RCL, consulta los siguientes artículos:
- Consumo de componentes de ASP.NET Core Razor de bibliotecas de clases Razor (RCL)
- Interfaz de usuario reutilizable de Razor en bibliotecas de clases con ASP.NET Core