Eine dynamisch skalierbare, feste Seitenleiste mit HTML und CSS

Avatar of Ryan Mulligan
Ryan Mulligan am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Das Erstellen von Seiteninhalten, die beim Scrollen am Viewport haften bleiben, wie z. B. ein Sprungzielmenü oder Abschnittsüberschriften, war noch nie einfacher. Verwenden Sie position: sticky in Ihrer CSS-Regel, legen Sie den Richtungsabstand fest (z. B. top: 0) und schon sind Sie bereit, Ihre Teamkollegen mit minimalem Aufwand zu beeindrucken. Schauen Sie sich diesen CSS-Tricks-Artikel an, um einige wirklich ausgefallene Anwendungsfälle für die Positionierung von sticky zu sehen.

Aber die sticky-Positionierung kann etwas knifflig werden, insbesondere wenn es um die Höhe und die gefährliche Situation geht, Inhalte an einer Position zu verstecken, die nicht gescrollt werden kann. Lassen Sie mich die Bühne bereiten und Ihnen das Problem und meine Lösung zeigen.

Ich habe kürzlich an einem Desktop-Layout gearbeitet, das uns allen vertraut ist: ein Hauptinhaltsbereich mit einer Seitenleiste daneben. Diese spezielle Seitenleiste enthält Aktionsschaltflächen und Filter, die für den Hauptinhalt relevant sind. Wenn der Seitenabschnitt gescrollt wird, bleibt diese Komponente fest am Viewport und ist kontextbezogen zugänglich.

Das Layout-Styling war so einfach zu implementieren, wie ich es bereits erwähnt hatte. Aber es gab einen Haken: Die Höhe der Komponente würde je nach Inhalt variieren. Ich hätte sie mit max-height begrenzen und overflow-y: auto setzen können, um den Inhalt der Komponente scrollbar zu machen. Das funktionierte gut auf meinem Laptop-Bildschirm und meiner typischen Viewporthöhe, aber in einem kleineren Viewport mit weniger vertikalem Platz würde die Höhe der Seitenleiste den Viewport überschreiten.

Wenn die Höhe der festen Seitenleiste größer ist als der Viewport, sind einige ihrer Inhalte unzugänglich, bis zum Ende des Containers, wenn das Element nicht mehr fest ist.

Hier wurde es knifflig.

Lösungsansätze

Ich habe zunächst über eine Media-Query nachgedacht. Vielleicht könnte ich eine Media-Query verwenden, um die sticky-Positionierung zu entfernen und die Komponente relativ zur Oberseite des Seitenleisten-Containers zu positionieren. Dies würde den Zugriff auf den gesamten Inhalt ermöglichen. Andernfalls wird beim Scrollen der Seite der Inhalt der sticky-Komponente am unteren Rand des Viewports abgeschnitten, bis ich das Ende ihres übergeordneten Abschnitts erreiche.

Dann erinnerte ich mich, dass die Höhe der sticky-Komponente dynamisch ist.

Welchen magischen Wert könnte ich für meine Media-Query verwenden, um so etwas zu handhaben? Vielleicht könnte ich stattdessen eine JavaScript-Funktion schreiben, um zu prüfen, ob die Komponente beim Laden der Seite über die Viewport-Grenzen hinausfließt? Dann könnte ich die Höhe der Komponente aktualisieren…

Das war eine Möglichkeit.

Aber was ist, wenn der Benutzer sein Fenster verkleinert? Sollte ich dieselbe Funktion in einem resize-Event-Handler verwenden? Das fühlt sich nicht richtig an. Es muss einen besseren Weg geben, dies zu tun.

Es stellte sich heraus, dass es einen gab und er beinhaltete einige CSS-Tricks, um die Aufgabe zu erledigen!

Einrichtung des Seitenabschnitts

Ich begann mit einer flex-Anzeige auf dem Hauptelement. Ein flex-basis-Wert wurde der Seitenleiste für eine feste Desktop-Breite zugewiesen. Dann füllte das Artikel-Element den Rest des verfügbaren horizontalen Viewport-Platzes aus.

Wenn Sie neugierig sind, wie ich die beiden Container für kleinere Viewports ohne Media-Query gestapelt habe, schauen Sie sich The Flexbox Holy Albatross an.

