Delen via


ASP.NET Core Blazor CSS-isolatie

Opmerking

Dit is niet de nieuwste versie van dit artikel. Zie de .NET 9-versie van dit artikel voor de huidige release.

Waarschuwing

Deze versie van ASP.NET Core wordt niet meer ondersteund. Zie het .NET- en .NET Core-ondersteuningsbeleid voor meer informatie. Zie de .NET 9-versie van dit artikel voor de huidige release.

Belangrijk

Deze informatie heeft betrekking op een pre-releaseproduct dat aanzienlijk kan worden gewijzigd voordat het commercieel wordt uitgebracht. Microsoft geeft geen garanties, uitdrukkelijk of impliciet, met betrekking tot de informatie die hier wordt verstrekt.

Zie de .NET 9-versie van dit artikel voor de huidige release.

Door Dave Brock

In dit artikel wordt uitgelegd hoe CSS-isolatie css beperkt tot Razor onderdelen, waardoor CSS kan worden vereenvoudigd en conflicten met andere onderdelen of bibliotheken kunnen worden voorkomen.

Isoleer CSS-stijlen voor afzonderlijke pagina's, weergaven en onderdelen om het aantal te verminderen of te voorkomen:

  • Afhankelijkheden van globale stijlen die lastig kunnen worden onderhouden.
  • Stijlconflicten in geneste inhoud.

CSS-isolatie inschakelen

Als u onderdeelspecifieke stijlen wilt definiëren, maakt u een .razor.css bestand dat overeenkomt met de naam van het .razor bestand voor het onderdeel in dezelfde map. Het .razor.css bestand is een scoped CSS-bestand.

Maak voor een Example onderdeel in een Example.razor bestand een bestand naast het onderdeel met de naam Example.razor.css. Het Example.razor.css bestand moet zich in dezelfde map bevinden als het Example onderdeel (Example.razor). De basisnaamExample van het bestand is niet hoofdlettergevoelig.

Example.razor:

@page "/example"

<h1>Scoped CSS Example</h1>

Example.razor.css:

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

De stijlen die in Example.razor.css zijn gedefinieerd, worden alleen toegepast op de weergegeven uitvoer van de Example component. CSS-isolatie wordt toegepast op HTML-elementen in het overeenkomende Razor bestand. Css-declaraties h1 die elders in de app zijn gedefinieerd, conflicteren niet met de stijlen van het Example onderdeel.

Opmerking

Om stijlisolatie te garanderen wanneer bundeling plaatsvindt, wordt het importeren van CSS in Razor codeblokken niet ondersteund.

CSS-isolatiebundeling

CSS-isolatie vindt plaats tijdens de build. Blazor herschrijft CSS-selectors zodat deze overeenkomen met de opmaak die door het onderdeel wordt weergegeven. De herschreven CSS-stijlen worden gebundeld en geproduceerd als een statische asset. Er wordt naar het opmaakmodel verwezen in de <head> tag (locatie van <head> inhoud). Het volgende <link> element wordt toegevoegd aan een app die is gemaakt op basis van de Blazor projectsjablonen:

Blazor Web App s:

<link href="@Assets["{PACKAGE ID/ASSEMBLY NAME}.styles.css"]" rel="stylesheet">

Zelfstandige Blazor WebAssembly-apps:

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

De {PACKAGE ID/ASSEMBLY NAME} placeholder is de pakket-id van het project (<PackageId> in het projectbestand) voor een library- of assemblynaam voor een app.

Het volgende voorbeeld is afkomstig van een gehoste Blazor WebAssemblyClient app. De assemblynaam van de app is BlazorSample.Client, en de <link> wordt toegevoegd door de Blazor WebAssembly projectsjabloon wanneer het project wordt gemaakt met de Gehost-optie (-ho|--hosted optie met de .NET CLI of ASP.NET Core Gehost met Visual Studio):

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

In het gebundelde bestand wordt elk onderdeel gekoppeld aan een bereik-id. Voor elke gestyled component wordt een HTML-kenmerk toegevoegd met het formaat b-{STRING}, waarbij de {STRING} tijdelijke aanduiding een tekenreeks van tien tekens is die door het framework wordt gegenereerd. De id is uniek voor elke app. In het gerenderde Counter-onderdeel wordt een scope-identificatie toegevoegd aan het h1-element door Blazor.

<h1 b-3xxtam6d07>

Het {PACKAGE ID/ASSEMBLY NAME}.styles.css bestand gebruikt de bereik-id om een stijldeclaratie met het bijbehorende onderdeel te groeperen. In het volgende voorbeeld ziet u de stijl voor het voorgaande <h1> element:

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

