Zum Inhalt springen
Shops & CMS

Seitenzahlen, Mehr laden oder Endlos: Listing schnell halten

Seitenzahlen, Mehr laden oder endloses Scrollen im Shop-Listing: wie Startlast, INP, Layoutsprünge, Rücksprung und eigene URL je Seite zusammenhängen.

21 Min. Lesezeit KategorieseitePaginationLadezeitShopware

Kurz und einfach erklärt

In vielen Shops gibt es lange Listen mit Produkten. Die Liste lädt nicht auf einmal, sondern in Teilen. So ist der Anfang schnell.

Es gibt drei Wege. Man blättert mit Seitenzahlen. Man drückt einen Knopf für mehr Produkte. Oder neue Produkte kommen beim Scrollen von selbst.

Wer von einem Produkt zurück zur Liste geht, soll an derselben Stelle landen. Dafür braucht jeder Teil der Liste eine eigene Adresse.

Beim Nachladen darf nichts springen. Die Seite hält deshalb den Platz für neue Produkte frei.

Wir prüfen Ihre Kategorieseiten. Dann stellen wir das Nachladen so ein, dass die Seiten schnell bleiben.

Eine Kategorieseite mit einigen hundert Artikeln lädt nicht in einem Stück, und das ist gut so. Google nennt als Vorteil des schrittweisen Ladens ausdrücklich, dass der erste Seitenaufbau schneller ist, als wenn alle Ergebnisse auf einmal kommen (Google Search Central). Offen bleibt, wie die nächsten Artikel ins Bild kommen: über Seitenzahlen, über einen Knopf „Mehr laden“ oder automatisch beim Scrollen. Die Entscheidung betrifft mehr als die Optik. Sie legt fest, wie viel Skript die Seite am Anfang braucht, ob nachgeladene Kacheln den Inhalt verschieben, ob der Zurück-Knopf an dieselbe Stelle führt und ob jeder Abschnitt eine eigene Adresse hat. Dieser Beitrag vergleicht die drei Muster an genau diesen Punkten, erklärt, wovon die Artikelzahl je Ladeschritt abhängt, und zeigt, warum tiefe Seiten die Datenbank stärker belasten als die erste. Wo es um Shopware geht, stützen wir uns auf den Quellcode der Storefront in Version 6.7.15.1.

Das Wichtigste in Kürze

  • Die Startlast hängt vor allem an der Abschnittsgröße: Shopware lädt ab Werk 24 Produkte je Seite (Shopware-Quellcode). Welche Größe passt, entscheidet das schwächste Gerät, in der Regel das Smartphone.
  • Seitenzahlen funktionieren mit reinen Links und ohne Skript. „Mehr laden“ und endloses Scrollen brauchen ein Skript, das Platz reserviert, den Fokus führt und die Adresse über die History API nachzieht.
  • Scrollen entschuldigt keinen Layoutsprung (web.dev): Beim endlosen Scrollen zählt jeder Sprung durch nachgeladene Kacheln voll, beim Klick auf „Mehr laden“ erst nach 500 Millisekunden (web.dev). Platzhalter in Kachelgröße fangen beides ab.
  • Wer nach dem Zurück-Klick am Listenanfang landet, muss seine Position neu suchen, und das betrifft viele Wege: Auf Mobilgeräten ist jede fünfte Navigation ein Zurück oder Vorwärts (web.dev). Abhilfe: bfcache-tauglich bleiben und den Abschnitt als ?p=3 in der Adresse führen.
  • Jede Seite einer Reihe braucht eine eigene URL und einen eigenen canonical-Verweis statt eines Verweises auf Seite 1. Googles Crawler folgen Links, klicken aber keine Knöpfe (Google Search Central).
  • Tiefe Seiten kosten mehr: Mit OFFSET liest die Datenbank alle übersprungenen Zeilen mit (MariaDB-Dokumentation), und Elasticsearch blättert per from und size standardmäßig höchstens 10.000 Treffer weit (Elastic-Dokumentation).

Drei Muster, ein Ziel: weniger auf einmal laden