Ich habe align-self: start zur Seitenleiste hinzugefügt, damit ihre Höhe nicht mit dem Hauptartikel gestreckt wird (stretch  ist der Standardwert). Dies gab meinen Positionierungseigenschaften die Möglichkeit, ihre Magie zu wirken.

.sidebar {
  --offset: var(--space);
  /* ... */
  position: sticky;
  top: var(--offset);
}

Schauen Sie sich das an! Mit diesen beiden CSS-Eigenschaften haftet das Seitenleisten-Element oben am Viewport mit einem Abstand, um ihm etwas Luft zum Atmen zu geben. Beachten Sie, dass der top-Wert auf eine bereichsspezifische CSS-Custom-Property gesetzt ist. Die Variable --offset kann nun auf jedem untergeordneten Element innerhalb der Seitenleiste wiederverwendet werden. Dies wird sich später als nützlich erweisen, wenn die maximale Höhe der sticky-Seitenleistenkomponente eingestellt wird.

Eine Liste globaler CSS-Variablen-Deklarationen finden Sie in der CodePen Demo, einschließlich der --space-Variable, die für den Offset-Wert in der :root-Regel verwendet wird.

Die feste Seitenleiste

Denken Sie daran, dass die Komponente selbst nicht sticky ist; es ist die Seitenleiste selbst. Allgemeine Layout- und Positionierungsaufgaben sollten normalerweise vom übergeordneten Element übernommen werden. Dies gibt der Komponente mehr Flexibilität und macht sie modularer für die Verwendung in anderen Bereichen der Anwendung.

Tauchen wir in die Anatomie dieser Komponente ein. In der Demo habe ich die dekorativen Eigenschaften unten entfernt, um mich auf die Layout-Stile zu konzentrieren.

.component {
  display: grid;
  grid-template-rows: auto 1fr auto;
}


.component .content {
  max-height: 500px;
  overflow-y: auto;
}
  • Diese Komponente verwendet CSS Grid und die Pancake Stack-Idee von 1-Line Layouts, um die Zeilen dieses Templates zu konfigurieren. Sowohl der Header als auch der Footer (auto) passen sich der Höhe ihrer Kinder an, während der Inhalt (1fr, oder eine Brucheinheit) den Rest des freien vertikalen Platzes ausfüllt.
  • Ein  max-height für den Inhalt begrenzt das Wachstum der Komponente auf größeren Bildschirmen. Dies ist unnötig, wenn es bevorzugt wird, dass die Komponente sich dehnt, um die Viewporthöhe auszufüllen.
  • overflow-y: auto ermöglicht das Scrollen des Inhalts, wenn nötig.

Wenn die Komponente in der Seitenleiste verwendet wird, ist ein max-height erforderlich, damit sie die Viewporthöhe nicht überschreitet. Der --offset, der zuvor für die .sidebar-Klasse galt, wird verdoppelt, um einen unteren Rand des Elements zu erzeugen, der dem oberen Abstand der sticky-Seitenleiste entspricht.

.sidebar .component {
  max-height: calc(100vh - var(--offset) * 2);
}

Das schließt die Montage dieser sticky-Seitenleistenkomponente ab! Nach dem Anbringen einiger dekorativer Stile wurde dieser Prototyp für Tests und Überprüfungen bereit. Probieren Sie es aus! Öffnen Sie die Demo in CodePen und klicken Sie auf die Rasterelemente, um sie zur Seitenleiste hinzuzufügen. Ändern Sie die Größe Ihres Browserfensters, um zu sehen, wie sich die Komponente mit dem Viewport mitbewegt und gleichzeitig sichtbar bleibt, während Sie den Hauptinhaltsbereich scrollen.


Dieses Layout funktioniert möglicherweise gut in einem Desktop-Browser, ist aber für kleinere Geräte oder Viewport-Breiten nicht ideal. Der Code hier bietet jedoch eine solide Grundlage, die es einfach macht, Verbesserungen an der Benutzeroberfläche vorzunehmen.

Eine einfache Idee: Eine Schaltfläche könnte am Viewport-Fenster befestigt werden, die beim Klicken die Seite zum Seitenleisten-Inhalt nach unten springen lässt. Eine andere Idee: Die Seitenleiste könnte außerhalb des Bildschirms versteckt werden und eine Umschalt-Schaltfläche könnte sie von links oder rechts herein schieben. Iteration und Benutzer-Tests werden helfen, diese Erfahrung in die richtige Richtung zu lenken.