Isolation CSS ASP.NET Core Blazor

Remarque

Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 8 de cet article.

Important

Ces informations portent sur la préversion du produit, qui est susceptible d’être en grande partie modifié avant sa commercialisation. Microsoft n’offre aucune garantie, expresse ou implicite, concernant les informations fournies ici.

Pour la version actuelle, consultez la version .NET 8 de cet article.

Par Dave Brock

Cet article explique comment l’isolation CSS permet d’étendre les CSS aux composants Razor, ce qui peut simplifier les CSS et éviter les collisions avec d’autres composants ou bibliothèques.

Isolez les styles CSS en pages, vues et composants individuels afin de réduire ou d’éviter :

  • Les dépendances sur les styles globaux qui peuvent être difficiles à gérer.
  • Les conflits de style dans du contenu imbriqué.

Activez l’isolation CSS

Pour définir des styles spécifiques au composant, créez un fichier .razor.css correspondant au nom du fichier .razor du composant dans le même dossier. Le fichier .razor.css est un fichier CSS délimité.

Pour un composant Example dans un fichier Example.razor, créez un fichier à côté du composant nommé Example.razor.css. Le fichier Example.razor.css doit résider dans le même dossier que le composant Example (Example.razor). Le nom de base « Example » du fichier ne respecte pas la casse.

Example.razor:

@page "/example"

<h1>Scoped CSS Example</h1>

Example.razor.css:

h1 { 
    color: brown;
    font-family: Tahoma, Geneva, Verdana, sans-serif;
}

Les styles définis dans Example.razor.css sont uniquement appliqués à la sortie rendue du composant Example. L’isolation CSS est appliquée aux éléments HTML dans le fichier Razor correspondant. Les déclarations CSS h1 définies ailleurs dans l’application ne sont pas en conflit avec les styles du composant Example.

Remarque

Pour garantir l’isolation du style lors du regroupement, l’importation de CSS dans des blocs de code Razor n’est pas prise en charge.

Regroupement d’isolation CSS

L’isolation CSS se produit au moment de la build. Blazor réécrit les sélecteurs CSS pour qu’ils correspondent aux balises rendues par le composant. Les styles CSS réécrits sont regroupés et produits sous la forme d’une ressource statique. La feuille de style est référencée à l’intérieur de la balise <head> (emplacement du <head> contenu). L’élément suivant <link> est ajouté par défaut à une application créée à partir des modèles de projet Blazor, où l’espace réservé {ASSEMBLY NAME} est le nom de l’assembly du projet :

<link href="{ASSEMBLY NAME}.styles.css" rel="stylesheet">

L’exemple suivant provient d’une application hébergée Blazor WebAssemblyClient. Le nom de l’assembly de l’application est BlazorSample.Client, et <link> est ajouté par le modèle de projet Blazor WebAssembly lorsque le projet est créé avec l’option Hébergé (option -ho|--hosted à l’aide de l’interface de ligne de commande .NET ou la case à cocher ASP.NET Core Hébergé à l’aide de Visual Studio) :

<link href="BlazorSample.Client.styles.css" rel="stylesheet">

Dans le fichier groupé, chaque composant est associé à un identificateur d’étendue. Pour chaque composant de style, un attribut HTML est ajouté au format b-{STRING}, où l’espace réservé {STRING} est une chaîne de dix caractères générée par l’infrastructure. L’identificateur est unique pour chaque application. Dans le composant rendu Counter, Blazor ajoute un identificateur d’étendue à l’élément h1 :

<h1 b-3xxtam6d07>

Le fichier {ASSEMBLY NAME}.styles.css utilise l’identificateur d’étendue pour regrouper une déclaration de style avec son composant. L’exemple suivant fournit le style pour l’élément <h1> précédent :

/* /Components/Pages/Counter.razor.rz.scp.css */
h1[b-3xxtam6d07] {
    color: brown;
}

Au moment de la génération, un ensemble de projets est créé avec la convention obj/{CONFIGURATION}/{TARGET FRAMEWORK}/scopedcss/projectbundle/{ASSEMBLY NAME}.bundle.scp.css, où sont les espaces réservés :

  • {CONFIGURATION} : la configuration de build de l’application (par exemple, Debug, Release).
  • {TARGET FRAMEWORK} : l’infrastructure cible (par exemple, net6.0).
  • {ASSEMBLY NAME} : le nom de l’assembly de l’application (par exemple, BlazorSample).

Prise en charge des composants enfants