Tijdens de build wordt een projectbundel gemaakt met de conventie obj/{CONFIGURATION}/{TARGET FRAMEWORK}/scopedcss/projectbundle/{PACKAGE ID/ASSEMBLY NAME}.bundle.scp.css, waarbij de plaatsaanduidingen zijn:

  • {CONFIGURATION}: de buildconfiguratie van de app (bijvoorbeeld Debug, Release).
  • {TARGET FRAMEWORK}: Het doelframework (bijvoorbeeld net6.0).
  • {PACKAGE ID/ASSEMBLY NAME}: de pakket-id van het project (<PackageId> in het projectbestand) voor een bibliotheek- of assemblynaam voor een app (bijvoorbeeld BlazorSample).

Ondersteuning voor kindonderdelen

CSS-isolatie is alleen van toepassing op het onderdeel dat u koppelt aan de indeling {COMPONENT NAME}.razor.css, waarbij de {COMPONENT NAME} tijdelijke aanduiding meestal de onderdeelnaam is. Als u wijzigingen wilt toepassen op een subcomponent, gebruikt u het ::deeppseudo-element op elk afstammend element in het bestand van de bovenliggende component. Het ::deep pseudo-element selecteert elementen die afstammelingen zijn van de gegenereerde bereik-id van een element.

In het volgende voorbeeld ziet u een bovenliggend onderdeel Parent met een onderliggend onderdeel Child.

Parent.razor:

@page "/parent"

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

    <Child />
</div>

Child.razor:

<h1>Child Component</h1>

Werk de h1-declaratie in Parent.razor.css bij met het ::deep pseudo-element, zodat de h1 stijldeclaratie van toepassing is op het oudercomponent en diens kindelementen.

Parent.razor.css:

::deep h1 { 
    color: red;
}

De h1 stijl is nu van toepassing op de Parent en Child onderdelen zonder dat u een afzonderlijk CSS-bereikbestand hoeft te maken voor het onderliggende onderdeel.

Het ::deep pseudo-element werkt alleen met onderliggende elementen. Met de volgende markeringen worden de h1 stijlen toegepast op onderdelen zoals verwacht. De bereik-id van het bovenliggende onderdeel wordt toegepast op het div element, dus de browser weet stijlen over te nemen van het bovenliggende onderdeel.

Parent.razor:

<div>
    <h1>Parent</h1>

    <Child />
</div>

Als u echter het div element uitsluit, wordt de onderliggende relatie verwijderd. In het volgende voorbeeld wordt de stijl niet toegepast op het kindonderdeel.

Parent.razor:

<h1>Parent</h1>

<Child />

Het ::deep pseudo-element beïnvloedt waar het bereikkenmerk wordt toegepast op de regel. Wanneer u een CSS-regel definieert in een CSS-bereikbestand, wordt het bereik toegepast op het juiste element. Bijvoorbeeld: div > a wordt getransformeerd naar div > a[b-{STRING}], waarbij de {STRING} tijdelijke aanduiding een tekenreeks van tien tekens is die wordt gegenereerd door het framework (bijvoorbeeld b-3xxtam6d07). Als u in plaats daarvan wilt dat de regel wordt toegepast op een andere selector, kunt u dit doen met het ::deep pseudo-element. Wordt bijvoorbeeld div ::deep > a getransformeerd naar div[b-{STRING}] > a (bijvoorbeeld div[b-3xxtam6d07] > a).

Met de mogelijkheid om het ::deep pseudo-element aan elk HTML-element toe te voegen, kunt u css-stijlen maken die van invloed zijn op elementen die door andere onderdelen worden weergegeven wanneer u de structuur van de weergegeven HTML-tags kunt bepalen. Voor een onderdeel dat een hyperlinktag (<a>) in een ander onderdeel weergeeft, moet u ervoor zorgen dat het onderdeel is verpakt in een div (of een ander element) en gebruikt u de regel ::deep > a om een stijl te maken die alleen op dat onderdeel wordt toegepast wanneer het bovenliggende onderdeel wordt weergegeven.

Belangrijk

Scoped CSS is alleen van toepassing op HTML-elementen en niet op Razor onderdelen of Tag Helpers, inclusief elementen waarop een Tag Helper is toegepast, zoals <input asp-for="..." />.

Ondersteuning voor CSS-preprocessor

