Warum öffnet sich mein Burger-Menü erst beim zweiten Klick?
Die Zusammenfassung in einem Satz: Wenn Sie ein JavaScript delay aktiviert haben (Skripte werden beim ersten Klick oder nach einem Timer geladen), weckt der allererste Tap auf das Burger-Menü nur das Laden der Skripte, er öffnet das Menü nicht. Das Menü reagiert erst beim zweiten Tap. Die Lösung: das Menü-Skript und seine Abhängigkeiten aus dem Delay herausnehmen, oder noch besser: ein Vanilla-Menü ohne jede Abhängigkeit verwenden.
Sie tippen auf das Burger-Menü: nichts passiert. Sie tippen erneut: Das Menü öffnet sich. Jedes Mal braucht es zwei Taps. Das ist weder Zufall noch ein Theme-Bug: Es ist das mechanische Verhalten des „JavaScript delay“, einer sehr verbreiteten Optimierung. Hier erfahren Sie, warum, und die zwei Wege, es zu beheben.
Was das „JavaScript delay“ macht (und warum der erste Klick verloren geht)
Um Performance-Punkte zu gewinnen, verschiebt das „JS delay“ (oder „load on interaction“) die Skriptausführung so lange, bis der Besucher etwas tut: scrollt, die Maus bewegt oder zum ersten Mal tippt. Solange sich nichts bewegt, läuft kein JavaScript, und der anfängliche Score steigt.
Das Problem liegt auf der Hand, wenn man darüber nachdenkt: genau dieser allererste Tap auf das Burger-Menü IST diese erste Interaktion. Dieser Tap öffnet also nicht das Menü, sondern er löst das Laden der Skripte aus. Bis diese eintreffen und sich an den Button hängen, ist Ihr Finger schon längst wieder weg. Das Menü öffnet sich erst beim zweiten Tap, wenn das Skript endlich da ist und lauscht.
Tap 1 → nichts
Der Tap wird „verbraucht“, um das Laden der Skripte zu starten, nicht um das Menü zu öffnen.
Tap 2 → das Menü öffnet sich
Die Skripte sind endlich geladen, und der Handler lauscht jetzt am Button.
Bei der Timer-Variante ist es noch deutlicher sichtbar: Wenn die Skripte „nach 3 Sekunden“ laden, steht ein Besucher, der vorher tippt, vor einem toten Burger-Menü.
Bestätigen, dass es wirklich daran liegt (30 Sekunden)
Drei einfache Prüfungen:
- Das Symptom ist konstant, nicht sporadisch: Es sind immer zwei Taps. Ein echter Bug wäre unregelmäßiger.
- DevTools-Netzwerktab: neu laden, nichts berühren und beobachten. Die Menü-Skripte (oft jQuery + das Theme-Skript) werden erst nach Ihrer ersten Interaktion heruntergeladen. Das ist die Signatur des Delays.
- Ausschlusstest: das JS delay vorübergehend deaktivieren. Reagiert das Burger-Menü beim ersten Tap, ist der Übeltäter identifiziert.
Lösung A: das Menü UND seine Abhängigkeiten isolieren
Die naheliegende Reaktion ist, das Menü-Skript vom Delay auszuschließen. Das ist notwendig, aber oft nicht ausreichend, und genau hier bleiben die meisten hängen.
Ein Theme-Menü funktioniert fast nie allein: Es hängt von anderen Skripten ab, typischerweise von jQuery (und manchmal jQuery Migrate oder dem Theme-Core). Schließen Sie das Menü-Skript aus, lassen aber jQuery im Delay, läuft das Menü-Skript, während jQuery noch nicht existiert: Es scheitert stillschweigend oder hängt sich an nichts. Ergebnis: Das Menü bleibt kaputt, und Sie verstehen nicht, warum, denn „das Menü ist doch ausgeschlossen“.
Sie müssen also die gesamte Kette ausschließen: jQuery → (jQuery Migrate) → das Menü-Skript. Gemeinsam.
Zwei konkrete Fallstricke bei der Deklaration dieser Ausschlüsse:
- Nach einem eindeutigen Bestandteil der Datei-URL zielen (zum Beispiel
jquery.min.jsoder dem Namen des Theme-Skripts), nicht nach dem internen „handle“: Je nach Tool kann das technische Suffix entfernt werden, wodurch der Ausschluss sein Ziel verfehlt. - Eine Absicherung des Dokumentzustands beibehalten: Das ausgeschlossene Skript muss ein frühes Ausführen vertragen (prüfen, ob das DOM bereit ist, bevor es sich an den Button hängt).
Der hinzunehmende Kompromiss: Indem Sie jQuery und das Menü aus dem Delay nehmen, laden Sie einen Teil des JavaScripts früher nach, sodass Sie einen Teil des Performance-Gewinns verlieren. Das ist akzeptabel, wenn Sie das Theme-Menü so beibehalten möchten, aber es ist nicht kostenlos.
Lösung B (der Idealfall): ein Vanilla-Menü ohne Abhängigkeit
Die wirklich dauerhafte Lösung, besonders bei einem schweren Theme (Divi zum Beispiel, wo es das Menü ist, das jQuery erzwingt), besteht darin, das Menü überhaupt nicht mehr von jQuery abhängen zu lassen.
Ein Burger-Menü ist im Kern trivial: ein Button, der eine Klasse an der Navigation umschaltet. Ein paar Zeilen natives JavaScript reichen aus, ganz ohne Abhängigkeit:
<button class="nav-toggle" aria-expanded="false" aria-controls="site-nav">Menu</button>
<nav id="site-nav" class="site-nav"><!-- links --></nav>
<script>
const btn = document.querySelector('.nav-toggle');
const nav = document.getElementById('site-nav');
btn.addEventListener('click', function () {
const open = nav.classList.toggle('is-open');
btn.setAttribute('aria-expanded', open);
});
</script>Weil dieses Skript winzig und abhängigkeitsfrei ist, eröffnen sich zwei Möglichkeiten:
- Sie binden es unverändert inline ein, nicht deferred, im Theme: Das Burger-Menü reagiert immer beim ersten Tap;
- und Sie können dann absolut alles andere deferren in Ihrem JavaScript, ganz beruhigt, da die einzige kritische Interaktion (das Öffnen des Menüs) von nichts mehr abhängt.
Ein nicht zu vernachlässigender Bonus: Bei vielen Themes ist das Menü der einzige Grund, warum jQuery mit Priorität lädt. Ein Vanilla-Menü kann Ihnen daher erlauben, jQuery vollständig aus dem kritischen Pfad zu nehmen. Das ist das Beste aus beiden Welten: ein sofortiges Menü und leichteres JavaScript.
Mit Mantys Core
Mantys Core deckt beide Wege präzise ab. Für Lösung A werden die Delay-Ausnahmen anhand eines URL-Fragments deklariert (nicht des zerbrechlichen handle) und berücksichtigen die Abhängigkeitskette, mit der Absicherung des Dokumentzustands, die dafür sorgt, dass der Ausschluss tatsächlich greift, statt stillschweigend zu scheitern.
Und für Lösung B ist der Ansatz „autarker, nicht deferred Block“ nativ eingebaut: Ein Vanilla-Menü kann außerhalb des Delays ausgeliefert werden, während der Rest des JavaScripts aufgeschoben wird, ohne dass Sie zwischen Score und Funktion jonglieren müssen.
Mit anderen Worten: Ob Sie das Theme-Menü behalten oder zu Vanilla wechseln, das Burger-Menü reagiert beim ersten Tap, ohne die Schlankheit des Rests zu opfern.
Zusammenfassend
- Der „obligatorische zweite Klick“ kommt vom JS delay: Der erste Tap weckt das Laden der Skripte, statt das Menü zu öffnen.
- Bestätigen Sie es, indem Sie beobachten, dass die Skripte erst nach der ersten Interaktion laden (oder indem Sie das Delay deaktivieren).
- Lösung A: das Menü UND seine Abhängigkeiten aus dem Delay ausschließen (jQuery eingeschlossen), Zielsetzung per URL, mit einer Zustandsabsicherung. Es funktioniert, kostet aber einen Teil des Gewinns.
- Lösung B (der Idealfall): ein Vanilla-Menü ohne Abhängigkeit, inline eingebunden und nicht deferred, das beim ersten Tap reagiert und es erlaubt, den Rest zu deferren, jQuery eingeschlossen.