Google beschreibt drei Muster, um eine lange Liste in Teilen zu zeigen. Bei Seitenzahlen wechselt man über Links wie „weiter“, „zurück“ und Seitennummern zwischen Seiten, die jeweils einen Ausschnitt zeigen. Bei „Mehr laden“ erweitert ein Knopf die angezeigte Menge. Beim endlosen Scrollen lädt neuer Inhalt, sobald man das Ende der Seite erreicht (Google Search Central). Allen dreien ist gemeinsam, dass nicht der ganze Katalog auf einmal kommt. Neben dem schnelleren ersten Aufbau nennt Google weniger Datenverkehr, der besonders auf Mobilgeräten zählt, und weniger Last im Backend, weil weniger Inhalt aus der Datenbank gelesen wird (Google Search Central).

Die Unterschiede liegen im Detail, und Google benennt sie selbst: Seitenzahlen zeigen, wie groß das Ergebnis ist und wo man steht, verlangen aber mehr Bedienung und für jede weitere Seite einen neuen Seitenaufruf. „Mehr laden“ hält alles auf einer Seite und kann den Gesamtumfang am Knopf nennen, kommt aber mit sehr vielen Ergebnissen schlecht zurecht, weil alles auf derselben Seite landet. Endloses Scrollen ist intuitiv, kann bei unklarem Umfang aber zu Scroll-Ermüdung führen (Google Search Central). Für die Ladezeit kommen vier Fragen dazu: Was lädt am Anfang? Verschiebt das Nachladen den Inhalt oder bremst es die Reaktion auf Klicks? Wohin führt der Zurück-Knopf? Und hat jeder Abschnitt eine eigene Adresse?

Abgrenzung

Wie Filter und Facetten im Listing schnell reagieren, beschreibt der Beitrag Filter im Shop-Listing. Warum viele Knoten im Baum jede Interaktion verteuern, steht im Beitrag DOM-Größe reduzieren, die Grundlagen des sofortigen Zurück-Sprungs im Beitrag zum Back-Forward-Cache. Hier geht es um die Wahl des Lademusters selbst.

Startlast: Die Abschnittsgröße entscheidet

Bei gleicher Artikelzahl je Abschnitt laden alle drei Muster beim ersten Aufruf dieselben Produktdaten. Die Startlast unterscheidet sich trotzdem, und zwar beim Skript und beim Vorladen. Seitenzahlen kommen mit normalen Links aus, die Seite funktioniert auch, bevor ein Skript ausgeführt ist. „Mehr laden“ braucht ein kleines Skript, das den nächsten Abschnitt abruft und einfügt. Endloses Scrollen braucht zusätzlich einen Beobachter am Listenende, lädt den nächsten Abschnitt in der Regel schon vor, bevor jemand ihn sieht, und muss die Adresse mitführen. Das Mockup oben zeigt diese Reihenfolge schematisch. Der größere Hebel ist aber die Zahl der Artikel je Abschnitt: Jede Kachel bringt Bild, Preis, Markup und oft eigene Skripte für Merkzettel oder Schnellansicht mit.

In Shopware legt die Einstellung „Anzahl der Produkte pro Seite“ diese Zahl je Verkaufskanal fest. Fehlt ein Wert, gilt der Standard von 24 Produkten (Shopware-Quellcode). Über den Parameter limit lassen sich je Abruf höchstens 100 Produkte anfordern (Shopware-Quellcode). 24 ist eine praktische Größe, weil sie sich durch zwei, drei, vier und sechs teilen lässt: Die letzte Reihe ist in jedem gängigen Raster voll, und es bleiben keine halben Reihen, die beim Nachladen auffallen.

Eine Zahl, die für jeden Shop passt, gibt es nicht. Der Zielkonflikt ist aber klar: Weniger Produkte je Abschnitt bedeuten beim ersten Aufruf weniger Daten und weniger zu zeichnende Bilder, zu wenige zwingen dagegen zu ständigem Weiterblättern. Ein gangbarer Weg ist eine Kombination aus „Mehr laden“ und Lazy Loading der Produktbilder: Der Abschnitt kann dann größer sein, ohne dass die Startlast im gleichen Maß steigt. Welche Größe im eigenen Shop trägt, zeigen die Felddaten der eigenen Kategorieseiten.

