OnePager

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Single-Page-Webseiten oder OnePager (auch als pageless Design bekannt) sind gerade für Web-Visitenkarten, Landing Pages und kleinere Projekte perfekt geeignet.

Bei Single-Page-Webseiten wird der Inhalt nicht auf mehrere kurze Seiten verteilt, sondern auf einer einzigen "langen" Seite sofort geladen und durch Scrollen oder Navigieren ohne weiteren HTTP-Request eingeblendet.

Für die Kompaktvariante spricht,

  • dass die Latenzzeiten in Mobilfunknetzen bei mehreren Dateien zu einem verzögertem Laden führen, so dass es vorteilhaft ist, alles zusammen in einem HTTP-Request zu haben.

Für Einzeldateien spricht:

  • ein gemeinsames Bild der ganzen Webseite, oder EIN Stylesheet für OnePager und andere Seiten braucht nicht immer geladen zu werden.
    Wird es einmal aufgerufen, kann es vom lokalen Cache geladen werden.

Allerdings wird der potentielle Geschwindigkeitsvorteil von OnePagern durch den Einsatz von Frameworks oft in sein Gegenteil verkehrt, wenn erst mehrere MB geladen werden müssen, um die Funktionalität einer einzelnen Seite herzustellen. In diesen Beispielen zeigen wir, wie man eine solche Seite nur mit CSS (und ein bisschen JavaScript für den Komfort) realisiert.

Basis-Version

OnePager sind sinnvoll, wenn es einen klar umrissenen Inhalt von einigen Abschnitten gibt. Das kann eine Landing Page, eine Web-Visitenkarte oder eine Präsentation eines neuen Produkts oder einer Recherche sein. Umfangreichere Webprojekte oder nicht thematisch zusammengehörende Seiten sollten besser mit klassischen Einzelseiten realisiert werden.[1][2][3]

Die Bedienung eines One-Pagers sollte so einfach wie möglich sein. Das Scrollen mit Maus und Wischgeste führt die Benutzer intuitiv zu weiteren Inhalten. Trotzdem sollte es in den einzelnen Bereichen Wegweiser für die weitere Nutzung geben - besonders wenn es mehrere Möglichkeiten gibt - wie z. B. ein mögliches horizontales Scrollen zur Seite.

HTML-Grundstruktur

Diese Webseite besteht aus mehreren Seiten(bereichen), die in section-Elementen untereinander notiert sind. Diese werden mit einer eindeutigen id ausgezeichnet und erhalten zusätzlich einen tabindex, damit sie auch mit der Tastatur angesteuert werden können.

HTML-Grundstruktur
    <section id="part_1" tabindex="1">
      <h2>Webdesign</h2>

        ...
    </section>

    <section id="part_2" tabindex="2">
      <h2>HTML</h2>

        ...
    </section>
  <section id="part_3"  tabindex="3">
    <h2>CSS</h2>
      ...

...

<nav>	
	<ul id="navigation">
		<li><a href="#part_1">Webdesign</a></li>
		<li><a href="#part_2">HTML</a></li>
		<li><a href="#part_3">CSS</a></li>
	</ul>
</nav>

Die Navigation besteht aus internen Ankern, die auf diese id-Anker referenzieren.

Scroll Snap

Benutzer, die auf mobilen Geräten mit Touchscreen surfen, sind es gewohnt weitere Inhalte mit einem Wisch in den sichtbaren Bereich zu holen. Deshalb sollen die einzelnen Sektionen im nächsten Beispiel untereinander in ihrer normalen Reihenfolge angeordnet werden. Ein Wisch (oder eine Mausbewegung oder ein Klick in der Navigation) verschiebt den Inhalt und führt zum nächsten Abschnitt. Schön wäre, wenn nicht impulsiv bis zum Seitenende gescrollt wird, sondern an der nächsten Überschrift automatisch angehalten werden kann.

Diese Technologie nennt sich Scroll Snap. Beim Scrollen rastet der Browser an bestimmten Stellen im Layout ein, wenn über diese Punkte hinweg gescrollt werden soll. Während dies früher den Einsatz von JavaScript und jQuery erforderte, reicht heute allein CSS.

