Linuchs: Tabellen-Kopfzeile fixieren und kopieren

Moin,

ich beiße mir gerade die Zähne daran aus, eine fixierte Kopie einer Tabellen-Zeile pixelgerecht oben auf der Seite zu fixieren, damit die Überschrift beim Scrollen stehen bleibt.

<table class=liste style="position:fixed; left:0; top:0"><!-- TEST -->
  <thead>
    <tr id="tr_kopie"></tr>
  </thead>
</table>

Bildbeschreibung

Die left:0 klebt direkt am Bildschirm-Rand, obwohl

body {
  position: relative;
  padding: 0;
  margin: 5px;
  background: #cfc;
}

Zur Kontrolle habe ich background eingefügt. Und siehe da: body hat nicht den erwarteten Rand von 5px.

Nach fast 20 Jahren HTML muss ich nun fragen: Was ist eigentlich body? Oder habe ich was übersehen?

Beim Kopieren der Spalten-Breite stimmen die Pixel auch nicht überein, aber dazu später mehr. Ein Schritt nach dem anderen.

Linuchs

  1. Hallo,

    ich beiße mir gerade die Zähne daran aus, eine fixierte Kopie einer Tabellen-Zeile pixelgerecht oben auf der Seite zu fixieren, damit die Überschrift beim Scrollen stehen bleibt.

    damit haben sich schon andere abgemüht ...

    <table class=liste style="position:fixed; left:0; top:0"><!-- TEST -->
      <thead>
        <tr id="tr_kopie"></tr>
      </thead>
    </table>
    

    Bildbeschreibung

    Die left:0 klebt direkt am Bildschirm-Rand, obwohl

    body {
      position: relative;
      padding: 0;
      margin: 5px;
      background: #cfc;
    }
    

    Natürlich. Sobald position:fixed gesetzt ist, beziehen sich die Koordinaten nicht mehr auf irgendwelche Vorfahrenelemente, sondern direkt auf das Browserfenster. Ein margin und/oder padding für body ist da wirkungslos. Die Angabe position:relative für body auch.

    Zur Kontrolle habe ich background eingefügt. Und siehe da: body hat nicht den erwarteten Rand von 5px.

    Öhm ...

    Nach fast 20 Jahren HTML muss ich nun fragen: Was ist eigentlich body?

    Das Containerelement, das den gesamten darzustellenden Inhalt der Webseite umfasst. (Ja, man kann auch head oder eines seiner Kindelemente darstellen, aber das ist ziemlich ungewöhnlich.)

    So long,
     Martin

    --
    Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.
    - Douglas Adams, The Hitchhiker's Guide To The Galaxy
    1. Hallo Der Martin,

      Bemühe mal bitte die Forumssuche. Da gibt es einige Lösungsansätze.

      Bis demnächst
      Matthias

      --
      Dieses Forum nutzt Markdown. Im Wiki erhalten Sie Hilfe bei der Formatierung Ihrer Beiträge.
      1. Hi,

        Bemühe mal bitte die Forumssuche. Da gibt es einige Lösungsansätze.

        warum ich??

        Ciao,
         Martin

        --
        Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.
        - Douglas Adams, The Hitchhiker's Guide To The Galaxy
        1. Hej Der Martin,

          Bemühe mal bitte die Forumssuche. Da gibt es einige Lösungsansätze.

          warum ich??

          Damit du Linuchs helfen kannst ;-)

          Marc

    2. Hallo,

      ich beiße mir gerade die Zähne daran aus, eine fixierte Kopie einer Tabellen-Zeile pixelgerecht oben auf der Seite zu fixieren, damit die Überschrift beim Scrollen stehen bleibt.

      damit haben sich schon andere abgemüht ...

      ich finde die Lösung von Jürgen B ganz gelungen.

      Fred

      --
      Tag ein, Tag aus, Webseiten-Entwickler beklagt monotone Arbeit.
      1. Hallo Fred,

        ich finde die Lösung von Jürgen B ganz gelungen.

        Nunja, mit festen Spaltenbreiten ...

        div.scrollcontainer div table thead th { width:100px; }  
        div.scrollcontainer div table tbody td { width:100px; }
        

        Ich versuche, nachdem die Original-Tabelle aufgebaut wurde, die Breiten auf die fixierte Tabelle zu übertragen:

        window.addEventListener('DOMContentLoaded', function ( ) {
          alert( "[" +document.getElementById( "tr_original" ).getElementsByTagName( "td" )[0].style.paddingLeft +"]" );
          // alle Zellen der Zeile kopieren
          document.getElementById( "tr_kopie" ).innerHTML = document.getElementById( "tr_original" ).innerHTML;
          // alle Zellenbreiten kopieren
          for ( i=0; i<document.getElementById( "tr_original" ).getElementsByTagName( "td" ).length; i++ ) {
            document.getElementById( "tr_kopie" ).getElementsByTagName( "td" )[i].style.width
            = ( document.getElementById( "tr_original" ).getElementsByTagName( "td" )[i].clientWidth -10 ) +"px";
          }
        });
        

        Dabei ergibt sich das Problem, dass die Original-Breite nicht 1:1 kopiert werden kann, denn clientWidth enthält Daten und padding, ist aber nur-lesbar. style.width ist wiederum beim Original nicht greifbar. Bildbeschreibung

        Da ich im Original 5px padding habe, ziehe ich 10px ab. Aber dieser Wert müsste von der betreffenden Zelle gelesen werden und nicht im javascript-Programm "festgezurrt". Die Frage nach style.paddingLeft ergibt NULL.

        Linuchs

        1. Hi,

          Dabei ergibt sich das Problem, dass die Original-Breite nicht 1:1 kopiert werden kann, denn clientWidth enthält Daten und padding, ist aber nur-lesbar. style.width ist wiederum beim Original nicht greifbar.

          hast du es mal mit getComputedStyle() versucht? Das scheint mir für den Zweck prädestiniert.

          So long,
           Martin

          --
          Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.
          - Douglas Adams, The Hitchhiker's Guide To The Galaxy
          1. Hallo Martin,

            danke für den Tipp. So funktioniert's beim FF und der Opera:

            window.addEventListener('DOMContentLoaded', function ( ) {
              // alle Zellen der Zeile kopieren
              document.getElementById( "tr_kopie" ).innerHTML = document.getElementById( "tr_original" ).innerHTML;
              // alle Zellenbreiten kopieren
              original  = document.getElementById( "tr_original" ).getElementsByTagName( "td" );
              kopie     = document.getElementById( "tr_kopie" ).getElementsByTagName( "td" );
              for ( i=0; i<original.length; i++ ) {
                var theCSSprop = window.getComputedStyle(original[i],null).getPropertyValue("width");
                kopie[i].style.width = theCSSprop;
              }
              // Tabelle links ausrichten
              theCSSprop = window.getComputedStyle(document.getElementsByTagName( "body" )[0],null).getPropertyValue("marginLeft");
              document.getElementsByTagName( "table" )[0].style.left = theCSSprop;
            });
            

            Linuchs

            1. ich stelle eben fest, dass bei resize zwar die Original-Tabelle neu gestaltet wird, aber nicht die Kopie und habe diese verbesserte Version versucht:

              window.addEventListener('DOMContentLoaded', function() {
                copyThead();
                window.addEventListener("resize", copyThead() );
              });
              

              Klappt nicht, vermutlich wird das Original kopiert bevor es auf die neue Window-Breite umgestellt wurde. Irgendwie wäre das noch zu kombinieren mit "nachdem Seite neu formatiert".

              Wie heisst das auf javanocryptisch?

              Linuchs

              1. sehe gerade, dass der "resize" nur einmal feuert nach Aufruf der Seite. Bei Veränderung der der Window-Größe aber nicht. Wieso?

                function copyTheadSpaeter() {
                  alert ( "copyTheadSpaeter" ); // wird nur einmal angezeigt
                  setTimeout( copyThead(), 3000 );
                }
                window.addEventListener('DOMContentLoaded', function() {
                ...
                  copyThead();
                  window.addEventListener("resize", copyTheadSpaeter() );
                ...
                

                Linuchs

                1. Hallo,

                  sehe gerade, dass der "resize" nur einmal feuert nach Aufruf der Seite. Bei Veränderung der der Window-Größe aber nicht. Wieso?

                    window.addEventListener("resize", copyTheadSpaeter() );
                  

                  weil du als EventListener das Ergebnis deiner Funktion THeadSpaeter zuweist (also undefined, weil die Funktion kein Ergebnis liefert), anstatt einer Referenz auf die Funktion selbst.

                  So long,
                   Martin

                  --
                  Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.
                  - Douglas Adams, The Hitchhiker's Guide To The Galaxy
                  1. Hoppla,

                    weil du als EventListener das Ergebnis deiner Funktion THeadSpaeter zuweist (also undefined, weil die Funktion kein Ergebnis liefert), anstatt einer Referenz auf die Funktion selbst.

                    Ahh, jetzt ja. Die Klammern sind zu viel. Hatte ich übernommen von

                    window.addEventListener('DOMContentLoaded', function() {...})
                    

                    gehören die da auch weg? Das wurde mir so empfohlen.

                    So, nun wandert bei geschmaltem Fenster das Original nach rechts aus, die Kopie quetscht sich aber. Damit passt die Überschrift nicht zu den Spalten. Muss ich wohl mit minWith erzwingen ... Schaun mer mal.

                    Linuchs

                    1. Ist verdammt teuflisch, diese Aufgabe.

                      Nach weglassen der Klammer brauche ich keine Verzögerung mehr. Also scheint das "resize" Event erst den Neuaufbau der Seite abzuwarten, bevor es feuert.

                      Sieht gut aus, bis ... man den horizontalen Scrollbalken betätigt. Die "fixe" Zeile scrollt natürlich nicht mit. Kann man das "fixen" auf das Y-Scroll begrenzen?

                      window.addEventListener('DOMContentLoaded', function() {
                      ...
                        copyThead();
                        window.addEventListener("resize", copyThead );
                      });
                      
                      

                      Da muss ich wohl noch einen EventListener für den X-Scroll suchen ...

                      Linuchs

                      1. Hallo Linuchs,

                        Sieht gut aus, bis ... man den horizontalen Scrollbalken betätigt. Die "fixe" Zeile scrollt natürlich nicht mit. Kann man das "fixen" auf das Y-Scroll begrenzen?

                        https://forum.selfhtml.org/m1451537

                        Bis demnächst
                        Matthias

                        --
                        Dieses Forum nutzt Markdown. Im Wiki erhalten Sie Hilfe bei der Formatierung Ihrer Beiträge.
      2. @@Fred

        ich finde die Lösung von Jürgen B ganz gelungen.

        Die geht von einer festen Höhe des Tabellenkopfes aus. Was, wenn eine Spaltenüberschrift mehrzeilig ist?

        Ein weiteres Problem ist der Scrollbalken, der über die ganze Tabellenhöhe einschließlich des Kopfes geht anstatt – wie es sein sollte – nur über den scrollbaren Bereich.

        Mal in meiner Bastelkiste gekramt:

        LLAP 🖖

        --
        “You might believe there are benefits for the developer, but first of all, you should put those behind the interest of the user.” —Stefan Tilkov
        Selfcode: sh:) fo:} ch:? rl:) br:> n4:& va:| de:> zu:} fl:{ ss:| ls:# js:|
        1. Tach!

          Die geht von einer festen Höhe des Tabellenkopfes aus. Was, wenn eine Spaltenüberschrift mehrzeilig ist?

          Ich hätte da gern mal ein ähnliches Problem. Da soll allerdings die erste Spalte fixiert werden und die restlichen Spalten horizontal gescrollt werden. Auch da ist es so, dass die Information in der Spalte mehrzeilig werden kann. Ich hatte schon mal nach einer Lösung gesucht, die scheiterte jedoch bei ebendieser Mehrzeiligkeit.

          Mal in meiner Bastelkiste gekramt:

          Die hab ich mir eben nur mal ganz kurz angeschaut und noch nicht näher analysiert. Aber hast du in deiner Bastelkiste auch was für meinen Bedarf? Oder wenn sich die drei (oder eine davon) auch einfach an Spalten anpassen lassen, dann reicht mir auch diese Bestätigung und ich such mir die Lösung selbst, wenn ich wieder Muße hab.

          dedlfix.

          1. Hallo,

            wir setzen im Büro das Kendo UI Grid von Telerik ein. Ist Payware. Sie haben allerdings die verlinkte Online-Doku und für viele Anwendungsfälle ein Dojo (=Frikkelstube) - da kann man sich eventuell Dinge abschauen :)

            Gruß Rolf

            1. Tach!

              wir setzen im Büro das Kendo UI Grid von Telerik ein. Ist Payware. Sie haben allerdings die verlinkte Online-Doku und für viele Anwendungsfälle ein Dojo (=Frikkelstube) - da kann man sich eventuell Dinge abschauen :)

              Telerik-Komponenten habe ich auch schon für einige Projekte einsetzen können. Aber in dem Fall geht das nicht, weil es sich beim Problemkind um eine nicht von mir betriebene Mediawiki-Installation handelt. Abschauen ist so eine Sache. Die tricksen da rum, indem sie zwei Tabellen nebeneinander setzen und die Höhe der Zellen vermutlich mit Javascript anpassen. Der Inspektor zeigt da elementindividuelle heigth-Styles an.

              Es sollte schon mit einer Tabelle auskommen, weil das das ist, was das Mediawiki erzeugt, wenn man dessen Tabellensyntax verwendet. Umsteigen aus individuelle Templates fällt aus, da wird die Syntax ätzend umständlich, beispielsweise von | für einen Zellentrenner zu {{irgendwas}}. Das kann man zwar einmalig mit Suchen une Ersetzen umschreiben, aber die Tabelle muss auch wartbar bleiben. Javascript als Notlösung lässt sich sicher verwenden, aber wenn es sich vermeiden lässt ... Das Installieren neuer Extensions wird jedenfalls nicht möglich sein.

              dedlfix.