Für die Abschnittsgröße zählt das schwächste Gerät. 73 Prozent der Online-Shopper ab 16 Jahren in Deutschland kaufen per Smartphone ein (Bitkom 2025), und gerade mobil schneiden Unterseiten schlechter ab: Nur 69 Prozent der mobilen Unterseiten erreichen eine gute INP, bei Startseiten sind es 80 Prozent (HTTP Archive Web Almanac 2025). Kategorieseiten gehören zu diesen Unterseiten. Eine feste Zahl je Adresse ist trotzdem sinnvoll, auch wenn Desktop und Smartphone unterschiedlich viel vertragen: Wer auf dem Desktop mehr zeigen will, lädt dort den zweiten Abschnitt automatisch nach, statt die Seitengröße je Gerät zu ändern. So zeigt dieselbe Adresse überall dieselben Artikel.

  • Bilder der ersten sichtbaren Reihe laden sofort, alle weiteren tragen loading="lazy". Wie Lazy Loading und Code-Splitting zusammenspielen, beschreibt der Beitrag Lazy Loading richtig umsetzen.
  • Jede Kachel hat feste Maße für Bild und Text. Auf 62 Prozent der mobilen Seiten fehlen bei mindestens einem Bild die Maßangaben (HTTP Archive Web Almanac 2025), und genau solche Bilder verschieben nachgeladene Reihen.
  • Merkzettel, Schnellansicht und Variantenauswahl in der Kachel starten erst bei Interaktion, nicht für jede Kachel schon beim Laden.
  • Das Markup einer Kachel bleibt flach, denn es wiederholt sich mit jedem Abschnitt.

Seitenzahlen: der robuste Standard

Seitenzahlen sind das einfachste Muster für Browser und Suchmaschine. Jede Seite ist ein eigenes Dokument, das ohne Skript funktioniert, und jede Seite hat dieselbe überschaubare Größe. Google empfiehlt, von jeder Seite per <a href> auf die folgende zu verlinken, damit der Crawler die weiteren Seiten findet (Google Search Central).

Das Standard-Theme von Shopware geht diesen Weg und baut ihn aus. Die Vorlage der Seitenleiste erzeugt echte Links mit dem Parameter ?p= und zeigt nur ein Fenster von Seitenzahlen um die aktuelle Seite. Klickt jemand auf eine Zahl, fängt das Listing-Plugin den Klick ab, lädt den Abschnitt per fetch nach, tauscht die Kacheln aus und schreibt die neue Adresse per pushState in den Verlauf (Shopware-Quellcode). Die Route, die den Abschnitt liefert, antwortet auf GET-Anfragen, ist für den HTTP-Cache freigegeben und sendet x-robots-tag: noindex, damit die Teilantwort nicht im Index landet (Shopware-Quellcode). Eine Seitenzahl jenseits der letzten Seite beantwortet Shopware mit dem Fehler „nicht gefunden“, statt eine leere Liste auszuliefern (Shopware-Quellcode).

Der Nachteil ist der zusätzliche Klick und, ohne Skript, ein vollständiger Seitenwechsel. Der lässt sich verkürzen: Google rät, für den Wechsel auf die nächste Seite preload, preconnect oder prefetch in Betracht zu ziehen (Google Search Central). Mit Speculation Rules lädt der Browser die nächste Seite vor, sobald jemand mit dem Zeiger auf den Link geht; wie das funktioniert und wo die Grenzen liegen, steht im Beitrag zu Speculation Rules. Für die Bedienung zählt außerdem, dass die Seitenzahlen auf dem Smartphone groß genug zum Tippen sind und die aktuelle Seite als solche ausgezeichnet ist. Die Shopware-Vorlage setzt dafür aria-current="page" (Shopware-Quellcode).

„Mehr laden“: Kontrolle mit reserviertem Platz

Beim Knopf „Mehr laden“ bleibt die Seite stehen, und der nächste Abschnitt wird darunter angehängt. Die Nielsen Norman Group sieht darin einen Kompromiss: Der Knopf hält den Fußbereich erreichbar, zeigt deutlich, dass es weitere Inhalte gibt, und hilft bei langsamer Verbindung, weil weniger im Voraus lädt. Dafür kostet jeder Abschnitt einen zusätzlichen Klick, der den Lesefluss kurz unterbricht (Nielsen Norman Group 2022). Für Suchmaschinen ist der Knopf zunächst unsichtbar: Googles Crawler klicken keine Knöpfe und lösen in der Regel keine Skriptfunktionen aus, die eine Nutzeraktion voraussetzen (Google Search Central). Deshalb ist der Knopf im HTML ein Link auf den nächsten Abschnitt, zum Beispiel ?p=2, den erst ein Skript im Browser in einen Nachlade-Knopf verwandelt.

