Zum Inhalt springen
NativeCSS
Handbuch-Inhalt

Eigene Komponenten erstellen

Für ein Bauteil, das es in ncss noch gar nicht gibt (nicht nur eine Variante eines bestehenden - dafür reicht Einzelne Komponenten anpassen). Vier Entscheidungen machen eine eigene Komponente, die sich anfühlt wie eingebaut, statt wie ein Fremdkörper.

1. Eigenes Präfix statt ncss-

Das Präfix ncss- ist für die Bibliothek selbst reserviert - eine spätere ncss-Version könnte jederzeit eine neue Klasse namens ncss-stat-card einführen, die dann mit einer eigenen, gleichnamigen Klasse kollidiert. Eigenes, kurzes Projekt-Kürzel verwenden (z.B. mp- für "Mein Projekt"):

<div class="mp-stat-card">...</div>

Modifier-Klassen im selben Stil wie ncss selbst: mp-stat-card--compact (doppelter Bindestrich für eine Variante, wie .ncss-btn--primary), nicht zwingend, aber wiedererkennbar für alle, die schon mit ncss selbst arbeiten.

2. ncss-Tokens verwenden statt roher Werte

Farbe, Abstand, Radius, Schrift, Schatten, Bewegung - über var(--ncss-*) beziehen statt eigene Werte zu erfinden. Eine eigene Komponente zieht dadurch automatisch mit theme.css um (siehe Eigenes Theme erstellen), ohne dass sie selbst je wieder angefasst werden muss:

.mp-stat-card {
  padding: var(--ncss-space-md);
  border-radius: var(--ncss-radius-lg);
  background-color: var(--ncss-color-surface);
  box-shadow: var(--ncss-shadow-sm);
  color: var(--ncss-color-text);
}

Volle Token-Liste (Farben, Abstände, Radien, Schatten, Bewegung, Breakpoint-Konvention): Design Tokens.

3. In den bestehenden components-Layer einhängen

ncss.css deklariert die Cascade-Layer-Reihenfolge bereits seitenweit (tokens < reset < base < helpers < components < ..., siehe Architektur) - eine eigene Komponente hängt sich per @layer components { ... } einfach in den SCHON VORHANDENEN Layer-Namen ein, egal in welcher Datei oder <link>-Reihenfolge das passiert (Layer-Order ist global, nicht pro Stylesheet):

/* mp-stat-card.css - nach ncss.css laden */
@layer components {
  .mp-stat-card {
    padding: var(--ncss-space-md);
    border-radius: var(--ncss-radius-lg);
    background-color: var(--ncss-color-surface);
    box-shadow: var(--ncss-shadow-sm);
  }
}

Dadurch verhält sich die eigene Komponente GENAU wie eine eingebaute: allgemeine ncss-Utilities aus helpers/ (.ncss-border, .ncss-radius-*, .ncss-shadow-*, siehe Komponenten-Referenz) lassen sich frei damit kombinieren, weil helpers VOR components in der Layer-Reihenfolge steht - eine spätere Layer-Regel gewinnt immer gegen eine frühere, unabhängig von Selektor-Spezifität. Genau umgekehrt gilt das NICHT: eine helpers-Utility kann eine gleichnamige Eigenschaft aus components nicht überschreiben, selbst wenn die Utility-Klasse im Markup nach der Komponenten-Klasse steht (Layer-Reihenfolge schlägt Quelltext-Reihenfolge).

Unlayered nur für punktuelle Overrides, nicht für ganze Komponenten

Der theme.css-Trick (unlayered CSS, gewinnt immer) eignet sich für einzelne Eigenschaften einer BESTEHENDEN Komponente (siehe Schritt 7). Eine komplett neue, eigene Komponente unlayered zu deklarieren funktioniert zwar auch, verhindert aber, dass jemand sie später mit einer ncss-helpers-Utility kombiniert/anpasst - unlayered gewinnt gegen ALLES, auch gegen Utilities, die eigentlich gezielt etwas überschreiben sollen.

4. Container Queries statt Viewport-Breakpoints

ncss-Komponenten reagieren auf die Breite ihres EIGENEN Containers, nicht des Viewports - dieselbe Konvention für eine eigene Komponente übernehmen, damit sie sich überall gleich verhält, egal ob sie in einer schmalen Sidebar oder einer breiten Hauptspalte landet:

@layer components {
  .mp-stat-card {
    container-type: inline-size;
    container-name: mp-stat-card;
    padding: var(--ncss-space-md);
  }

  @container mp-stat-card (min-width: 20rem) {
    .mp-stat-card {
      display: flex;
      align-items: center;
      gap: var(--ncss-space-md);
    }
  }
}

Eigener container-name pro Komponente (nicht der generische Name eines fremden Containers) - sonst könnte eine verschachtelte fremde Komponente versehentlich auf die eigene Container-Query anspringen. Details: Layout.

Vollständiges Beispiel

Alle vier Punkte zusammen - eine kleine Kennzahl-Karte (Wert + Label + Trend-Icon), die sich ab einer bestimmten Breite von gestapelt auf nebeneinander umschaltet:

<div class="mp-stat-card">
  <span class="mp-stat-card-value">128</span>
  <span class="mp-stat-card-label">Neue Bestellungen</span>
</div>
@layer components {
  .mp-stat-card {
    container-type: inline-size;
    container-name: mp-stat-card;
    display: grid;
    gap: var(--ncss-space-3xs);
    padding: var(--ncss-space-md);
    border-radius: var(--ncss-radius-lg);
    background-color: var(--ncss-color-surface);
    box-shadow: var(--ncss-shadow-sm);
  }
  .mp-stat-card-value {
    font-size: var(--ncss-font-size-xl);
    font-weight: 700;
    color: var(--ncss-color-brand-on-soft);
  }
  .mp-stat-card-label {
    font-size: var(--ncss-font-size-sm);
    color: var(--ncss-color-text-muted);
  }

  @container mp-stat-card (min-width: 16rem) {
    .mp-stat-card {
      grid-template-columns: auto 1fr;
      align-items: baseline;
      gap: var(--ncss-space-sm);
    }
  }
}

Mit ncss-Utilities frei kombinierbar, weil components nach helpers in der Layer-Reihenfolge steht: class="mp-stat-card ncss-border ncss-shadow-hover-md" ergänzt Rahmen + Hover-Schatten, ohne eine Zeile der eigenen Datei anzufassen.

Datei-Organisation

Eigene Komponenten-Dateien nach demselben Muster wie ncss selbst - eine Datei pro Komponente, z.B. assets/components/stat-card.css, im HTML NACH ncss.css/theme.css laden (reine Lesbarkeits-Konvention, technisch nicht zwingend, da Layer-Reihenfolge bereits durch ncss.csss @layer-Zeile seitenweit fixiert ist, unabhängig von <link>-Reihenfolge):

<link rel="stylesheet" href="ncss.css">
<link rel="stylesheet" href="theme.css">
<link rel="stylesheet" href="components/stat-card.css">

Allgemein genug für andere Projekte? Als Pull Request auf github.com/skerbis/nativecss willkommen - dann mit ncss--Präfix statt des eigenen Projekt-Kürzels.