Par défaut, l’isolation CSS s’applique uniquement au composant que vous associez au format {COMPONENT NAME}.razor.css, où l’espace réservé {COMPONENT NAME} est généralement le nom du composant. Pour appliquer des modifications à un composant enfant, utilisez le ::deeppseudo-élément pour tous les éléments descendants dans le fichier .razor.css du composant parent. Le pseudo-élément ::deep sélectionne les éléments descendants de l’identificateur d’étendue généré d’un élément.

L’exemple suivant montre un composant parent appelé Parent avec un composant enfant appelé Child.

Parent.razor:

@page "/parent"

<div>
    <h1>Parent component</h1>

    <Child />
</div>

Child.razor:

<h1>Child Component</h1>

Mettez à jour la déclaration h1 dans Parent.razor.css avec le pseudo-élément ::deep pour signifier que la déclaration de style h1 doit s’appliquer au composant parent et à ses enfants.

Parent.razor.css:

::deep h1 { 
    color: red;
}

Le style h1 s’applique désormais aux composants Parent et Child sans avoir besoin de créer un fichier CSS délimité distinct pour le composant enfant.

Le pseudo-élément ::deep fonctionne uniquement avec les éléments descendants. La balise suivante applique les styles h1 aux composants comme prévu. L’identificateur d’étendue du composant parent est appliqué à l’élément div, afin que le navigateur sache hériter des styles du composant parent.

Parent.razor:

<div>
    <h1>Parent</h1>

    <Child />
</div>

Toutefois, l’exclusion de l’élément div supprime la relation descendante. Dans l’exemple suivant, le style n’est pas appliqué au composant enfant.

Parent.razor:

<h1>Parent</h1>

<Child />

Le pseudo-élément ::deep affecte l’emplacement où l’attribut d’étendue est appliqué à la règle. Lorsque vous définissez une règle CSS dans un fichier CSS délimité, l’étendue est appliquée à l’élément le plus à droite par défaut. Par exemple : div > a est transformé en div > a[b-{STRING}], où l’espace réservé {STRING} est une chaîne de dix caractères générée par l’infrastructure (par exemple, b-3xxtam6d07). Si vous souhaitez plutôt que la règle s’applique à un autre sélecteur, le pseudo-élément ::deep vous permet de le faire. Par exemple, div ::deep > a est transformé en div[b-{STRING}] > a (par exemple, div[b-3xxtam6d07] > a).

La possibilité d’attacher le pseudo-élément ::deep à n’importe quel élément HTML vous permet de créer des styles CSS délimités qui affectent les éléments rendus par d’autres composants lorsque vous pouvez déterminer la structure des balises HTML rendues. Pour un composant qui affiche une balise de lien hypertexte (<a>) à l’intérieur d’un autre composant, vérifiez que le composant est enveloppé dans un div (ou tout autre élément) et utilisez la règle ::deep > a pour créer un style qui n’est appliqué à ce composant que lorsque le composant parent s’affiche.

Important

Le CSS délimité s’applique uniquement aux éléments HTML et non aux composants Razor ou aux assistants de balise, y compris les éléments auxquels un assistant de balise a été appliqué, tels que <input asp-for="..." />.

Prise en charge des préprocesseurs CSS

Les préprocesseurs CSS sont utiles pour améliorer le développement CSS en utilisant des fonctionnalités comme les variables, l’imbrication, les modules, les mixins et l’héritage. Bien que l’isolation CSS ne prenne pas nativement en charge les préprocesseurs CSS comme Sass ou Less, l’intégration de préprocesseurs CSS se fait de manière fluide dès lors que la compilation du préprocesseur se produit avant que Blazor ne réécrive les sélecteurs CSS lors du processus de build. Par exemple, avec Visual Studio, configurez la compilation du préprocesseur existant en tant que tâche Avant la build dans l’Explorateur d’exécuteur de tâches Visual Studio.

De nombreux packages NuGet tiers, comme AspNetCore.SassCompiler, peuvent compiler des fichiers SASS/SCSS au début du processus de build avant que l’isolation CSS ne se produise.

Configuration de l’isolation CSS

L’isolation CSS est conçue pour fonctionner en l’état, mais permet de configurer certains scénarios avancés, notamment lorsqu’il existe des dépendances avec des outils ou des flux de travail existants.

Personnaliser le format de l’identificateur d’étendue