Für den Cumulative Layout Shift ist der Klick ein Vorteil. Layoutsprünge innerhalb von 500 Millisekunden nach einer Eingabe tragen eine Markierung und können aus der Berechnung herausfallen (web.dev). Braucht der Server länger, zählt der Sprung, wenn die neuen Kacheln den Fußbereich nach unten schieben oder Bilder ohne Maße nachrutschen. web.dev empfiehlt für Interaktionen mit längerer Netzwerkanfrage, sofort Platz zu schaffen und einen Ladehinweis zu zeigen (web.dev). Für „Mehr laden“ heißt das: Direkt beim Klick erscheinen Platzhalter in Kachelgröße für den ganzen Abschnitt, und die echten Kacheln ersetzen sie, ohne dass sich die Höhe ändert. Gut ist ein CLS von höchstens 0,1 (web.dev); weitere Ursachen beschreibt der Beitrag Cumulative Layout Shift vermeiden.

Der Klick zählt zugleich für die Interaction to Next Paint. Gut ist eine INP von höchstens 200 Millisekunden (web.dev). Der Klick-Handler setzt darum nur den Ladezustand und die Platzhalter und gibt den Main Thread wieder frei. Abruf, Einfügen und Tracking laufen danach. Das Einfügen selbst geschieht in einem Schritt, nicht Kachel für Kachel, und neue Kacheln richten ihre Skripte erst ein, wenn sie gebraucht werden. Wie sich lange Aufgaben aufteilen lassen, zeigt der Beitrag INP optimieren. Das folgende Beispiel fasst die Schritte zusammen; der Endpunkt /listing/chunk steht für eine Route, die nur die Kacheln eines Abschnitts liefert.

load-more.html
<!-- Ohne Skript ein normaler Link auf den nächsten Abschnitt -->
<ul class="product-grid" id="product-list" aria-busy="false">
  <!-- Kacheln von Abschnitt 1, jede mit festen Bildmaßen -->
</ul>
<p class="listing-status" id="listing-status" aria-live="polite"></p>
<a class="load-more" href="?p=2" data-next-page="2">Weitere Artikel laden</a>

<script type="module">
  const link = document.querySelector('.load-more');
  const list = document.getElementById('product-list');
  const status = document.getElementById('listing-status');

  // Platzhalter mit derselben Höhe wie echte Kacheln (per CSS)
  function addSkeletonTiles(count) {
    const tiles = Array.from({ length: count }, () => {
      const li = document.createElement('li');
      li.className = 'product-tile is-skeleton';
      return li;
    });
    list.append(...tiles);
    return tiles;
  }

  link.addEventListener('click', async (event) => {
    event.preventDefault();
    const page = Number(link.dataset.nextPage);

    // 1. Sofort reagieren: Ladezustand und Platzhalter
    list.setAttribute('aria-busy', 'true');
    const skeletons = addSkeletonTiles(24);

    // 2. Main Thread freigeben, erst dann abrufen
    await globalThis.scheduler?.yield?.();
    const response = await fetch(`/listing/chunk?p=${page}`);
    const html = await response.text();

    // 3. In einem Schritt einfügen und Platzhalter entfernen
    const fragment = document.createRange().createContextualFragment(html);
    const firstNew = fragment.firstElementChild;
    skeletons[0].before(fragment);
    skeletons.forEach((tile) => tile.remove());
    list.setAttribute('aria-busy', 'false');

    // 4. Adresse nachziehen, Fokus auf die erste neue Kachel
    history.replaceState({ page }, '', `?p=${page}`);
    firstNew?.querySelector('a')?.focus();
    status.textContent = 'Weitere Artikel geladen';
    link.dataset.nextPage = String(page + 1);
    link.href = `?p=${page + 1}`;
  });
</script>

