• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

Frage Gutes Sticky Header Script

Aaron3219

Senior HTML'ler
Hey Forum,

nur kurz mal eine Frage an euch.
Kennt jemand ein gutes Script, für einen sticky header? Ich hatte bis jetzt ein gutes gefunden, der benutzt aber JQuery 1.7.1 und damit funktioniert der Rest meiner Seite nicht mehr. Also es sollte am besten eine möglichst aktuelle Version von Jquery sein oder einfach vanilla js.

Grüße
Aaron
 
Werbung:
Hey Forum,

nur kurz mal eine Frage an euch.
Kennt jemand ein gutes Script, für einen sticky header? Ich hatte bis jetzt ein gutes gefunden, der benutzt aber JQuery 1.7.1 und damit funktioniert der Rest meiner Seite nicht mehr. Also es sollte am besten eine möglichst aktuelle Version von Jquery sein oder einfach vanilla js.

Grüße
Aaron

Für was ein externes Script? Ein resize EventListener, ein scroll EventListener und eine Bedingung die dem Header entweder eine CSS Klasse hinzufügt oder entfernt - mehr braucht es nicht. Diese Bedingung ist die eigentliche "Kunst" daran und von Anwendungsfall zu Anwendungsfall unterschiedlich.

jQuery 1 und 2 ist außerdem weitestgehend kompatibel. Bei 3 weiß ich es nicht. Wenn du also bereits eine neuere Version verwendest, dann musst du keine alte stattdessen einbinden.

Des weiteren gibt es mittlerweile CSS-only Lösungen mit position:sticky. Hatte ich zwar noch nicht im Einsatz, aber vielleicht kommst du ja damit weiter.
 
Ich hatte das Thema in einem vorherigen Thread schon einmal angeschnitten. Da hatte ich es noch selber versucht, denn ich weiß ja theoretisch wie man das macht.

Hier mal eben mein script:
https://www.frachtagentur-krüger.de/test/js/sticky_header.js
Hier die Seite dazu:
https://www.frachtagentur-krüger.de/test/index.html

Es funktioniert aber alles irgendwie nicht:
Anleitung zur replikation eines bekannten bugs:
1. Scroll ein wenig runter bis der parallax effekt nicht mehr zu sehen ist (am besten noch weiter).
2. Resize das Fenster auf irgendeine Art.
3. Scroll wieder nach oben und teste.
4. wenn es trotzdem funktioniert einfach noch eln paar Mal testen, es funktioniert nur manchmal.

Also es hört sich danach an, als läuft etwas beim update der Variablen auf Resize falsch. Weiß nur nicht was.

Ich werde mich aber mal mit der CSS Variante beschäftigen.

Edit:
Sticky Header sind mit CSS aktuell nicht möglich. position: sticky; ist im Moment nur in der Experimentel Funktion von Chrom, FF, etc. möglich und muss manuell von jedem Nutzer freigeschaltet werden. Ich hoffe, dass es bald richtg freugeschaltet wird.
 
Zuletzt bearbeitet:
Werbung:
Also wenn jemand was nicht verstanden hat, dann bitte einfach fragen. Ich sitze schon so verdammt lange an diesem Problem und kriege es einfach nicht gebacken. Es wäre schön wenn sich jemand das Problem nochmal anschauen könnte.
 
Also wenn jemand was nicht verstanden hat, dann bitte einfach fragen. Ich sitze schon so verdammt lange an diesem Problem und kriege es einfach nicht gebacken. Es wäre schön wenn sich jemand das Problem nochmal anschauen könnte.

Hier mal ein Vorschlag meinerseits:
https://jsfiddle.net/0wvq8dp5/

Weniger JS, mehr CSS.

Bei dynamischer <nav>-Höhe könntest du im handleSticky den margin-top von <main> anhand der Höhe des <nav> setzen:
https://jsfiddle.net/0wvq8dp5/1/
 
Zuletzt bearbeitet:
Okay Danke schonmal scbawik für deine Antowort. Lustigerweise kam mir dieselbe Idee schon bevor du den Code gepostet hattest und ich habe es jetzt endlich hinbekommen.
Ich poste in später als Edit hier rein (zusammen mit einer kleinen Erklärung).
Wenn ich das richtig erkenne, haben wir in etwa den gleichen Pfad eingeschlagen @scbawik. Trotzdem ein Danke an dich.
Viele Tage Arbeit für nichts...
Es war in Prinzip so einfach.
Wie gesagt ich poste den Code später.
 