Par défaut, les identificateurs d’étendue utilisent le format b-{STRING}, où l’espace réservé {STRING} est une chaîne de dix caractères générée par le framework. Pour personnaliser le format de l’identificateur d’étendue, mettez à jour le fichier projet avec un modèle souhaité :

<ItemGroup>
  <None Update="Components/Pages/Example.razor.css" CssScope="custom-scope-identifier" />
</ItemGroup>

Dans l’exemple précédent, le CSS généré pour Example.razor.css change son identificateur d’étendue de b-{STRING} en custom-scope-identifier.

Utilisez des identificateurs d’étendue pour mettre en œuvre l’héritage avec des fichiers CSS délimités. Dans l’exemple de Fichier projet suivant, un fichier BaseComponent.razor.css contient des styles communs entre les composants. Un fichier DerivedComponent.razor.css hérite de ces styles.

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

Utilisez l’opérateur de caractère générique (*) pour partager des identificateurs d’étendue entre plusieurs fichiers :

<ItemGroup>
  <None Update="Components/Pages/*.razor.css" CssScope="custom-scope-identifier" />
</ItemGroup>

Par défaut, les identificateurs d’étendue utilisent le format b-{STRING}, où l’espace réservé {STRING} est une chaîne de dix caractères générée par le framework. Pour personnaliser le format de l’identificateur d’étendue, mettez à jour le fichier projet avec un modèle souhaité :

<ItemGroup>
  <None Update="Pages/Example.razor.css" CssScope="custom-scope-identifier" />
</ItemGroup>

Dans l’exemple précédent, le CSS généré pour Example.razor.css change son identificateur d’étendue de b-{STRING} en custom-scope-identifier.

Utilisez des identificateurs d’étendue pour mettre en œuvre l’héritage avec des fichiers CSS délimités. Dans l’exemple de Fichier projet suivant, un fichier BaseComponent.razor.css contient des styles communs entre les composants. Un fichier DerivedComponent.razor.css hérite de ces styles.

<ItemGroup>
  <None Update="Pages/BaseComponent.razor.css" CssScope="custom-scope-identifier" />
  <None Update="Pages/DerivedComponent.razor.css" CssScope="custom-scope-identifier" />
</ItemGroup>

Utilisez l’opérateur de caractère générique (*) pour partager des identificateurs d’étendue entre plusieurs fichiers :

<ItemGroup>
  <None Update="Pages/*.razor.css" CssScope="custom-scope-identifier" />
</ItemGroup>

Changer le chemin de base pour les ressources web statiques

Le fichier scoped.styles.css est généré à la racine de l’application. Dans le Fichier projet, utilisez la <StaticWebAssetBasePath> propriété pour changer le chemin d’accès par défaut. L’exemple suivant place le fichier scoped.styles.css et le reste des ressources de l’application dans le chemin d’accès _content :

<PropertyGroup>
  <StaticWebAssetBasePath>_content/$(PackageId)</StaticWebAssetBasePath>
</PropertyGroup>

Désactiver le regroupement automatique

Pour ne pas accepter la façon dont Blazor publie et charge des fichiers délimités au moment de l’exécution, utilisez la propriété DisableScopedCssBundling. Lors de l’utilisation de cette propriété, cela signifie que d’autres outils ou processus sont chargés de prendre les fichiers CSS isolés du répertoire obj, et de les publier et de les charger au moment de l’exécution :

<PropertyGroup>
  <DisableScopedCssBundling>true</DisableScopedCssBundling>
</PropertyGroup>

Désactivez l’isolation CSS

Désactivez l’isolation CSS pour un projet en définissant la propriété <ScopedCssEnabled> sur false dans le Fichier projet de l’application :

<ScopedCssEnabled>false</ScopedCssEnabled>

Prise en charge de la bibliothèque de classes Razor (RCL)

Les styles isolés pour les composants d’un package NuGet ou d’une bibliothèque de classes Razor (RCL) sont automatiquement regroupés :

  • L’application utilise des importations CSS pour référencer les styles groupés de la RCL. Pour une bibliothèque de classes nommée ClassLib et une application Blazor avec une feuille de style BlazorSample.styles.css, la feuille de style RCL est importée en haut de la feuille de style de l’application :

    @import '_content/ClassLib/ClassLib.bundle.scp.css';
    
  • Les styles groupés de la RCL ne sont pas publiés en tant que ressource web statique de l’application qui consomme les styles.

Pour plus d’informations sur les bibliothèques de classes Razor, consultez les articles suivants :

Ressources supplémentaires