Zwei Details entscheiden, ob der Knopf auch mit Tastatur und Screenreader funktioniert. Nach dem Nachladen springt der Fokus auf die erste neue Kachel; sonst bleibt er auf einem Knopf, der weiter nach unten gewandert ist, und die neuen Artikel liegen unbemerkt davor. Und eine Statuszeile mit aria-live sagt an, dass neue Artikel da sind. Der Knopf selbst kann nennen, wie viele Artikel noch folgen, was Google als Vorteil dieses Musters aufführt (Google Search Central). Mit jedem Klick wächst allerdings der Baum der Seite. Wie sich das begrenzen lässt, steht im Beitrag DOM-Größe reduzieren; eine einfache Grenze ist, nach einer festen Zahl von Abschnitten auf Seitenzahlen zu wechseln.

Endloses Scrollen: bequem, aber teuer im Detail

Endloses Scrollen nimmt den Klick weg, und genau das hat Folgen für die Messung. Scrollen und Hovern zählen nicht als Interaktion für die INP (web.dev). Für den CLS ist Scrollen keine Eingabe, die Layoutsprünge entschuldigt: Die Markierung für kurz zurückliegende Eingaben gilt nur für einzelne Ereignisse wie Tippen, Klicken oder Tastendruck, nicht für Scrollen, Ziehen oder Zoomen (web.dev). Schiebt ein nachgeladener Abschnitt beim Scrollen den Fußbereich oder eine Reihe nach unten, zählt jeder Sprung voll.

Daraus folgen zwei Regeln. Erstens lädt der nächste Abschnitt früh genug, dass er fertig ist, bevor jemand das Listenende sieht. Ein IntersectionObserver auf einem Element am Listenende erfüllt das, wenn sein rootMargin den Beobachtungsbereich nach unten erweitert; ohne Angabe beginnt die Beobachtung erst an der Kante des Sichtbereichs (MDN Web Docs). Zweitens steht der Platz für den nächsten Abschnitt schon da, bevor die Daten kommen: Platzhalter in Kachelgröße, die die echten Kacheln ersetzen, ohne dass sich die Höhe ändert.

Die Nielsen Norman Group nennt weitere Schwächen: Der Fußbereich mit Kontaktdaten und Rückgaberegeln wird unerreichbar, es fehlen Orientierungspunkte in der Liste, und ohne Ladehinweis entsteht der Eindruck, das Ende sei erreicht (Nielsen Norman Group 2022). Für Tastatur und Screenreader beschreibt das Feed-Muster der W3C-Autorenpraxis, wie eine solche Liste bedienbar bleibt: Strg + Ende führt den Fokus hinter den Feed, und während des Einfügens trägt der Container aria-busy="true" (W3C WAI-ARIA Authoring Practices). Eine neuere Variante blendet zwischen den nachgeladenen Abschnitten Seitenzahlen ein. Die Nielsen Norman Group sieht darin Orientierungspunkte, die das Wiederfinden erleichtern; der Fußbereich bleibt aber auch so unerreichbar (Nielsen Norman Group 2022).

Auch beim endlosen Scrollen braucht jeder Abschnitt eine eigene, dauerhafte Adresse. Google empfiehlt absolute Seitenzahlen wie ?page=12 statt relativer Angaben wie ?date=yesterday und rät, die angezeigte Adresse über die History API anzupassen, sobald ein neu geladener Abschnitt der hauptsächlich sichtbare ist (Google Search Central). Dafür passt replaceState besser als pushState: Sonst legt jeder Abschnitt einen eigenen Eintrag im Verlauf an, und der Zurück-Knopf führt Abschnitt für Abschnitt rückwärts statt zur vorherigen Seite.

Rücksprung an dieselbe Stelle

Kaum ein Weg ist im Shop so häufig wie Liste, Produkt, zurück. Laut Chrome-Nutzungsdaten ist auf dem Desktop jede zehnte und auf Mobilgeräten jede fünfte Navigation ein Zurück oder Vorwärts (web.dev). Landet man dabei am Listenanfang, wird es teuer: Wer seine Position in einer langen Liste erneut suchen muss, verliert Zeit, und manche Besucher brechen an dieser Stelle ab. Auf Mobilgeräten wiegt das schwerer, weil dort weniger Kacheln auf einen Bildschirm passen.