Werbung:
So hat leider ein wenig später als gedacht schicke ich hier mein Script mit für den Sticky Header:
Code:
var $window = $(window);
var $parallax_container = $(".parallax-container");
var $header = $("header");
var $main = $(".main");
var $wh = $parallax_container.height();
var $header_height = $header.height();

function abfrage() {
    $wh = $parallax_container.height();
    $header_height = $header.height();
    if ($window.scrollTop() >= $wh) {
        $header.addClass("fixed");
        $main.css("marginTop", $header_height);
    } else {
        $header.removeClass("fixed");
        $main.css("marginTop", 0);
    }
    return;
}
$(document).ready(function () {
    $window.on("resize scroll", function () {     
        abfrage();
    });

    abfrage();
});

Link:
https://www.xn--frachtagentur-krger-lbc.de/test/index.html
Kurze Erklärung:
Code:
var $window = $(window);
var $parallax_container = $(".parallax-container");
var $header = $("header");
var $main = $(".main");
Diese Variablen sind nur für die Performance wichtig.

Code:
var $wh = $parallax_container.height();
var $header_height = $header.height();
Mit diesen Variablen messe ich die Containerhöhe und die Höhe des Headers aus, da direkt darunter der Sticky Header sitzt (Ich messe die Höhe des Headers aus, da ich diese später als margin hinzfüge, damit sich nicht der Rest des Contents darunter verschiebt).

die function abfrage() wird immer beim resizen und scrollen ausgeführt (und einmal zu Anfang geladen).
Dafür ist dieser Teil zuständig:
Code:
$(document).ready(function () {
    $window.on("resize scroll", function () {      
        abfrage();
    });

    abfrage();
});


In der function abfrage() update ich alle Variablen, die für das resizen und scrollen wichtig sind (die Funktion wird ja wie gesagt beim scollen und resizen ausgeführt. Dadurch updaten sich die Variablen).
Code:
$wh = $parallax_container.height();
$header_height = $header.height();
Da hier nun kein var mehr vor steht, werden die lokalen Variablen von den Globalen Variablen überschrieben.

Code:
if ($window.scrollTop() >= $wh) {
        $header.addClass("fixed");
        $main.css("marginTop", $header_height);
} else {
        $header.removeClass("fixed");
        $main.css("marginTop", 0);
}
In der Variable $wh ist der Abstand von ganz oben der Seite bis zum Header gespeichert (Diese muss beim resizen und scrollen überschrieben werden, da diese bei mir responsive ist und mehr CSS verändert wird).
Das Prinzip ist ganz einfach. Ich messe mit $window.scrollTop() den Abstand aus, der heruntergescrollt wurde. Ist dieser >= $wh wird die Klasse fixed zum header hinzugefügt und das margin gesetzt, damit sich der Rest des Contents nicht verschiebt. Ist $window.scrollTop() < $wh wird das margin und die Klasse fixed wieder weggenommen.

So ich hoffe das war einigermaßen verständlich. Falls jemand noch Verbesserungsvorschläge für das Script hat, dann schreibt es gerne. Da geht bestimmt noch mehr an Performance (Schließlich werden JEDES Mal 2 Variablen beim Scrollen und resizen überschrieben).
 
So hat leider ein wenig später als gedacht schicke ich hier mein Script mit für den Sticky Header:
Code:
var $window = $(window);
var $parallax_container = $(".parallax-container");
var $header = $("header");
var $main = $(".main");
var $wh = $parallax_container.height();
var $header_height = $header.height();

function abfrage() {
    $wh = $parallax_container.height();
    $header_height = $header.height();
    if ($window.scrollTop() >= $wh) {
        $header.addClass("fixed");
        $main.css("marginTop", $header_height);
    } else {
        $header.removeClass("fixed");
        $main.css("marginTop", 0);
    }
    return;
}
$(document).ready(function () {
    $window.on("resize scroll", function () {    
        abfrage();
    });

    abfrage();
});

Link:
https://www.xn--frachtagentur-krger-lbc.de/test/index.html
Kurze Erklärung:
Code:
var $window = $(window);
var $parallax_container = $(".parallax-container");
var $header = $("header");
var $main = $(".main");
Diese Variablen sind nur für die Performance wichtig.

Code:
var $wh = $parallax_container.height();
var $header_height = $header.height();
Mit diesen Variablen messe ich die Containerhöhe und die Höhe des Headers aus, da direkt darunter der Sticky Header sitzt (Ich messe die Höhe des Headers aus, da ich diese später als margin hinzfüge, damit sich nicht der Rest des Contents darunter verschiebt).

die function abfrage() wird immer beim resizen und scrollen ausgeführt (und einmal zu Anfang geladen).
Dafür ist dieser Teil zuständig:
Code:
$(document).ready(function () {
    $window.on("resize scroll", function () {     
        abfrage();
    });

    abfrage();
});