Scroll Snap benötigt einen Scroll-Container, in dem gescrollt werden soll und mehrere Kindelemente, die verschiebbar sein sollen.[4]


OnePager mit Scroll Snap ansehen …
@media screen and (prefers-reduced-motion: no-preference) and (height > 22em) {
  html {
    margin: 0;
    scroll-snap-type: y mandatory; 
    scroll-behavior: smooth;
    scroll-padding: 0; /* nicht nötig */
  }

  section {
    height: 100vh;
    scroll-snap-align: start; 
    scroll-margin: 0;  /* nicht nötig */
  }
}

Der body hat 2 neue Regelsätze:

  • scroll-snap-type hat 2 Parameter:
    • y legt fest, dass der Scroll-Container in y-Richtung, also nach unten gescrollt wird.
    • mandatory legt fest, dass am nächsten Fangpunkt eingerastet wird.
  • scroll-behavior spezifiziert das Scroll-Verhalten einer Scroll-Box, wenn ein Scroll-Event durch eine Navigation ausgelöst wird. Dass heißt, wenn ein interner Seitenanker auf eine section-klick, kommt es nicht zu einem plötzlichen Übergang, sondern ebenfalls zu einem Runterscrollen.
  • scroll-padding legt einen (möglichen) Innenabstand innerhalb des Scroll-Containers fest.

Die section-Elemente haben ebenfalls neue Eigenschaften:

  • scroll-snap-align legt mit dem Wert start fest, dass sich die Fangposition am Anfang der Scroll-Box befindet.
  • scroll-margin legt einen (möglichen) Außenabstand außerhalb des Fangpunktes der Scroll-Box fest.

Diese Regelsätze sind innerhalb einer Medienabfrage verschachtelt.

  • Sind keine Festlegungen für prefers-reduced-motion getroffen, wird gescrollt.
  • Falls der Benutzer dies in seinem Betriebssystem so angegeben hat, wird auf das Scollen verzichtet
    (→ Der Benutzer erhält die Kontrolle, wie die Webseite bei ihm animiert wird.)
  • Diese Medienabfrage wird kombiniert mit einer weiteren Bedingung, damit scroll-snap erst ab einer Viewport-Höhe über 22em aktiv wird.
Scrollbalken gestalten
body {
  scrollbar-color: steelblue gold;
  scrollbar-width: auto;
}

Damit Nutzer erkennen, dass es außerhalb des Viewports weitere Inhalte gibt, werden bei vielen Browsern Scrollbalken angezeigt, die hier mit CSS blau und gold gefärbt werden.

Im MacOS sind diese standardmäßig ausgeblendet, was aber in den Systemeinstellungen geändert werden kann.

  • Scrollbalken gestalten

    Bildlaufleisten mit CSS formatieren

Scroll-Buttons

Im Forum gibt es immer wieder die Frage, wie man denn anzeigen könnte, dass es verborgene Inhalte außerhalb des Viewports gibt, da die Scrollbalken z.B. im Firefox oder auf Macs standardmäßig ausgeblendet sind.

Könnte man nicht einen Pfeil erzeugen, der auf die Scroll-Richtung hinweist?
Mittlerweile gibt es dafür Pseudoelemente, die allein mit CSS ohne JavaScript erzeugt werden können. Der ::scroll-button()-Selektor erzeugt ein Pseudoelement als Schaltfläche zur Steuerung des Bildlaufs eines Scroll-Containers.

Achtung!

Um dieses Beispiel zu untersuchen, öffnen Sie bitte …
  1. das Beispiel mit einem Klick auf Vorschau in einem neuen Tab!
  2. den Seiteninspektor mit F12!