Der schnellste Weg zurück ist der Back-Forward-Cache. Er hält die ganze Seite samt JavaScript-Speicher im Arbeitsspeicher und stellt sie beim Zurück wieder her (web.dev), mit allen nachgeladenen Abschnitten und der Scrollposition. Das gilt für alle drei Muster gleich. Voraussetzung ist, dass die Kategorieseite in den Cache darf: keine unload-Handler, kein unnötiges Cache-Control: no-store, keine offenen Verbindungen beim Verlassen (web.dev). Wie man die Eignung prüft und herstellt, beschreibt der Beitrag zum Back-Forward-Cache.

Greift der Cache nicht, lädt der Browser die Seite neu, und dann zeigt sich der Wert einer Adresse je Abschnitt. Bei Seitenzahlen liefert ?p=3 dieselbe Seite wie vorher, und mit dem Wert auto von history.scrollRestoration stellt der Browser die Scrollposition selbst wieder her (MDN Web Docs), sofern die Kacheln feste Maße haben und die Höhe beim Wiederherstellen schon stimmt. Bei „Mehr laden“ und endlosem Scrollen fehlt diese Grundlage, wenn die Adresse unverändert bleibt. Deshalb sollte die Adresse bei jedem Klick auf „Mehr laden“ mitwandern, etwa per history.pushState, damit beim Zurück der richtige Ausschnitt geladen werden kann. Das Codebeispiel oben nutzt replaceState: Es führt die Adresse ebenso mit, legt aber keinen eigenen Verlaufseintrag je Abschnitt an.

Ein robustes Muster für den Rückweg ohne Cache sieht so aus: Die Adresse trägt den Abschnitt, in dem die angeklickte Kachel steht, und history.state merkt sich das Produkt. Beim Zurück rendert der Server nur diesen Abschnitt, darüber steht ein Link „Vorherige Artikel laden“, und ein kleines Skript scrollt zur gemerkten Kachel. Wer die Position selbst setzt, schaltet die automatische Wiederherstellung mit history.scrollRestoration = "manual" ab (MDN Web Docs), damit Browser und Skript nicht gegeneinander arbeiten. Der Vorteil für die Startlast: Der Rückweg lädt einen Abschnitt statt aller, die vorher zu sehen waren.

Eine eigene URL je Abschnitt

Eine Adresse je Abschnitt hilft nicht nur beim Zurück. Sie lässt sich neu laden, teilen und als Lesezeichen ablegen, und sie zeigt bei jedem Aufruf dieselben Artikel, solange die Seitenzahl absolut ist. Filter und Sortierung gehören als eigene Parameter dazu, damit ?p=3 mit aktivem Filter etwas anderes ist als ohne; wie Filter dabei schnell bleiben, beschreibt der Beitrag zu Filtern im Shop-Listing. Für den Cache hat das einen Nebeneffekt: Jede Kombination aus Seite, Filter und Sortierung ist ein eigener Eintrag, und tiefe Seiten werden so selten abgerufen, dass sie oft nicht im Cache liegen.

Für Suchmaschinen reicht ein Absatz, weil die Regeln klar sind. Google crawlt Adressen aus dem href von Links, verlangt eine eigene URL je Seite, etwa mit ?page=n, und rät ausdrücklich davon ab, die erste Seite einer Reihe als canonical für alle anderen zu setzen: Jede Seite bekommt ihren eigenen canonical-Verweis. Seitenzahlen gehören nicht hinter ein #, weil Google den Teil nach der Raute ignoriert, und rel="next" und rel="prev" nutzt Google nicht mehr. Varianten mit Filtern oder anderer Sortierung sollen nicht in den Index, etwa per noindex (Google Search Central). Shopware setzt den canonical-Verweis ab Seite 2 auf die Kategorieadresse mit ?p= (Shopware-Quellcode).

Tiefe Seiten belasten die Datenbank

Die erste und eine sehr tiefe Seite sehen gleich aus, kosten die Datenbank aber nicht dasselbe. Die übliche Abfrage mit LIMIT und OFFSET überspringt die Zeilen davor nicht, sie liest sie. Die MariaDB-Dokumentation rechnet das an einer Liste mit 50.000 Einträgen und zehn Einträgen je Seite vor: Für die letzte Seite muss die Datenbank alle 50.000 Zeilen finden, die ersten 49.990 überspringen und dann zehn ausliefern (MariaDB-Dokumentation). Ruft ein Crawler alle 5.000 Seiten ab, berührt er dabei rund 125 Millionen Einträge (MariaDB-Dokumentation). Je nach Filter und Sortierung muss unter Umständen schon für die erste Seite die ganze Liste gelesen werden (MariaDB-Dokumentation).