In der function abfrage() update ich alle Variablen, die für das resizen und scrollen wichtig sind (die Funktion wird ja wie gesagt beim scollen und resizen ausgeführt. Dadurch updaten sich die Variablen).
Code:
$wh = $parallax_container.height();
$header_height = $header.height();
Da hier nun kein var mehr vor steht, werden die lokalen Variablen von den Globalen Variablen überschrieben.

Code:
if ($window.scrollTop() >= $wh) {
        $header.addClass("fixed");
        $main.css("marginTop", $header_height);
} else {
        $header.removeClass("fixed");
        $main.css("marginTop", 0);
}
In der Variable $wh ist der Abstand von ganz oben der Seite bis zum Header gespeichert (Diese muss beim resizen und scrollen überschrieben werden, da diese bei mir responsive ist und mehr CSS verändert wird).
Das Prinzip ist ganz einfach. Ich messe mit $window.scrollTop() den Abstand aus, der heruntergescrollt wurde. Ist dieser >= $wh wird die Klasse fixed zum header hinzugefügt und das margin gesetzt, damit sich der Rest des Contents nicht verschiebt. Ist $window.scrollTop() < $wh wird das margin und die Klasse fixed wieder weggenommen.

So ich hoffe das war einigermaßen verständlich. Falls jemand noch Verbesserungsvorschläge für das Script hat, dann schreibt es gerne. Da geht bestimmt noch mehr an Performance (Schließlich werden JEDES Mal 2 Variablen beim Scrollen und resizen überschrieben).

Extra Variablen für die .height()’s zu definieren, bringt nichts.
Vor allem die header.height() wird ohnehin nur benötigt, wenn die Bedingung true ist.
parallax.height() ebenso nur einmal im if-Statement.

$(document).ready() wird nicht benötigt wenn du das Script einfach am Ende des Codes einfügst - wie es sich für JavaScripts gehört.

JavaScript Variablen schreibt man in lowerCamelCase, Konstanten in UPPERCASE_UND_UNDERSCORE und Klassen in CapitalizedCamelCase. Gleiches gilt übrigens auch für PHP.

Des weiteren habe ich gesehen, dass du meine $-Naming Strategie übernommen hast. Allerdings nicht richtig.
Ich mache das nur, um jQuery Objekte bereits am Namen von Vanilla JS zu unterscheiden. Wenn du das bei allen Variablen machst, kannst du auch gleich komplett darauf verzichten. Was natürlich auch ok ist.
Überall $-Präfix zu verwenden ist jedoch nicht zielführend.

Des weiteren ist es ganz praktisch alles in eine self-invoking function zu packen (die richtige Bezeichnung fällt mir gerade nicht ein), um eine Isolation deines Scripts zu erzeugen:

Code:
var xyz = 1;

(function ($, window, someVar) {

    var xyz = 2;

    console.log(someVar);    // Output: 1
    console.log(window.xyz); // Output: 1
    console.log(xyz);        // Output: 2

})(jQuery, window, xyz); // <—- Die benötigten Variablen als Parameter übergeben

Dadurch vermeidest du Konflikte mit Variablen aus anderen Scripts.

Habe ich in meinem JSFiddle natürlich nicht gemacht, da es das einzige Script auf der Seite ist.
 
Des weiteren habe ich gesehen, dass du meine $-Naming Strategie übernommen hast. Allerdings nicht richtig.
Ich mache das nur, um jQuery Objekte bereits am Namen von Vanilla JS zu unterscheiden. Wenn du das bei allen Variablen machst, kannst du auch gleich komplett darauf verzichten. Was natürlich auch ok ist.
Überall $-Präfix zu verwenden ist jedoch nicht zielführend.
Lustigerweise nicht. Das kommt, da ich, als ich mit Jquery und JS angefangen habe, dachte, dass man Variablen wie in PHP mit $ am Anfang schreiben muss. Nach kurzer Zeit wusste ich dann, dass muss gar nicht sein. Ich habe es aber (zumindest in meinen Scripten oft) weiter so gemacht. Stört ja keinen.

$(document).ready() wird nicht benötigt wenn du das Script einfach am Ende des Codes einfügst - wie es sich für JavaScripts gehört.
Also dass man JS am Ende einbindet ist ja klar. Aber dass man dann kein document ready benötigt war mir gar nicht klar o_O. Danke für den Hinweis.

