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=3in 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
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.
<!-- 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.
| Kriterium | Seitenzahlen | Mehr laden | Endloses Scrollen |
|---|---|---|---|
| Startlast bei gleicher Abschnittsgröße | HTML und Links, kein Skript nötig | plus Skript für Abruf und Einfügen | plus Beobachter, Vorladen und Adresspflege |
| Eigene URL je Abschnitt | angelegt (?p=n) | mit Link als Rückfall und History API | nur 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 Nachladen | beim Seitenwechsel kaum | Klick schützt 500 ms, danach Platzhalter nötig | Scrollen schützt nicht, Platzhalter und frühes Laden nötig |
| Fußbereich erreichbar | enthalten | enthalten | nur mit Pause oder Knopf |
| Passt zu | großen Kategorien, Suchergebnissen, B2B-Listen | Kategorien zum Stöbern, besonders mobil | Inspirations- 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: falseerfassen 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
pageshowmit der Eigenschaftpersistedmessen (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
href (Google Search Central). Ein Feed ohne Abschnittsadressen zeigt ihnen deshalb nur den ersten Abschnitt. Mit ?page=n je Abschnitt, Links von Abschnitt zu Abschnitt und einer Adresszeile, die per History API mitläuft, ist dasselbe Muster für Crawler eine normale Seitenreihe.?p= (Shopware-Quellcode).fetch nach (Shopware-Quellcode), und für den Wechsel auf die nächste Seite nennt Google prefetch als Möglichkeit, ihn zu verkürzen (Google Search Central). Für das Tempo zählen darum weniger das Muster als die Abschnittsgröße und der reservierte Platz für neue Kacheln.Verwandte Artikel
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.
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.
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.