In Shopware kommt die Zählung dazu. Für das Listing fordert Shopware die exakte Gesamtzahl der Treffer an (Shopware-Quellcode), denn die Seitenleiste braucht die letzte Seitenzahl. Im Quellcode ist dieser Modus als langsam gekennzeichnet. Daneben gibt es einen Modus, der nur prüft, ob weitere Seiten folgen: Er liest höchstens das Sechsfache der Seitengröße plus eine Zeile (Shopware-Quellcode). Für „Mehr laden“ und endloses Scrollen reicht diese Auskunft, denn der Knopf muss nur wissen, ob es weitergeht. Die MariaDB-Dokumentation beschreibt denselben Gedanken für eigene Abfragen: LIMIT 11 statt LIMIT 10 abfragen und am elften Eintrag erkennen, ob es eine nächste Seite gibt (MariaDB-Dokumentation).

Die grundsätzliche Empfehlung der MariaDB-Dokumentation lautet, auf OFFSET zu verzichten und sich zu merken, wo die letzte Seite aufgehört hat (MariaDB-Dokumentation). Für „Mehr laden“ passt das gut, weil der nächste Abschnitt ohnehin am letzten angezeigten Artikel anschließt. Bei Suchservern gilt dieselbe Grenze in anderer Form: Elasticsearch blättert über from und size standardmäßig höchstens 10.000 Treffer weit, und für tiefere Ergebnisse verweist die Dokumentation auf search_after (Elastic-Dokumentation). Jeder Shard muss für eine tiefe Seite die Treffer aller vorherigen Seiten in den Speicher laden (Elastic-Dokumentation).

Für den Shopbetrieb heißt das: tiefe Seiten aus dem HTTP-Cache bedienen, wo es geht, die Seitenleiste auf ein Fenster um die aktuelle Seite begrenzen, wie es das Shopware-Theme tut, und Aufrufe mit hoher Seitenzahl im Slow-Query-Log und im Zugriffsprotokoll beobachten. Wie Cache-Schichten zusammenspielen, steht auf unserer Seite zu Caching-Strategien, wie man langsame Abfragen findet und mit Indexen beschleunigt, im Beitrag zur Datenbank-Query-Optimierung.

Welches Muster für welches Listing?

Ein Muster für alle Listen gibt es nicht. Die Tabelle fasst zusammen, was jedes Muster von sich aus mitbringt und was erst mit Zusatzarbeit entsteht.

KriteriumSeitenzahlenMehr ladenEndloses Scrollen
Startlast bei gleicher AbschnittsgrößeHTML und Links, kein Skript nötigplus Skript für Abruf und Einfügenplus Beobachter, Vorladen und Adresspflege
Eigene URL je Abschnittangelegt (?p=n)mit Link als Rückfall und History APInur mit History API und Seitenparameter
Rücksprung an die Stelleüber bfcache oder Adresse und Scroll-Wiederherstellungüber bfcache oder Abschnittsadresse mit gemerktem Produktüber bfcache oder Abschnittsadresse, sonst schwierig
Layoutsprünge beim Nachladenbeim Seitenwechsel kaumKlick schützt 500 ms, danach Platzhalter nötigScrollen schützt nicht, Platzhalter und frühes Laden nötig
Fußbereich erreichbarenthalten enthalten nur mit Pause oder Knopf
Passt zugroßen Kategorien, Suchergebnissen, B2B-ListenKategorien zum Stöbern, besonders mobilInspirations- und Neuheitenseiten

Für die meisten Kategorieseiten ist ein Fundament aus echten Seitenlinks in der Regel die robustere Wahl, das ein Skript zu „Mehr laden“ ausbaut, wo Stöbern überwiegt. So bleibt jeder Abschnitt adressierbar, Suchmaschinen finden alle Artikel, und das Skript verbessert nur, was ohne es schon funktioniert. Endloses Scrollen passt zu Seiten, auf denen Besucher eher schauen als suchen, und braucht dann Abschnittsadressen, frühes Laden, reservierten Platz und nach einigen Abschnitten einen Halt, damit der Fußbereich erreichbar bleibt. Welche Vorlage zuerst drankommt, entscheiden die Felddaten: Die Kategorieseite mit viel Verkehr und schwacher INP ist der erste Kandidat.