Des weiteren ist es ganz praktisch alles in eine self-invoking function zu packen (die richtige Bezeichnung fällt mir gerade nicht ein), um eine Isolation deines Scripts zu erzeugen
Ja macht Sinn:
Code:
(function ($, window) {
//Hier der Code
})(jQuery, window);

JavaScript Variablen schreibt man in lowerCamelCase, Konstanten in UPPERCASE_UND_UNDERSCORE und Klassen in CapitalizedCamelCase. Gleiches gilt übrigens auch für PHP.
Aah, dacht ich's mir doch. Ich hab mich schon oft gefragt, ob underscore eigentlich als "Wörtertrennnung" benutzt wird. Danke für die Info.
Variable wird also von $header_height = $headerHeight (da diese ja ach responsive ist und keine Konstante).

Edit:
Obwohl...
$header.height() ist ja im Prinzip fast eine konstante...
es ändert sich nur ab einer Fenstergröße von 615px um 10px.
Es ist also qasi eine Konstante.
Ist es dann nicht schlauer, noch eine if-Abfrage nach der Fenstergröße zu fragen, und wenn diese < 615 ist, die Konstante + 10 zu nehmen? Ansonsten wird ja bei JEDEM Scroll und resize Event der Header neu ausgemessen.

2 Edit:
Ne stimmt gar nicht... das erste Edit ist Schwachsinn. Ich brauche ja gar keine variablen in der if-Funktion. Es werden also keine Variablen aktualisiert.
Damit hätte sich das hier auch erledigt:
Extra Variablen für die .height()’s zu definieren, bringt nichts.
Vor allem die header.height() wird ohnehin nur benötigt, wenn die Bedingung true ist.
parallax.height() ebenso nur einmal im if-Statement.


Hier also folgender resultierender Code:
Code:
(function ($, window) {
    var $window = $(window);
    var $parallaxContainer = $(".parallax-container");
    var $header = $("header");
    var $main = $(".main");

    function abfrage() {
        if ($window.scrollTop() >= $parallaxContainer.height()) {
            $header.addClass("fixed");
            $main.css("marginTop", $header.height());
        } else {
            $header.removeClass("fixed");
            $main.css("marginTop", 0);
        }
        return;
    }

    $window.on("resize scroll", function () {
        abfrage();
    });

    abfrage();

})(jQuery, window);
Danke für die Tipps!
 
Zuletzt bearbeitet:
Werbung:
Lustigerweise nicht. Das kommt, da ich, als ich mit Jquery und JS angefangen habe, dachte, dass man Variablen wie in PHP mit $ am Anfang schreiben muss. Nach kurzer Zeit wusste ich dann, dass muss gar nicht sein. Ich habe es aber (zumindest in meinen Scripten oft) weiter so gemacht. Stört ja keinen.


Also dass man JS am Ende einbindet ist ja klar. Aber dass man dann kein document ready benötigt war mir gar nicht klar o_O. Danke für den Hinweis.


Ja macht Sinn:
Code:
(function ($, window) {
//Hier der Code
})(jQuery, window);


Aah, dacht ich's mir doch. Ich hab mich schon oft gefragt, ob underscore eigentlich als "Wörtertrennnung" benutzt wird. Danke für die Info.
Variable wird also von $header_height = $headerHeight (da diese ja ach responsive ist und keine Konstante).

Edit:
Obwohl...
$header.height() ist ja im Prinzip fast eine konstante...
es ändert sich nur ab einer Fenstergröße von 615px um 10px.
Es ist also qasi eine Konstante.
Ist es dann nicht schlauer, noch eine if-Abfrage nach der Fenstergröße zu fragen, und wenn diese < 615 ist, die Konstante + 10 zu nehmen? Ansonsten wird ja bei JEDEM Scroll und resize Event der Header neu ausgemessen.

2 Edit:
Ne stimmt gar nicht... das erste Edit ist Schwachsinn. Ich brauche ja gar keine variablen in der if-Funktion. Es werden also keine Variablen aktualisiert.
Damit hätte sich das hier auch erledigt:



Hier also folgender resultierender Code:
Code:
(function ($, window) {
    var $window = $(window);
    var $parallaxContainer = $(".parallax-container");
    var $header = $("header");
    var $main = $(".main");

    function abfrage() {
        if ($window.scrollTop() >= $parallaxContainer.height()) {
            $header.addClass("fixed");
            $main.css("marginTop", $header.height());
        } else {
            $header.removeClass("fixed");
            $main.css("marginTop", 0);
        }
        return;
    }

    $window.on("resize scroll", function () {
        abfrage();
    });

    abfrage();

})(jQuery, window);
Danke für die Tipps!

Jep, sieht jetzt gut aus ;)
 
Zurück
Oben