Ich sehe vor lauter Bäumen den Wald nicht mehr
Lukas.
- css
Hallo Forum,
ich würde gerne von dieser Seite den "shrinking fixed header" übernehmen.
Mir gelingt es zwar, nahezu den kompletten Rest heraus zu löschen. Was mir aber nicht gelingt, ist den wirklich relevanten Code, der den Header betrifft zu separieren. Ich schleppe also massig Balast (an js und css Dateien, bzw. Code) mit mir herum, den ich niemals wirklich brauchen werde, der aber relevanten Code nur noch schwer veränderbar macht, weil ich ihn nicht finde.
Wie kann ich es schaffen, nur die relevanten Dateien bzw. Codezeilen zu identifizieren?
L.
Hello,
selber machen!
Mit jQuery einen Event-Listener einbauen:
$(window).scroll(
function()
{
if($(window).scrollTop() >= ($(document).height() - $(window).height() -2))
{
// deine Aktionen
myAction();
}
}
);
Habe ich gerade damit herumgespielt
Liebe Grüße
Tom S.
Hello,
selber machen!
Habe ich gerade damit herumgespielt
Wie bitte? *g* ( Sorry, der musste jetzt sein 😉 )
Hallo Tom,
Mit jQuery einen Event-Listener einbauen:
$(window).scroll( function() { if($(window).scrollTop() >= ($(document).height() - $(window).height() -2)) { // deine Aktionen myAction(); } } );
Na, das ist aber schion noch was anderes. Wenn Du eine Navigation mit Logo und "smoothen" Übergängen haben möchtest, ist das dann doch nicht so einfach. Ich habe das Original jetzt weitestgehend isoliert, aber schleppe doch noch z.b den kompletten bootstrap ccs Code mit mir herum.
L.
Hej Lukas.,
Mit jQuery einen Event-Listener einbauen:
Na, das ist aber schion noch was anderes. Wenn Du eine Navigation mit Logo und "smoothen" Übergängen haben möchtest, ist das dann doch nicht so einfach.
Dann suchst du nach CSS-Animationen und/oder Transitions... 😉
Hilft das weiter?
Gerade so etwas selber zu bauen macht sehr viel Spaß - auch wenn es etwas dauert.
Aber nicht übertreiben!!!
Marc
Hi Marc,
Dann suchst du nach CSS-Animationen und/oder Transitions... 😉
Hilft das weiter?
Geht so...
Gerade so etwas selber zu bauen macht sehr viel Spaß - auch wenn es etwas dauert.
Mir gar nicht. Mir macht programmieren Spaß, Design ist so gar nicht meines…
L.
Hello Lukas,
ich habe mal 'was gebastelt. Da fallen zwar garantiert gleich wieder Einige mit nebensächlichen Verwässerungsvorschlägen (sic!) drüber her, aber das muss ich dann eben aushalten ;-P
Weitere Ideen:
Und wenn wir das dann hier nach und nach veröffentlichen, haben wir auch schon fast wieder einen Artikel fürs Wiki. Da müssen die Verbesserer dann natürlich noch vorher ran ;-)
<?php ### shrinking_header.php ### utf-8 ### ÄÖÜäöü
header('Content-Type: text/html; CharSet=utf-8');
?>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Shrinking Header</title>
<script src="/jQuery.js"></script>
<script>
$(document).ready(
function()
{
function setHeaderHeight(height)
{
$( "header" ).height(height);
// weitere für Textgrößen, Farben etc.
}
$(window).scroll(
function()
{
$( "footer" ).text('DocHeight = ' + $(document).height() +', ScrollTop = ' + $(window).scrollTop() );
if($(window).scrollTop() > 200)
{
// deine Aktionen
setHeaderHeight(100);
// $( "section#Sec02" ).text('Hallo');
}
else if ($(window).scrollTop() < 120)
{
setHeaderHeight(200);
// $( "section#Sec02" ).text('Selber Hallo');
}
}
);
}
);
</script>
<style>
html, body {
width: 100%;
margin: 0;
font-family: "Century Gothic", Helvetica, Tahoma, sans-serif;
}
main {
width: 100%
margin: 0;
margin-top: 220px;
padding-bottom: 25pt;
}
header {
position: fixed;
top: 0;
left: 0;
width: 100%;
padding: 0 20pt;
height: 200px;
background-color: #AAAAAA;
}
section {
margin: 20pt;
padding: 15pt;
/* width: calc(100% - 70pt); */
height: 500px;
background-color: #ffffbb;
border: 1px solid #8080ff;
border-radius: 10pt;
-moz-border-radius: 10pt;
-webkit-border-radius: 10pt;
}
footer {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 10pt;
padding: 5pt 20pt; /*top+bottom - left+right */
background-color: #FFA0A0;
border-top: 1px solid #808080;
}
</style
</head>
<body>
<header>
<h1>Shrinking Header</h1>
<p>Die Kunst nach Kunst auszusehen</p>
</header>
<main>
<section id="Sec01">
Nur zum Füllen
</section>
<section id="Sec02">
Nur zum Füllen
</section>
</main>
<footer>
Footer-Text
</footer>
<nav>
</nav>
</body>
</html>
Liebe Grüße
Tom S.
Aloha ;)
ich habe mal 'was gebastelt. Da fallen zwar garantiert gleich wieder Einige mit nebensächlichen Verwässerungsvorschlägen (sic!) drüber her, aber das muss ich dann eben aushalten ;-P
Aber gerne doch 😝
Wie verträgt sich...
$(window).scroll( function() { $("footer").text('DocHeight = '+$(document).height()+', ScrollTop = '+$(window).scrollTop() ); if($(window).scrollTop() > 200) { // deine Aktionen setHeaderHeight(100); // $( "section#Sec02" ).text('Hallo'); } else if ($(window).scrollTop() < 120) { setHeaderHeight(200); // $( "section#Sec02" ).text('Selber Hallo'); } } );
...mit dem neulich von @Gunnar Bittersmann formulierten Grundsatz
Aufs scroll-Event reagieren (das etliche Male pro Sekunde feuert), ist nichts, was man tun möchte, wenn man nicht muss.
Mein Gefühl sagt eher nicht so, aber ich mag mich täuschen.
Ich hab das mal in einem Pen nachgebaut und finde, dass das eher irritiert - zusätzlich zum Performance-Debakel. Der Header springt irgendwann auf eine kleinere Größe um, das ist nicht grad toll.
Ich hab mal einen Alternativvorschlag geforked, der einen besseren visuellen Eindruck macht und komplett ohne Javascript auskommt. Die Essenz davon ist:
body {
margin-top:200px;
background-color:white;
}
html {
background-color:#AAAAAA;
}
header {
position: fixed;
top: 0;
left: 0;
width: 100%;
padding: 0 20pt;
height: 100px;
background-color: #AAAAAA;
}
Das ist nur eine von mehreren Möglichkeiten, wie man das mit reinem CSS umsetzen kann und sie sind vermutlich fast alle besser als mit JavaScript auf eine Änderung bei scroll
zu horchen.
Grüße,
RIDER
Hello Janosch,
Ich hab mal einen Alternativvorschlag geforked, der einen besseren visuellen Eindruck macht und komplett ohne Javascript auskommt. Die Essenz davon ist:
body { margin-top:200px; background-color:white; } html { background-color:#AAAAAA; } header { position: fixed; top: 0; left: 0; width: 100%; padding: 0 20pt; height: 100px; background-color: #AAAAAA; }
Netter Fake. Kommt aber in die Sammlung.
Ich musste doch genau suchen, wo sie Stelle mit dem Trick steckt, obwohl mir klar war, was da wohin geschoben wird ;-)
Ist aber an der Aufgabenstellung vorbei.
Eine der Aufgaben war, den Header (smoothing) zu verleinern, inclusive seiner Inhalte, also auch der Texte usw.. Ich habe da nur erst mal einen Weg ausprobiert, wie man das überhaupt erreichen kann, den Header zu verkleinern, nicht nur seine vermeintliche Höhe. An der Inhaltsverkleinerung muss noch gearbeitet werden.
Aber vielleicht kann mir hier jemand sagen, wie ich innerhalb der Closure eine static Var anlegen kann, die beim ersten Aufruf gefüllt wird und dann bei jedem weiteren Aufruf wieder zur Verfügung steht?
Liebe Grüße
Tom S.
Aloha ;)
Netter Fake. Kommt aber in die Sammlung.
Fake ist das A und O um mit CSS zu bekommen was man will 😀
Ist aber an der Aufgabenstellung vorbei.
Kommt drauf an. Das ist als Anregung zu verstehen - genau genommen wissen wir ja gar nicht, ob der TO wirklich so „viel“ sucht wie im ursprünglichen Vorbild oder ob ein einfaches Schrumpfen in der Höhe genügt. Je nach Wunsch lassen sich eventuell auch mehrere Fakes kombinieren, um das gewünschte zu erreichen. Ich will hier aber nicht mehr Kreativität als Notwendigkeit für ein kleines Machbarkeitsbeispiel aufbringen.
Eine der Aufgaben war, den Header (smoothing) zu verleinern, inclusive seiner Inhalte, also auch der Texte usw.. Ich habe da nur erst mal einen Weg ausprobiert, wie man das überhaupt erreichen kann, den Header zu verkleinern, nicht nur seine vermeintliche Höhe. An der Inhaltsverkleinerung muss noch gearbeitet werden.
Schau dir mal an, was ich noch geschrieben habe - ich habe mal analysiert, was genau die vorliegende Seite eigentlich tut. Der Weg beruht dann zwar immer noch auf dem Scroll-EventListener (wünschenswert wäre eine Alternative ohne), aber ist dann was die Effekte angeht beliebig erweiterbar - mit so wenig wie möglich Overhead im JS-Teil, der im schlimmsten Fall mehrmals je Sekunde ausgeführt werden muss beim Scrollen.
Grüße,
RIDER
Hello,
Aber vielleicht kann mir hier jemand sagen, wie ich innerhalb der Closure eine static Var anlegen kann, die beim ersten Aufruf gefüllt wird und dann bei jedem weiteren Aufruf wieder zur Verfügung steht?
Ich habe das jetzt so gelöst. Ob es richtig™️ ist, weiß ich nicht, aber es funktioniert.
function setHeaderHeight(height)
{
if (!this.fsize) this.fsize = $( "header h1" ).css("font-size");
if (!this.hheight) this.hheight = $( "header" ).height();
$( "header" ).height(height);
var newfsize = (parseInt(fsize) * height / hheight) + 'px';
$( 'header h1' ).css( { 'font-size':newfsize} );
}
und das CSS habe ich so geändert:
header {
position: fixed;
top: 0;
left: 0;
width: 100%;
padding: 0 20pt;
height: 200px;
background-color: #AAAAAA;
transition: height 2s;
}
header h1 {
font-size: 40pt;
transition: font-size 2s;
}
Das leistet schon mal einen Großteil von dem, was Lukas haben wollte. Zumindest zeigt es einen Weg auf, wie man es erreichen kann.
Ob der scroll()-Event-Listener selbst nun so besonders teuer ist, vermag ich nicht zu sagen. Eine merkliche Systemlaststeigerung kann ich nicht feststellen dadurch. Vermutlich lacht das System darüber.
Dass man allerdings nochmal über einen oder zwei Schalter nachdenken sollte, der regelt, dass die Funktionen, die der Scroll-Handler ausführen soll, nur dann anspringen, wenn sie auch gebraucht werden, bleibt als Aufgabe.
Liebe Grüße
Tom S.
Aloha ;)
Das leistet schon mal einen Großteil von dem, was Lukas haben wollte. Zumindest zeigt es einen Weg auf, wie man es erreichen kann.
Du verwendest immer noch JavaScript um visuelle Details umzuschalten, machst die Animation also "zu Fuß" und dadurch, dass...
Dass man allerdings nochmal über einen oder zwei Schalter nachdenken sollte, der regelt, dass die Funktionen, die der Scroll-Handler ausführen soll, nur dann anspringen, wenn sie auch gebraucht werden, bleibt als Aufgabe.
...das in deiner Lösung nicht vorkommt wird jedesmal der gesamte Code für die Änderungen ausgeführt. Dein System lacht vermutlich darüber - ein älteres Smartphone eher nicht. Vor allem dann nicht, wenn jedes visuelle Detail extra mit einem JS-Aufruf umgeschaltet wird.
Die Devise sollte sein: JavaScript protokolliert die Änderung, da das mit CSS nicht möglich ist (das verbraucht nur sehr überschaubar performance), CSS reagiert auf die Veränderung mit visueller Anpassung.
Das nutzt alle Performance-Vorteile optimal aus. - Immerhin ist die Browserengine auch daraufhin optimiert, Animationen / Transitions mit CSS umzusetzen, während das zu-Fuß-Realisieren einer Animation im Vergleich teuer sein sollte (bei jeder Änderung, die JS auslöst, muss die Browserengine die Darstellung anpassen und das gesamte Programm, das bei CSS-Veränderung abgespult werden muss, muss durchlaufen während das innerhalb einer CSS-Animation schätzungsweise optimiert stattfindet, da der CSS-Teil der Engine nur auf interne Impulse und nicht auf unvorhersehbare externe Vorgaben aus dem JS-Teil reagieren muss).
Grüße,
RIDER
@@TS
Ich habe das jetzt so gelöst. Ob es richtig™️ ist, weiß ich nicht, aber es funktioniert.
Nein, nicht richtig™️. Da du auf archivierte Postings stehst, hab ich eins von Cheatah für dich.
„Funktioniert“ ist ein notwendiges Kriterium für „richtig“, aber kein hinreichendes.
LLAP 🖖
Aloha ;)
Vielleicht noch was zur Performance-Problematik. Vergleich mal deinen JS-Ansatz
$(window).scroll( function() { $("footer").text('DocHeight = '+$(document).height()+', ScrollTop = '+$(window).scrollTop() ); if($(window).scrollTop() > 200) { // deine Aktionen setHeaderHeight(100); // $( "section#Sec02" ).text('Hallo'); } else if ($(window).scrollTop() < 120) { setHeaderHeight(200); // $( "section#Sec02" ).text('Selber Hallo'); } } );
mit meinem.
Hier muss bei jedem Scroll-Vorgang alles was an Anweisungen passieren kann auch ausgeführt werden (da mindestens if
oder else if
fast immer ausgeführt werden) - und das obwohl eigentlich nur in genau einem Fall eine tatsächliche Änderung stattfindet - nämlich dann, wenn der Scroll-Zustand nicht zum aktuellen visuellen Zustand passt. Im vorliegenden Beispiel sind das nur zwei Anweisungen je Scrollvorgang. Bei mehr gewünschten Effekten wird das aber stark wachsen - die Lösung skaliert also nicht.
In meiner Lösung bzw. dem, was auf der vorliegenden Seite eingesetzt wird, wird bei den allermeisten Scroll-Vorgängen ausschließlich mit zwei Wertabfragen geprüft, ob eine Aktion notwendig ist, und falls nein überhaupt nichts getan. Das ist performancetechnisch sehr viel sicherer als das Ausführen der Anweisungen ohne Wenn und Aber und dadurch, dass im Resultat nur eine Klasse umgeschaltet wird während die Effekte im CSS geschehen ist sichergestellt, dass die Lösung auch bei mehr Effekten noch fast mit der selben Performance arbeitet, sie skaliert also vergleichsweise gut.
Grüße,
RIDER
Hello,
prima, dass Du der gleichen Ansicht bist, wie ich.
Ich hatte das ja schon recht früh erwähnt, dass man die Hysterese besser abfragen und nutzen kann, als jedes Mal alle Aktionen bis in die Tiefe durchzuführen. Nur irgendwie muss man die Schritte wohl nacheinender mache, wenn man beim Erläutern nicht stolpern will?
Bisher hat sich Lukas noch nicht wieder zu Wort gemeldet.
Liebe Grüße
Tom S.
Hi there,
selber machen!
Mit jQuery einen Event-Listener einbauen:
"Selber machen" und "jQuery" beinhaltet jetzt aber schon eine gewisse Dichotomie. Er wollte den ganzen überflüssigen js- und css-Müll ja loswerden…
Hello,
selber machen!
Mit jQuery einen Event-Listener einbauen:
"Selber machen" und "jQuery" beinhaltet jetzt aber schon eine gewisse Dichotomie. Er wollte den ganzen überflüssigen js- und css-Müll ja loswerden…
Einverstanden.
Aber sas sollte bei der Aufgabenstellung auch noch möglich sein. Nur das JavaScript-Modul im Browser schreiben wir nicht selber! Ok?
Liebe Grüße
Tom S.
Aloha ;)
ich würde gerne von dieser Seite den "shrinking fixed header" übernehmen.
Mir gelingt es zwar, nahezu den kompletten Rest heraus zu löschen. Was mir aber nicht gelingt, ist den wirklich relevanten Code, der den Header betrifft zu separieren. Ich schleppe also massig Balast (an js und css Dateien, bzw. Code) mit mir herum, den ich niemals wirklich brauchen werde, der aber relevanten Code nur noch schwer veränderbar macht, weil ich ihn nicht finde.
Wie kann ich es schaffen, nur die relevanten Dateien bzw. Codezeilen zu identifizieren?
Mit deinem Inspector (z.B. in Chrome - Rechtsklick - Untersuchen). Damit kannst du beobachten, was denn eigentlich beim Scrollen passiert. Du wirst dann feststellen, dass beim Scrollen (und das funktioniert tatsächlich über einen Javascript-Event-Handler ähnlich zu TS Vorschlag mit den von mir genannten gravierenden Nachteilen) dem Body eine Klasse fixed-header-on
hinzugefügt (und bei wieder-hochscrollen entsprechend entfernt. Mit nativem JavaScript funktioniert das so (im Original wird ein JS-Framework verwendet):
function checkScroll() {
if(window.pageYOffset > 0 && !document.body.classList.contains("fixed-header-on")) {
document.body.classList.add("fixed-header-on");
} else if (window.pageYOffset == 0 && document.body.classList.contains("fixed-header-on")) {
document.body.classList.remove("fixed-header-on");
}
}
window.addEventListener("scroll",checkScroll);
window.addEventListener("load",checkScroll); // Falls mit Anker gesprungen wurde!
Das war der Teil, der den Header umschaltet. Wie das umschalten auf CSS-Basis funktioniert kannst du auch im Inspektor nachvollziehen. Such dafür im Inspektor den <header>
. Bei dessen CSS-Regeln siehst du, wenn du heruntergescrollt hast
.header {
color: #fff;
background-color: rgba(0,0,0,0.10);
padding: 10px 0;
-webkit-transition: all 0.2s ease-in-out;
-moz-transition: all 0.2s ease-in-out;
-o-transition: all 0.2s ease-in-out;
-ms-transition: all 0.2s ease-in-out;
transition: all 0.2s ease-in-out;
}
.fixed-header-on .header {
background-color: rgba(0,0,0,0.95);
padding: 5px 0;
}
Dieser CSS-Code tut all das[1], was die Animation hergibt. Die relevante Zeile für die Animation ist:
transition: all 0.2s ease-in-out;
Die transition-Angaben mit vendor-prefixes tun dasselbe und werden in aktuellen Browsern sowieso durch die Zeile ohne vendor-prefix überschrieben.
Wie du in unserem Wiki erfährst bedeutet diese Zeile:
transition
: Lass CSS-Änderungen schrittweise anwendenall
: und zwar bei jeder sich ändernden Eigenschaft0.2s
: mit einer Überblend-Dauer von 0.2sease-in-out
: Übergangsmodus mit einem langsamen Start und EndeDie sich verändernden CSS-Eigenschaften ergeben sich aus den CSS-Regeln für .fixed-header-on .header
, die nur dann greifen, wenn im Window der Scroll-Balken nicht ganz oben liegt.
Auch wenn du jetzt nach dieser Erklärung hoffentlich verstanden hast, wie die vorliegende Seite das löst, wäre es trotzdem nicht schlecht, sich noch Gedanken darüber zu machen, wie man das vorliegende ohne Javascript lösen kann - z.B. durch geschickte Verschiebung des Body und fixierten, kleineren header wie in meinem Alternativvorschlag oder durch eine andere kreative Idee.
Grüße,
RIDER
all das ist ein wenig geflunkert. Die veränderte Schriftgröße beispielsweise wird so realisiert, indem das entsprechende Sub-Element auch über diese transition-Eigenschaft und den zweiten Satz CSS-Regeln verfügt, aber das Prinzip ist das selbe - und grade die Sache mit der Schriftgröße hätte man sehr viel besser über eine Basis-Schriftgrößenänderung im header direkt und relative Schriftgröße in den Unterelementen lösen können. Aber wie gesagt - selbes Prinzip, je Effekt der nur auf Sub-Elemente angewandt werden soll ein wenig mehr CSS. ↩︎
Aloha ;)
Mit deinem Inspector (z.B. in Chrome - Rechtsklick - Untersuchen). Damit kannst du beobachten, was denn eigentlich beim Scrollen passiert. Du wirst dann feststellen, dass beim Scrollen (und das funktioniert tatsächlich über einen Javascript-Event-Handler ähnlich zu TS Vorschlag mit den von mir genannten gravierenden Nachteilen) dem Body eine Klasse
fixed-header-on
hinzugefügt (und bei wieder-hochscrollen entsprechend entfernt. Mit nativem JavaScript funktioniert das so (im Original wird ein JS-Framework verwendet):function checkScroll() { if(window.pageYOffset > 0 && !document.body.classList.contains("fixed-header-on")) { document.body.classList.add("fixed-header-on"); } else if (window.pageYOffset == 0 && document.body.classList.contains("fixed-header-on")) { document.body.classList.remove("fixed-header-on"); } } window.addEventListener("scroll",checkScroll); window.addEventListener("load",checkScroll); // Falls mit Anker gesprungen wurde!
Eventuell ist das Verwenden des Scroll-Event hier ausnahmsweise einigermaßen gerechtfertigt. Josh Broton schlägt in seinem Artikel vor, eine Intervall-Lösung zu nutzen, die nur in gewissen Zeitabständen wirklich tätig wird. Unterm Strich muss aber auch bei seiner Lösung dadurch jedesmal mindestens ein if
durchlaufen werden. Das unterscheidet sich nicht sehr vom Aufwand der hier vorliegenden Lösung (ohne Intervall) je Scroll-Auslöser. Vielleicht lässt sich die Performance sogar noch verbessern, indem der meist-vorkommende Fall (es wird gescrollt und es war davor auch schon gescrollt) bevorzugt abgefangen wird:
function checkScroll() {
if(window.pageYOffset > 0) {
if (document.body.classList.contains("fixed-header-on")) {
return true;
} else {
document.body.classList.add("fixed-header-on");
}
} else if (document.body.classList.contains("fixed-header-on")) {
document.body.classList.remove("fixed-header-on");
}
}
window.addEventListener("scroll",checkScroll);
window.addEventListener("load",checkScroll); // Falls mit Anker gesprungen wurde!
Eine weitere kleine Performance-Verbesserung kann man vielleicht erreichen, indem man eine fixe Boolean-Variable window.hasScrolled
verwendet statt des classList.contains-Aufruf, aber ich denke das ist performancetechnisch verschmerzbar.
Unter diesem Umstand kann man den Code hier vielleicht so verwenden, ohne große Performance-Bauchschmerzen zu bekommen.
Grüße,
RIDER
Hello,
Eine weitere kleine Performance-Verbesserung kann man vielleicht erreichen,
Wieso, ist Dein System zu langsam? Ich betreibe das hier (bekanntermaßen) auf Museumstechnik und die kommt überhaupt nicht ins Schwitzen davon.
indem man eine fixe Boolean-Variable
window.hasScrolled
verwendet statt des classList.contains-Aufruf, aber ich denke das ist performancetechnisch verschmerzbar.Unter diesem Umstand kann man den Code hier vielleicht so verwenden, ohne große Performance-Bauchschmerzen zu bekommen.
Von einer globalen Variable window.hasScrolled
würde ich nun wieder abraten. Die sollte schön geschützt werden! Wer weiß, was sonst noch alles in die Seite kommen soll. "Immer brav kapseln" habe ich im SelfHTML-Forum gelernt. Aber da warst Du vermutlich noch nicht dabei ;-)
Und die Sache mit den Closures hat Christian ja neulich nochmal ausführlich erklärt.
Liebe Grüße
Tom S.
Aloha ;)
Eine weitere kleine Performance-Verbesserung kann man vielleicht erreichen,
Wieso, ist Dein System zu langsam? Ich betreibe das hier (bekanntermaßen) auf Museumstechnik und die kommt überhaupt nicht ins Schwitzen davon.
Das zeigt die Erfahrung - mit dem, was momentan in deinem Code steht, crasht die Performance vielleicht noch nicht. Mit dem was am Ende drinstehen würde geht die Performance aber baden - weil das System so wie es ist schlecht skaliert falls du nicht entsprechende Schalter einbaust.
Die Schalter sind aber nicht die optionale Performance-Steigerung sondern die Grundvoraussetzung dafür, dass man auf das scroll-Event angemessen (lies: ohne Nutzer mit schwachen Geräten eine schlechte UX zu bieten) reagieren kann.
indem man eine fixe Boolean-Variable
window.hasScrolled
verwendet statt des classList.contains-Aufruf, aber ich denke das ist performancetechnisch verschmerzbar.Unter diesem Umstand kann man den Code hier vielleicht so verwenden, ohne große Performance-Bauchschmerzen zu bekommen.
Von einer globalen Variable
window.hasScrolled
würde ich nun wieder abraten.
Deshalb hab ich das auch nur erwähnt, nicht umgesetzt 😉
Die sollte schön geschützt werden! Wer weiß, was sonst noch alles in die Seite kommen soll. "Immer brav kapseln" habe ich im SelfHTML-Forum gelernt. Aber da warst Du vermutlich noch nicht dabei ;-)
Nein - aber die Lektion hatte ich trotzdem „damals schon“ gelernt. Die Kapselung ändert aber an der Funktionsweise nicht Elementar viel.
Abgesehen davon: Auch einfache Kapselung (window.myVars.hasScrolled
) ist kein Persilschein. Ich halte aber die Benennung window.hasScrolled
für ausreichend sicher - man kann wohl davon ausgehen, dass ein Skript, das zufällig eine gleich benannte Variable verwendet durch die Semantik der Variablenbenennung mit hoher Wahrscheinlichkeit genau das selbe mit dieser Variable tut.
Das ist jetzt was anderes als würde ich window.i
oder window.temp
oder window.elm
verwenden wollen.
Aber unterm Strich hast du natürlich Recht: Nichts davon bietet absolute Sicherheit.
Und die Sache mit den Closures hat Christian ja neulich nochmal ausführlich erklärt.
Richtig. Man hätte hier auch darauf verzichten können, die Funktion als window.checkScroll
zu definieren.
Mir ging es hier vor allem darum, Lukas die Funktionsweise zu erklären. Da hab ich die Bedenken mit Kapselung für die Verständlichkeit über Bord geworfen.
Falls du Closures (genauer: IIFE) verwenden willst hier ein Vorschlag, der alle Aspekte mit einbezieht:
(function () {
var hasScrolled = false;
var checkScroll = function() {
if(window.pageYOffset > 0) {
if (hasScrolled) {
return true;
} else {
hasScrolled = true;
document.body.classList.add("fixed-header-on");
}
} else if (hasScrolled) {
hasScrolled = false;
document.body.classList.remove("fixed-header-on");
}
}
window.addEventListener("scroll",checkScroll);
window.addEventListener("load",checkScroll); // Falls mit Anker gesprungen wurde!
})();
Grüße,
RIDER
@@Camping_RIDER
if(window.pageYOffset > 0 && !document.body.classList.contains("fixed-header-on")) { document.body.classList.add("fixed-header-on"); } else if (window.pageYOffset == 0 && document.body.classList.contains("fixed-header-on")) { document.body.classList.remove("fixed-header-on"); }
Die Abfragen document.body.classList.contains("fixed-header-on")
sind überhaupt nicht nötig, da in add()
bzw. remove()
bereits enthalten.
Die transition-Angaben mit vendor-prefixes tun dasselbe und werden in aktuellen Browsern sowieso durch die Zeile ohne vendor-prefix überschrieben.
Die transition-Angaben mit vendor-prefixes sind größtenteils unsinnig. -ms-transition
hat es nie gegeben, -moz-transition
und -o-transition
sind seit Ewigkeiten völlig irrelevant.
Lediglich -webkit-transition
mag für alte Android-Browser und den UC-Browser noch Berechtigung haben (je nach Zielgruppe).
LLAP 🖖
Hello @Gunnar,
jetzt finde ich deine Anmerkung zwar nicht mehr, dass man mit JS nicht direkt auf die Style-Eigenschaften zugreifen soll, sondern dies dem CSS überlassen soll, aber ich werfe jetzt hier nochmal einen Lösungsversuch rein:
siehe shrinking_header
Ist es so besser?
Vermutlich kann man die Klassen noch besser zusammenfassen? Aber das übersteigt meine Praxiserfahrung.
Irgendetwas muss man ja aber umschalten, also hoffe ich, die Klasse zu wechseln, ist erlaubt ;-)
Interessant ist auf jeden Fall, dass man dann mit JS nur noch eine einzige Klasse umschalten muss und alle anderen (davon abhängigen) automatisch mitziehen. So kann man wirklich am CSS alleine das voraussichtliche Designverhalten ablesen.
Liebe Grüße
Tom S.
Hallo TS,
jetzt finde ich deine Anmerkung zwar nicht mehr, dass man mit JS nicht direkt auf die Style-Eigenschaften zugreifen soll, sondern dies dem CSS überlassen soll,
Diese Anmerkung gab es schon oft hier.
Vermutlich kann man die Klassen noch besser zusammenfassen? Aber das übersteigt meine Praxiserfahrung.
Man kann auf eine verzichten.
Irgendetwas muss man ja aber umschalten, also hoffe ich, die Klasse zu wechseln, ist erlaubt ;-)
Natürlich.
Das ganze sollte noch in eine MQ gepackt werden. Auf Handys möchte man zudem darauf verzichten, das Scrollevent abzufragen, sonst hat man sich ganz schnell eine Taschenwärmer-App geschrieben.
Bis demnächst
Matthias
Aloha ;)
if(window.pageYOffset > 0 && !document.body.classList.contains("fixed-header-on")) { document.body.classList.add("fixed-header-on"); } else if (window.pageYOffset == 0 && document.body.classList.contains("fixed-header-on")) { document.body.classList.remove("fixed-header-on"); }
Die Abfragen
document.body.classList.contains("fixed-header-on")
sind überhaupt nicht nötig, da inadd()
bzw.remove()
bereits enthalten.
Danke für die Anmerkung, war mir so nicht bewusst. Demnach dann einfach:
if(window.pageYOffset > 0) {
document.body.classList.add("fixed-header-on");
} else if (window.pageYOffset == 0) {
document.body.classList.remove("fixed-header-on");
}
?
Grüße,
RIDER