Messen, ob das Muster trägt

Ob das gewählte Muster in der Praxis schnell bleibt, zeigen Felddaten und ein paar gezielte Tests. Die INP verrät, wie schnell der Klick auf eine Seitenzahl oder auf „Mehr laden“ beantwortet wird; welcher Code dabei bremst, macht die Long Animation Frames API sichtbar, beschrieben im Beitrag zu Long Animation Frames. Für den Rest hilft eine kurze Liste:

  • Layoutsprünge nach dem Nachladen mit hadRecentInput: false erfassen und dem Abschnitt zuordnen, der sie ausgelöst hat.
  • Beim endlosen Scrollen prüfen, ob der nächste Abschnitt fertig ist, bevor das Listenende sichtbar wird, auch mit gedrosselter Verbindung.
  • Den Anteil der Rücksprünge aus dem bfcache über das Ereignis pageshow mit der Eigenschaft persisted messen (web.dev).
  • Den Rückweg von Hand testen: Produkt im dritten Abschnitt öffnen, zurück, einmal mit und einmal ohne bfcache.
  • Jede Abschnittsadresse einzeln aufrufen: Sie zeigt dieselben Artikel, hat ihren eigenen canonical-Verweis und ist ohne Skript erreichbar.
  • Aufrufe sehr hoher Seitenzahlen im Zugriffsprotokoll suchen und ihre Antwortzeit gegen die erste Seite halten.

Bei einer Analyse gehen wir genau diese Punkte für Ihre Kategorievorlagen durch, mit Laborwerten für Desktop und Smartphone und, soweit vorhanden, mit Felddaten Ihrer Kategorieseiten. Das Ergebnis ist eine Empfehlung für das Lademuster je Vorlage und eine Reihenfolge der Änderungen nach Wirkung. Wie wir dabei vorgehen, steht unter technische Analyse. Für Shops auf Shopware setzen wir die Änderungen im Theme um, von der Abschnittsgröße bis zum Rückweg ohne Cache; mehr dazu auf der Seite Shopware-Performance. Einen Überblick über typische Bremsen in Onlineshops gibt die Seite PageSpeed im E-Commerce.

Quellen und Dokumentation

Dieser Artikel basiert auf Daten aus: Google Search Central (Pagination, incremental page loading, and their impact on Google Search; Fix Lazy-Loaded Website Content); web.dev (Cumulative Layout Shift; Interaction to Next Paint; Back/forward cache); Nielsen Norman Group 2022 (Infinite Scrolling: When to Use It, When to Avoid It); HTTP Archive Web Almanac 2025 (Kapitel Performance); Bitkom 2025 (Black Friday: Die Hälfte geht auf Schnäppchenjagd); MariaDB-Dokumentation (Pagination Optimization); Elastic-Dokumentation (Paginate search results); Shopware-Quellcode, Version 6.7.15.1 (Listing-Paginierung, Seitenleiste, Listing-Plugin, CMS-Controller, Kategorie-canonical, Criteria); MDN Web Docs (History: scrollRestoration; IntersectionObserver: rootMargin); W3C WAI-ARIA Authoring Practices (Feed Pattern).

Verwandte Artikel

Frontend-Optimierung

Produktgalerie und Zoom: schnelle Produktseite trotz Bildern

Produktgalerie und Zoom ohne Tempoverlust: erstes Bild eager und priorisiert, Folgebilder lazy, Zoom-Datei erst beim Klick, Variantenwechsel ohne Neuladen.

18 Min. Lesezeit
Shops & CMS

Filter im Shop-Listing: schnelle Facetten ohne Wartezeit

Jeder Filterklick im Shop zählt zur INP. So bestätigen Sie den Klick sofort, rechnen Zähler sparsam, cachen Ergebnisse und bauen das Listing ruhig neu auf.

19 Min. Lesezeit
Core Web Vitals & Messung

Soft Navigations in CrUX: was SPA-Shops bis Mai 2027 prüfen

CrUX zeigt seit Oktober 2026 Core Web Vitals mit Soft Navigations. Wer betroffen ist, wie sich LCP, INP und CLS verschieben und was SPA-Shops bis Mai 2027 tun.

17 Min. Lesezeit