CSS-preprocessors zijn handig voor het verbeteren van CSS-ontwikkeling door gebruik te maken van functies zoals variabelen, nesten, modules, mixins en overname. Hoewel CSS-isolatie geen systeemeigen ondersteuning biedt voor CSS-preprocessors, zoals Sass of Less, is het integreren van CSS-preprocessors naadloos zolang preprocessorcompilatie plaatsvindt voordat Blazor de CSS-selectors tijdens het buildproces opnieuw worden geschreven. Met Visual Studio configureert u bijvoorbeeld bestaande preprocessorcompilatie als een before build-taak in de Visual Studio Task Runner Explorer.

Veel NuGet-pakketten van derden, zoals AspNetCore.SassCompiler, kunnen SASS-/SCSS-bestanden compileren aan het begin van het buildproces voordat CSS-isolatie plaatsvindt.

CSS-isolatieconfiguratie

CSS-isolatie is ontworpen om kant-en-klaar te werken, maar biedt configuratie voor sommige geavanceerde scenario's, zoals wanneer er afhankelijkheden zijn van bestaande hulpprogramma's of werkstromen.

Indeling van bereik-ID aanpassen

Scope-identificatoren gebruiken de specificatie b-{STRING}, waarbij de {STRING}-plaatsaanduiding een tekenreeks van tien tekens is die door het framework wordt gegenereerd. Als u de indeling van de scope-id wilt aanpassen, werkt u het projectbestand bij naar een gewenst patroon:

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

In het voorgaande voorbeeld verandert de gegenereerde CSS voor Example.razor.css de scope-identificatie van b-{STRING} naar custom-scope-identifier.

Gebruik scope-identificatoren om overerving te bereiken met gescopeerde CSS-bestanden. In het volgende voorbeeld van een projectbestand bevat een BaseComponent.razor.css bestand algemene stijlen voor alle onderdelen. Een DerivedComponent.razor.css bestand neemt deze stijlen over.

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

Gebruik de wildcard (*) operator om scope-identificators te delen tussen meerdere bestanden:

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

Bereik-ID's gebruiken de notatie b-{STRING}, waarbij de {STRING} tijdelijke aanduiding een tekenreeks met een lengte van tien tekens is die door het framework wordt gegenereerd. Als u de indeling van de scope-id wilt aanpassen, werkt u het projectbestand bij naar een gewenst patroon:

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

In het voorgaande voorbeeld verandert de gegenereerde CSS voor Example.razor.css de scope-identificatie van b-{STRING} naar custom-scope-identifier.

Gebruik scope-identificatoren om overerving te bereiken met gescopeerde CSS-bestanden. In het volgende voorbeeld van een projectbestand bevat een BaseComponent.razor.css bestand algemene stijlen voor alle onderdelen. Een DerivedComponent.razor.css bestand neemt deze stijlen over.

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

Gebruik de wildcard (*) operator om scope-identificators te delen tussen meerdere bestanden:

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

Basispad voor statische webassets wijzigen

Het scoped.styles.css bestand wordt gegenereerd in de hoofdmap van de app. Gebruik de <StaticWebAssetBasePath> eigenschap in het projectbestand om het standaardpad te wijzigen. In het volgende voorbeeld worden het scoped.styles.css bestand en de rest van de assets van de app op het _content pad weergegeven:

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

Automatische bundeling uitschakelen

Als u zich wilt afmelden voor het Blazor publiceren en laden van scoped bestanden tijdens runtime, gebruikt u de DisableScopedCssBundling eigenschap. Wanneer u deze eigenschap gebruikt, betekent dit dat andere hulpprogramma's of processen verantwoordelijk zijn voor het nemen van de geïsoleerde CSS-bestanden uit de obj map en het publiceren en laden ervan tijdens runtime:

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

CSS-isolatie uitschakelen

Schakel CSS-isolatie voor een project uit door de <ScopedCssEnabled> eigenschap false in te stellen in het projectbestand van de app:

<ScopedCssEnabled>false</ScopedCssEnabled>

Razor ondersteuning voor klassebibliotheek (RCL)

Geïsoleerde stijlen voor onderdelen in een NuGet-pakket of Razor klassebibliotheek (RCL) worden automatisch gebundeld:

  • De app maakt gebruik van CSS-importbewerkingen om te verwijzen naar de gebundelde stijlen van de RCL. Voor een klassebibliotheek met de naam ClassLib en een Blazor app met een BlazorSample.styles.css opmaakmodel wordt het opmaakmodel van de RCL boven aan het opmaakmodel van de app geïmporteerd:

    @import '_content/ClassLib/ClassLib.bundle.scp.css';
    
  • De gebundelde stijlen van de RCL worden niet gepubliceerd als een statische webasset van de app die de stijlen gebruikt.

Zie de volgende artikelen voor meer informatie over RCL's:

Aanvullende bronnen