SCSS einbinden

Styles laufen über dieselbe Mechanik wie JavaScript, nur über die Schnittstelle IScssStyleProvider. Kompiliert wird zur Laufzeit von LigerShark.WebOptimizer.Sass.

Die Provider-Klasse

Ablage: src/FMH.Komponente.MeineKomponente/BundleKonfiguration/MeineKomponenteBundleScssSetup.cs

using System.Collections.Generic;
using FMH.Komponente.Infrastruktur.Bundle.Schnittstellen;

namespace FMH.Komponente.MeineKomponente.BundleKonfiguration;

public class MeineKomponenteBundleScssSetup : IScssStyleProvider
{
    public int Order => 100;

    public IEnumerable<string> GetScssPaths()
    {
        return new[] { "_content/FMH.Komponente.MeineKomponente/css/_meine-komponente.scss" };
    }
}

BundleName wird hier bewusst nicht gesetzt

Anders als bei JavaScript: Der Standardwert der Schnittstelle ist "fmh", und genau das ist das zentrale Stylebundle /bundle/fmh.css. Alle drei bestehenden SCSS-Provider (Basis, Tabelle, FileUpload) verzichten deshalb auf den Override.

Die Konstante BundleKonstanten.ScssBundleName hat denselben Wert, wird im Code aber nirgends verwendet. Wer sie schreibt, bekommt dasselbe Ergebnis, der kürzere Weg ist, die Eigenschaft wegzulassen.

fmh-bootstrap.css ist ein eigenes Bundle für Anpassungen an Bootstrap selbst und nicht der Ort für Komponenten-Styles.

Kompilierung

Nichts zu konfigurieren. AddBundledAssets() richtet die JavaScript-Engine ein, die der Sass-Compiler braucht; der Rest passiert in AddScssBundle. Es gibt weder eine appsettings-Sektion für WebOptimizer noch eigene Sass-Optionen.

Kompiliert wird bei der ersten Anfrage und danach im Arbeitsspeicher gehalten. Eine Änderung an einer .scss-Datei wird also ohne Neustart sichtbar, ein Vorteil gegenüber dem früheren WebCompiler-Ansatz mit eingecheckten .css-Dateien.

Gemischte Quellen sind erlaubt

In ein SCSS-Bundle dürfen auch fertige .css-Dateien. Beide bestehenden Komponenten nutzen das, um die Basis-Styles einer Fremdbibliothek vor die eigenen Anpassungen zu setzen:

public IEnumerable<string> GetScssPaths()
{
    return new[]
           {
               "_content/FMH.Komponente.FileUpload/lib/dropzone/dropzone.css",
               "_content/FMH.Komponente.FileUpload/css/_dropzone_override.scss"
           };
}

Partials und der Zugriff auf Variablen

Die Basis liefert genau eine Datei ans Bundle: css/style.scss. Alles Weitere zieht sie sich selbst über @use:

@use 'variables';
@use 'fonts';
@use 'corporate_design';

Eine Komponente listet ihre Partial dagegen direkt. Damit gilt: Variablen und Mixins der Basis stehen nicht automatisch zur Verfügung. Wer sie braucht, importiert sie in der eigenen Datei:

@use "../../FMH.Komponente.Basis/css/variables";
@use "../../FMH.Komponente.Basis/css/corporate_design";

Der Pfad zeigt auf die Static Web Assets der Basis, ist also nicht relativ zum Dateisystem des eigenen Projekts. Wizard, RichText und PDFViewer binden ihre Partials genau so ein.

Order bestimmt nur, an welcher Stelle der kompilierten Datei die eigenen Regeln landen, also wer bei gleicher Spezifität gewinnt:

Order Komponente Datei
0 RichText quill.snow.css, _richtext_override.scss
1 Basis style.scss
200 Tabelle _datatables.scss
250 Wizard _wizard.scss
300 FileUpload dropzone.css, _dropzone_override.scss
350 PDFViewer _document_viewer.scss

RichText steht bewusst vor der Basis, weil das Thema von Quill zuerst gelten und dann überschrieben werden soll. Für alles Übrige gilt: ein Wert über 1 sorgt dafür, dass die eigenen Regeln zuletzt greifen.

Wo eine Partial hingehört

Die Gestaltung liegt bei der Komponente, der die Selektoren gehören. Die Basis hält nur, was mehrere Komponenten teilen, Variablen, Corporate Design, Schriften und die allgemeinen Formularregeln der style.scss.

Die Faustregel dafür ist nachprüfbar: Wird eine Klasse ausschliesslich von einer Komponente gesetzt, gehört ihre Regel in diese Komponente. _wizard.scss (nur wz--Klassen), _richtext_override.scss (nur ql--Klassen), _document_viewer.scss (nur der DocumentViewer) und _dropzone_override.scss sind aus der Basis herausgelöst worden, weil sie diese Prüfung nicht bestanden haben.

Der Nebeneffekt zählt: Wer die Komponente nicht referenziert, bekommt ihre Regeln auch nicht ins Bundle.

Umgekehrt darf dieselbe Partial nicht zweimal existieren, einmal in der Basis und einmal in der Komponente. Beide landen im selben Bundle fmh.css und erzeugen doppelte Regeln. Beim Herauslösen also immer beides tun: Datei verschieben und das @use in der style.scss der Basis entfernen.