Linuchs: CSS sticky-Eigenschaft, wenn es stickt.

Moin,

ich muss zahlreiche Html-Dokumente zeitgleich bearbeiten. Dafür definiere ich h1 mit sticky, damit die Überschrift immer zu sehen ist.

Nun kommt es vor, dass beim Scrollen ein <br> direkt unter dem <h1> steht und es sieht so aus, als wäre die folgende Zeile die erste des Dokuments.

Gerne möchte ich <h1> eine andere Hintergrundfarbe geben, wenn es stickt.

Wie geht das?

  1. @@Linuchs

    Nun kommt es vor, dass beim Scrollen ein <br> direkt unter dem <h1> steht

    Häh?

    Wie geht das?

    Bist du nicht schon lange genug hier um zu wissen, wie das geht, sein Problem verständlich zu beschreiben?

    😷 LLAP

    --
    “When I was 5 years old, my mother always told me that happiness was the key to life. When I went to school, they asked me what I wanted to be when I grew up. I wrote down ‘happy.’ They told me I didn’t understand the assignment, and I told them they didn’t understand life.” —John Lennon
    1. Bist du nicht schon lange genug hier um zu wissen, wie das geht, sein Problem verständlich zu beschreiben?

      Ich dachte, das wäre verständlich. Normal ist Überschrift - Leerzeile - erster Satz.

      Nach dem Scrollen Überschrift (sticky) - Leerzeile - n-ter Satz.

      Ich möchte sehen, ob ich am Anfang des Dokuments stehe oder bereits gescrollt wurde.

  2. Hallo Linuchs,

    Gerne möchte ich <h1> eine andere Hintergrundfarbe geben, wenn es stickt.

    Mit der intersection observer API.

    https://dev.to/bhupendra1011/how-to-know-when-css-position-sticky-get-s-applied-4gk2

    Bis demnächst
    Matthias

    --
    Du kannst das Projekt SELFHTML unterstützen,
    indem du bei Amazon-Einkäufen Amazon smile (Was ist das?) nutzt.
    1. Hallo Matthias,

      das ist genau die gewünschte Lösung, aber extrem kompliziert umgesetzt. Vielleicht kommt ja noch ein einfacherer Vorschlag.

      Linuchs

      1. Hallo Linuchs,

        das ist genau die gewünschte Lösung, aber extrem kompliziert umgesetzt. Vielleicht kommt ja noch ein einfacherer Vorschlag.

        Es gab da was in jQuery:

        if($(window).scrollTop() >= ($(document).height()
        

        Wenn das mit Vanilla nutzen will, könnte dieser Artikel vielleicht auf die Spur führen.

        Good Luck
        Localhorst

  3. Hallo Linuchs,

    das Thema ist schon alt

    Aber :stuck (oder :sticking) gibt es immer noch nicht. Und wenn es nach dem Willen der WICG geht (wo die Großen der Branche neue Standards ausbrüten), dann wird es das auch nicht geben. Weil man in einer Regel mit h1:stuck Selektor ja auch position:static setzen könnte, und das führt zu einer Endlosschleife die man nicht beherrschen kann. Diskussion - wenn ihr das nicht einseht, streitet mit tabatkins, nicht mit mir...

    Ich habe auch noch einen Artikel von Eric Bidelman (Google) gefunden - aber nicht gründlich studiert - der ein Custom Event generiert wenn ein Element sticky wird. Trivial scheint auch das nicht zu sein - klingt nach einer Aufgabe für eine .js Library, die man schreiben müsste.

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Hallo,

      das Thema ist schon alt

      Aber :stuck (oder :sticking) gibt es immer noch nicht.

      so war auch mein Kenntnisstand. Aber das muss ja nichts heißen, und deswegen habe ich den Thread auch aufmerksam beobachtet - ich hatte auch gehofft, es gäbe da vielleicht einen Ansatz mit einer Pseudoklasse, die ich bisher nicht kenne.

      Live long and pros healthy,
       Martin

      --
      Für welches Tier mühen wir uns am meisten ab? - Für die Katz'.
    2. Hi,

      Aber :stuck (oder :sticking) gibt es immer noch nicht. Und wenn es nach dem Willen der WICG geht (wo die Großen der Branche neue Standards ausbrüten), dann wird es das auch nicht geben. Weil man in einer Regel mit h1:stuck Selektor ja auch position:static setzen könnte, und das führt zu einer Endlosschleife die man nicht beherrschen kann.

      Naja, dann dürfte es z.B. :hover auch nicht geben - da könnte man ja z.B. width:0 setzen, womit der hover-Status weg wäre, was dazu führt, daß die ursprüngliche width gilt, womit der Mauszeiger wieder über dem Element ist, was dann per :hover wieder zu width:0 führt, womit ...

      cu,
      Andreas a/k/a MudGuard

      1. Hallo MudGuard,

        genau auch meine Überlegung, wurde auch so im Thread benannt, aber angeblich sei eine :hover basierende Loop "wide", weshalb es da nur flackert, und eine potenzielle Sticky-basierende Loop sei "tight" und würde damit den Browser lahmlegen.

        Guck in die verlinkte Diskussion und versuch Dir einen Reim drauf zu machen. Ich nehme an, dass Tabatkins weiß, wovon er redet, und letztlich liest es sich so wie "wir haben das nun mal so designed, dass eine :stuck Pseudoklasse uns ins Knie schießen könnte, und damit ist es so. Tricks dich drumherum, oder mach's mit JavaScript"

        Eine vom Browser gelieferte Methode, um bei bestimmten CSS Übergängen automatisch ein Event abzuschießen, das wäre sicherlich eine prima Idee. Aber auch das ist wohl erst im Proposal-Stadium und man muss sich mit Observern behelfen. Naja, zumindest verstehe ich das jetzt so. Aber ich hab ja keine Ahnung 😉

        Rolf

        --
        sumpsi - posui - obstruxi
  4. Ich muss nach einem Scrollvorgang feststellen, ob h1 am oberen Rand des Fensters klebt. Habe ein knappes dutzend Webseiten mit Geschwurbel und Diskussionen durchgesehen, aber keine Lösung gefunden.

    Überlegung:

    Wenn ich sticky mit top:0 definiere und der Abstand window.scrollY genauso groß ist wie h1.offsetTop klebt h1 am oberen Rand:

    var h1  = document.getElementsByTagName( "h1" )[0];
    document.addEventListener('scroll', function() {
      if ( window.scrollY == h1.offsetTop ) {
        h1.classList.add( "pos_markiert" );     // Markierung setzen
      } else {
        h1.classList.remove( "pos_markiert" );  // Markierung entfernen
      }
    });
    

    funktioniert bestens.

    Allerdings feuert das scroll-Event mehrmals pro Scrollvorgang, wie könnte ich das noch optimieren?

    Linuchs

    1. Hallo Linuchs,

      Allerdings feuert das scroll-Event mehrmals pro Scrollvorgang, wie könnte ich das noch optimieren?

      https://wiki.selfhtml.org/wiki/JavaScript/Tutorials/Debounce_und_Throttle

      Gruß
      Jürgen

      1. Hallo Jürgen,

        danke für den verlinkten Tipp mit timeout. Bei jedem gefeuerten Scroll-Event verschiebe ich das Setzen/Zurücknehmen der Markierung um 1 sec. Kann man kürzer machen, ich wollte den Effekt deutlich sehen.

        So sieht jetzt meine Lösung aus:

        window.addEventListener('DOMContentLoaded', function ( ) {
          var h1          = document.getElementsByTagName( "h1" )[0];
          var toggleTime  = null;
          function toggle_h1() {
            console.log( "[" +window.scrollY +"] [" +h1.offsetTop +"]" ); // Test wg. Timeout
            if ( window.scrollY == h1.offsetTop ) {
              h1.classList.add( "pos_markiert" );     // Farbe setzen
            } else {
              h1.classList.remove( "pos_markiert" );  // Farbe entfernen
            }
          }
          document.addEventListener('scroll', function() {
            toggleTime  = setTimeout( toggle_h1, 1000 );
          });
        });
        

        Linuchs

        1. Hallo Linuchs,

          Infos und Beispiele zu Debounce und Throttle im Self Wiki

          Rolf

          --
          sumpsi - posui - obstruxi
          1. Hallo Rolf,

            Infos und Beispiele zu Debounce und Throttle im Self Wiki

            genau

            Gruß
            Jürgen

            1. Hallo JürgenB,

              ich hab's nochmal verlinkt weil er es beim ersten Aufruf nicht genau gelesen zu haben scheint (oder gar nicht). Ein Debouncer ohne clearTimeout macht mutmaßlich was falsch.

              Rolf

              --
              sumpsi - posui - obstruxi
        2. Hallo Linuchs,

          danke für den verlinkten Tipp mit timeout. Bei jedem gefeuerten Scroll-Event verschiebe ich das Setzen/Zurücknehmen der Markierung um 1 sec.

          du hast das Reagieren auf die vielen Scroll-Events nur um eine Sekunde verschoben, aber es wird genauso oft regiert. Der Trick ist, die Reaktion im 1s-Takt laufen zu lassen. Dazu musst du die Timeouts erst starten, wenn der vorherigen gelaufen ist.

          Gruß
          Jürgen

          1. Hallo Jürgen,

            du hast das Reagieren auf die vielen Scroll-Events nur um eine Sekunde verschoben, aber es wird genauso oft regiert.

            Du meinst, das Überschreiben von toggleTime = setTimeout( toggle_h1, 1000 ); löscht NICHT den alten Auftrag, den toggleTime hatte?

            Also muss es so aussehen?

            clearTimeout(toggleTime);
            toggleTime  = setTimeout( toggle_h1, 1000 );
            

            Linuchs

            1. Hi Linuchs,

              Du meinst, das Überschreiben von toggleTime = setTimeout( toggle_h1, 1000 ); löscht NICHT den alten Auftrag, den toggleTime hatte?

              korrekt, der Auftrag bleibt bestehen. Dass du die alte Quittung wegwirfst, ändert daran nichts.

              Also muss es so aussehen?

              clearTimeout(toggleTime);
              toggleTime  = setTimeout( toggle_h1, 1000 );
              

              Schon besser.

              Live long and pros healthy,
               Martin

              --
              Für welches Tier mühen wir uns am meisten ab? - Für die Katz'.
            2. Ja stimmt, die Kontrollanzeigen in function toggle_h1 laufen nach 1 sec los, auch wenn das Scrollen noch andauert.

              Irgendwie seltsam, dass sich die Variable toggleTime viele Aufträge merken kann. Ist das ein Array?

              Und auf welchen der Aufträge mit gleichem Namen bezieht sich dann clearTimeout(toggleTime);

              1. Hallo,

                Irgendwie seltsam, dass sich die Variable toggleTime viele Aufträge merken kann. Ist das ein Array?

                nein.

                Und auf welchen der Aufträge mit gleichem Namen bezieht sich dann clearTimeout(toggleTime);

                Nur auf den letzten. Auf die anderen kannst du nicht mehr einwirken, weil du das Handle überschrieben hast.

                Live long and pros healthy,
                 Martin

                --
                Für welches Tier mühen wir uns am meisten ab? - Für die Katz'.
    2. Hallo Linuchs,

      Allerdings feuert das scroll-Event mehrmals pro Scrollvorgang, wie könnte ich das noch optimieren?

      Was hat dir an meinem Vorschlag nicht gefallen?

      Bis demnächst
      Matthias

      --
      Du kannst das Projekt SELFHTML unterstützen,
      indem du bei Amazon-Einkäufen Amazon smile (Was ist das?) nutzt.
      1. Was hat dir an meinem Vorschlag nicht gefallen?

        Es sind soo viele Code-Zeilen (erst jetzt im eigenen Editor sehe ich, dass es viele Zeilenumbrüche gibt). Und ehrlich - ich habe es nicht verstanden.

        • IntersectionObserver
        • intersectionRatio
    3. Hi Linuchs,

      Ich muss nach einem Scrollvorgang feststellen, ob h1 am oberen Rand des Fensters klebt. Habe ein knappes dutzend Webseiten mit Geschwurbel und Diskussionen durchgesehen, aber keine Lösung gefunden.

      Überlegung:

      Wenn ich sticky mit top:0 definiere und der Abstand window.scrollY genauso groß ist wie h1.offsetTop klebt h1 am oberen Rand:

      var h1  = document.getElementsByTagName( "h1" )[0];
      document.addEventListener('scroll', function() {
        if ( window.scrollY == h1.offsetTop ) {
          h1.classList.add( "pos_markiert" );     // Markierung setzen
        } else {
          h1.classList.remove( "pos_markiert" );  // Markierung entfernen
        }
      });
      

      funktioniert bestens.

      Fein.

      Könntest Du einen Link auf eine öffentliche Webseite preisgeben, auf der Du das eingebaut hast? Oder ist das geheim/nur lokal?

      Gesundheit!
      Localhorst

      1. Moin,

        Könntest Du einen Link auf eine öffentliche Webseite preisgeben, auf der Du das eingebaut hast? Oder ist das geheim/nur lokal?

        Bei <h1> geht's um ein lokales Buchprojekt.

        Aber hier habe ich es für den <header> eingebaut. Das Script findest du ziemlich unten im Code.

        Suche nach DOMContentLoaded

        Linuchs

  5. @@Linuchs

    Nun kommt es vor, dass beim Scrollen ein <br> direkt unter dem <h1> steht und es sieht so aus, als wäre die folgende Zeile die erste des Dokuments.

    Alternative ohne JavaScript.

    Siehe Lea Verous Artikel Pure CSS scrolling shadows with background-attachment: local von 2012.

    Darin steht geschrieben, dass damals auch Safari Schatten anzeigte. Vielleicht findet ja jemand raus, warum der aktuelle das nicht mehr tut.

    😷 LLAP

    --
    “When I was 5 years old, my mother always told me that happiness was the key to life. When I went to school, they asked me what I wanted to be when I grew up. I wrote down ‘happy.’ They told me I didn’t understand the assignment, and I told them they didn’t understand life.” —John Lennon
    1. Hallo Gunnar,

      deine Verlinkung springt bei sticky um und zeigt einen Schatten. Sieht sehr gut aus, habe ich übernommen.

      Bin mit meiner JS-Lösung zufrieden, aber behalte die CSS-Lösung mal im Auge.

      Linuchs

      1. @@Linuchss

        deine Verlinkung springt bei sticky um

        Da springt nichts um und sticky ist da auch nicht im Spiel.

        habe ich übernommen.

        Du solltest versuchen, wenigstens ansatzweise zu verstehen, was du übernimmst.

        😷 LLAP

        --
        “When I was 5 years old, my mother always told me that happiness was the key to life. When I went to school, they asked me what I wanted to be when I grew up. I wrote down ‘happy.’ They told me I didn’t understand the assignment, and I told them they didn’t understand life.” —John Lennon