Pseudoelemente scroll-button() ansehen …
@supports selector(::scroll-button()) {
  .xyz {
    anchor-name: --screen;
	
  &::scroll-button(*) {
    position-anchor: --screen;
    position: fixed;
    align-self: anchor-center;
    width: 1.5em;
    background: skyblue;
    border-radius: 1em;
    border: thin solid skyblue;		
  }
  &::scroll-button(*):hover {
		background: gold;	
	}	

  &::scroll-button(down) {
    content: "↓";
    left: calc(anchor(left) + 1em);
  }
}

Top-Link

Leider ist es noch nicht möglich, einen Toplink (Sprungmarke zum Seitenanfang) mit CSS zu erzeugen.

Beispiel
  &::scroll-button(up) {
    content: "↑";
  }

Ein solcher Scroll-Button würde nach oben zur nächsten Fang-Position und nicht zum Seitenanfang springen. Deshalb wird der Link im HTML angelegt und mit CSS am unteren Seitenrand platziert.

Top-Link ansehen …
  <div class="back-to-top-wrapper">
    <a href="#top" class="back-to-top-link" aria-label="Scroll to Top">🔝</a>
  </div>

Komfort-Version mit JavaScript

In diesem Beispiel wollen wir unseren OnePager mit JavaScript weitere Funktionalität hinzufügen.

Das HTML-Dokument bleibt unverändert. Nach den Regeln des Unobtrusive JavaScript wird dem Dokument durch JavaScript zusätzliche Funktionalität hinzugefügt. Dies alles geschieht automatisch - bei einer Änderung des HTMLs ist keine Anpassung des Scripts nötig.

Intersection Observer API

Die Intersection Observer API ermöglicht es, ein Element zu beobachten und zu erkennen, wenn es einen bestimmten Punkt in einem Scroll-Container - oft (aber nicht immer) den Viewport - passiert und eine Callback-Funktion auslöst.[5]

Die Intersection Observer API soll verwendet werden, den aktuell sichtbaren Teil der Webseite zu identifizieren, um dann den entsprechenden Seitenanker in der Navigation mit aria-current auszuzeichnen. Dieses soll sowohl beim Anspringen durch Klick auf den Link als auch beim Scrollen erfolgen.


Observer definieren und den Sections zuordnen
const observer = new IntersectionObserver(function(entries) {
    ... 
}, { threshold: 0.1 });
document.querySelectorAll("section").forEach(element => observer.observe(element));

Hierdurch wird die dem IntersectionObserver als Parameter mitgegebene anonyme Funktion immer dann aufgerufen, wenn sich die Sichtbarkeit des überwachten Elements ändert. Der zweite Parameter ( threshold ) gibt an, wie weit das Element in den Viewport ragen muss, bis der Observer reagiert, hier 10%.

Die Observerfunktion soll dann den Link zum Element, dessen Sichtbarkeit sich geändert hat, suchen und markieren. Die Suche erfolgt über die ID des section-Elements. Als Markierung wird dem Link das aria-current-Attribut mit dem Wert location gegeben oder genommen.


Das Script sieht dann so aus:


Prüfen, welche Section sichtbar ist, und Link auf diese section hervorheben ansehen …
const observer = new IntersectionObserver(function(entries) {
  entries.forEach(entry => {
    const linkselector = `nav [href='#${entry.target.id}']`;
    const linkelement = document.querySelector(linkselector);
    if(linkelement) {
      if(entry.isIntersecting) linkelement.parentNode.setAttribute("aria-current", "location");
      else linkelement.parentNode.removeAttribute("aria-current");
    }
  });
}, { threshold: 0.1	});
document.querySelectorAll("section").forEach(element => observer.observe(element));

Achtung!

Um dieses Beispiel zu untersuchen, öffnen Sie bitte …
  1. das Beispiel mit einem Klick auf Vorschau in einem neuen Tab!
  2. den Seiteninspektor mit F12!

Durch die Verwendung des Attributs aria-current wird auch assistiven Technologien mitgeteilt, welcher Teil der Seite gerade angesprungen oder angescrollt wurde.

Damit der Link nun auch optisch hervorgehoben wird, wird dem CSS noch folgende Regel hinzugefügt:

[aria-current="location"]::after {
 content: "";
 position: absolute;
 bottom: -0.3em;
 left: 10%;
 width: 80%;
 height: 0.3em;
 background-color: steelblue;
}

Unterhalb des Links mit [aria-current="location"] wird ein Pseudoelement als blauer Streifen angezeigt.

URL-Anpassung

Über die Links der Navigation kommt man zu den internen Seitenankern auf die einzelnen „Seiten“. Dabei werden die URLs, bzw. Seitenanker in der History API gespeichert. Ein Klick auf den Zurück-Button des Browsers führt zum letzten geklickten Abschnitt, nicht zur letzten anderen Webseite.[6][7]

  <li><a href="#section1" data-scroll>Abschnitt 1</a></li>
  <li><a href="#section2" data-scroll>Abschnitt 2</a></li>
Beispiel
document.querySelectorAll('[data-scroll]').forEach(link => {
  link.addEventListener('click', e => {
    e.preventDefault();

    const target = document.querySelector(link.getAttribute('href'));
    target.scrollIntoView({ behavior: 'smooth' });

    // Replace URL fragment without adding history entry
    history.replaceState(null, "", link.getAttribute('href'));
  });
});
  • Reibungsloses Scrollen
  • Aktualisiert URL-Fragment (gut zum Teilen/Neuladen)
  • Fügt keine Einträge zum Verlauf hinzu
  • Vollständig zugänglich (gleiche Semantik wie echte Links)

Die fertige Seite

Die fertige Seite findet sich als Beispiel 1 unter unseren Beispiel-Templates, die du Dir zur freien Verwendung herunterladen kannst.


  • fertige Layouts
    Beispielseiten zur freien Verwendung
  • Vorschau-01.png

Siehe auch

  • Interactive Storytelling

    im Aufbau

  • Bilder präsentieren
    • Bilder-Galerie mit Scroll Snap
    • Bilder-Karussell
    • figure und figcaption
      • Bilderzoom mit Grid Layout
  • Scroll Snap bei columns

    Mehrspaltenlayout, das man scrollen kann

  • Progressive Web-App
    • Installierbarkeit
    • Offline-Browsing
  • fertige Layouts:
    Web-Visitenkarte
    10 verschiedene Stil-Ideen für einen OnePager als Web-Visitenkarte

Man könnte die Navigation auch dynamisch erzeugen, indem man mit JavaScript alle Kapitelüberschriften ausliest und in die Navigation einfügt.

dynamisch erstelltes Inhaltsverzeichnis

Einen anderen Ansatz verfolgen progressive Web Apps - eigentlich auch One-Pager. Jedoch werden dort die Seiteninhalte per JavaScript erzeugt und wieder entfernt.

Weblinks

  1. Jan Semler: Single-Page Website und wie man es richtig macht (28.01.2013)
  2. onepager.de (umfangreiche Erklärung aus Sicht der Werbeagenturen)
  3. In diesem Beispiel aus dem Jahre 2014 wird eine Seite durch einen Klick oder Tap auf den entsprechenden Verweis als Ziel (target) aktiviert und mit CSS über die strukturelle Pseudoklasse :target sichtbar gemacht.
    OnePager mit :target ansehen …
    body {
    	position: relative;
    	overflow: hidden;
    	height: 100vh;
    }
     
    section {
    	padding:3em 1em 1em;
    	width:100%;
    	height: 100vh;	
    	background: white;	
    	opacity: 0;
    	position: absolute;
    	top: 0;
    	left: 0;
    	transition: all 0.5s;
    }
     
    section:first-of-type {
      opacity: 1;
      transition: all 0.5s;
    }
     
    section:target {
      opacity: 1;
     
    }
    
  4. a11yproject.com: Scrollable Overflow containers
  5. MDN: Intersection Observer API
  6. developers.google.com: Grundlagen von JavaScript-SEO
    History API anstelle von Fragmenten verwenden
  7. Intelligent State Handling

Abgerufen am 25.11.2025
von "http://wiki.selfhtml.org/wiki/OnePager"