Jan^3: CSS: Tabelle mit 2 und mehr Kopfzeilen formatieren

Moin,

ich darf viele HTML-Seiten, welche von WikidPad erzeugt wurden formatieren.

In den html-Seiten gibt es viele Tabellen. Teilweise haben die Tabellen ein, sehr viele aber auch zwei und drei Kopfzeilen. Das Problem ist, dass das Programm WikidPad keine html konformen Tabellenkopf mit <th> erstellt. Vielmehr besteht die Tabellen nur Datenzellen mit <td>.

Die Formatierung mit einer Kopfzeile habe ich mit der Pseudoklasse :first-child umgesetzt. Das funktioniert auch ganz gut. Bei mehr als einer Kopfzeile scheitere ich. Weist die Tabelle mehr als eine Kopfzeile auf, kommen im Tabellenkopf (bzw. der ersten Zeile der Tabelle) immer mindestens eine zusammengesetzte Zelle vor. Trotz langer suche und vielen Versuchen ist es mir bisher nicht gelungen diese Kopfzeilen zu filtern und mit css anzusprechen.

Hier eine Beispieltabelle. Der Übersichtlichkeit halber habe bei jedem Tag nur das class="wikidpad" gelöscht.

<table border="2">  
  <tr>  
    <td rowspan="2">Schlüssel</td>  
    <td rowspan="2">Bezeichnung</td>  
    <td colspan="2">Datentyp</td>  
    <td rowspan="2">Beschreibung</td>  
    <td rowspan="2">Referenzliste Werte</td>  
  </tr>  
  <tr>  
    <td>Typ</td>  
    <td>Größe</td>  
  </tr>  
  <tr>  
    <td>Zelle 1.1</td>  
    <td>Zelle 1.2</td>  
    <td>Zelle 1.3</td>  
    <td>Zelle 1.4</td>  
    <td>Zelle 1.5</td>  
    <td>Zelle 1.6</td>  
  </tr>  
  <tr>  
    <td>Zelle 2.1</td>  
    <td>Zelle 2.2</td>  
    <td>Zelle 2.3</td>  
    <td>Zelle 2.4</td>  
    <td>Zelle 2.5</td>  
    <td>Zelle 2.6</td>  
  </tr>  
</table>  

Habt ihr einen Tipp für mich?

Im Voraus schon einmal vielen Dank für alle sachdienlichen Hinweise

Jan

  1. Hallo,

    hast du schon mal nth-child ausprobiert?

    Gruß
    Jürgen

    1. probiert habe ich es noch nicht, aber nth-child sollte genau so wie :first-child funktionieren.

      Das Problem ist, wie kann ich erkennen ob der Kopf aus einer, zwei oder drei Zeilen besteht.

      Jan

      1. Hallo

        probiert habe ich es noch nicht, aber nth-child sollte genau so wie :first-child funktionieren.

        Das Problem ist, wie kann ich erkennen ob der Kopf aus einer, zwei oder drei Zeilen besteht.

        Mit dem dir vorgegebenen HTML-Code überhaupt nicht. Das sind irgendwelche Tabellenzeilen, -spalten und -zellen. Da ist nichts, was diese Konstruktion als Tabellenkopf erkennbar macht. Aber selbst wenn dumit irgendwelichen Handständen aus der konkreten Konstruktion einen CSS-Selektor ableiten könntest — was meines Wissens nach nicht geht — könnte sich theoretisch eine solche oder zumindest vergleichbare Struktur auch mitten in der Tabelle befinden. Dann würde das Layout deiner Tabelle platzen.

        Bleibt also nur, das DOM umzubauen und den Tabellenkopf kenntlich zu machen. Wenn du das nicht auf der Erzeugerseite machen kannst, bleibt dir nur die in einem der anderen Zweige diskutierte JS-Lösung.

        Tschö, Auge

        --
        Wenn man ausreichende Vorsichtsmaßnahmen trifft, muss man keine Vorsichtsmaßnahmen mehr treffen.
        Toller Dampf voraus von Terry Pratchett
  2. Du willst das zweite tr Element treffen, ja? Dafür würdest Du meiner Meinung nach einen Selektor wie

    tr:has(td[colspan])+tr
    

    brauchen, den es aber nicht gibt. :has ist aus Performance-Gründen nicht im Standard.

    Rolf

    1. genau auf so etwas habe ich gehofft!

      So langsam schwinden meine Hoffnungen auf eine Lösung mit css und ohne JavaScript. 😟

      Trotzdem vielen Dank

      Jan

  3. @@Jan^3

    <table border="2">  
      <tr>  
        <td rowspan="2">Schlüssel</td>  
        <td rowspan="2">Bezeichnung</td>  
        <td colspan="2">Datentyp</td>  
        <td rowspan="2">Beschreibung</td>  
        <td rowspan="2">Referenzliste Werte</td>  
      </tr>  
      <tr>  
        <td>Typ</td>  
        <td>Größe</td>  
      </tr>  
      <tr>  
        <td>Zelle 1.1</td></tr>  
    </table>  
    

    Habt ihr einen Tipp für mich?

    Aus Scheiße Gold machen. Das DOM per JavaScript umwandeln zu

    <table>
      <thead> 
        <tr>  
          <th rowspan="2">Schlüssel</th>  
          <th rowspan="2">Bezeichnung</th>  
          <th colspan="2">Datentyp</th>  
          <th rowspan="2">Beschreibung</th>  
          <th rowspan="2">Referenzliste Werte</th>  
        </tr>  
        <tr>  
          <th>Typ</th>  
          <th>Größe</th>  
        </tr> 
      </thead>
      <tbody> 
        <tr>  
          <td>Zelle 1.1</td></tr>  
      </tbody>
    </table>  
    

    Dann klappt’s auch mit dem Nachbarn Stylen.

    LLAP 🖖

    --
    “When UX doesn’t consider all users, shouldn’t it be known as ‘Some User Experience’ or... SUX? #a11y” —Billy Gregory
    1. Mit JaveScript aus Scheiße Gold machen wird wohl die einzige Lösung bleiben.

      Vielen Dank Euch allen

      Jan

      1. Hallo Jan^3,

        Mit JaveScript aus Scheiße Gold machen wird wohl die einzige Lösung bleiben.

        Das wäre eine recht aufwändige Lösung.

        Eine reine CSS-Lösung gibt es nicht, weil CSS nicht rückwärts selektieren kann.

        Eine einfachere Lösung als das ganze DOM umzubauen, wäre der ersten Tabellenzeile genau dann eine Klasse zu geben, wenn sie td-Elemente mit colspan-Attributen enthält. Vielleicht superheading 😂

        var ths = document.querySelectorAll("td[colspan]");
        for (var i=0; i < ths.length; i++) {
        	ths[i].parentNode.classList.add("superheading");
        }
        

        Dann könntest du .superheading + tr td beliebig formatieren.

        (Ich habe es so verstanden: Die zweite Tabellenzeile ist genau dann eine Überschrift, wenn die erste Tabellenzeile verbundene Tabellenzellen enthält.)

        Bis demnächst
        Matthias

        --
        Rosen sind rot.
        1. @@Matthias Apsel

          Eine einfachere Lösung als das ganze DOM umzubauen, wäre der ersten Tabellenzeile genau dann eine Klasse zu geben, wenn sie td-Elemente mit colspan-Attributen enthält.

          Es geht um rowspan.

          Dann könntest du .superheading + tr td beliebig formatieren.

          Nein, das reicht nicht. Siehe Überschrift: „Tabelle mit 2 und mehr Kopfzeilen formatieren“.

          (Ich habe es so verstanden: Die zweite Tabellenzeile ist genau dann eine Überschrift, wenn die erste Tabellenzeile verbundene Tabellenzellen enthält.)

          Die 3., 4., … Zeile kann auch noch eine Kopfzeile sein.

          Du musst erstmal die Anzahl der Kopfzeilen ermitteln, d.h. den größten Wert eines rowspan-Attributs in den Zellen der 1. Zeile. (Ich gehe jetzt mal stillschweigend davon aus, dass die Tabelle so gestrickt ist, dass dies genügt.)

          Und dann macht es auch nicht mehr Arbeit, die Kopfzeilen in den thead zu hängen, als ihnen eine Klasse zu verpassen: CodePen

          Aus den td-Elementen th-Elemente zu machen wäre freilich etwas größerer Aufwand.

          LLAP 🖖

          --
          “When UX doesn’t consider all users, shouldn’t it be known as ‘Some User Experience’ or... SUX? #a11y” —Billy Gregory
          1. Hallo

            @Gunnar Bittersmann Danke! Dein Ansatz funktioniert super für die erste Tabelle. Ab der zweiten Tabelle werden die Kopfzeilen nicht mehr umgeschrieben.

            Ich stehe gerade vollkommen auf dem Schlauch und finde den Grund nicht. 😟

            Jan

            1. Hallo Jan^3,

              Ich stehe gerade vollkommen auf dem Schlauch und finde den Grund nicht. 😟

              document.querySelector('table') findet nur die erste Tabelle.

              Bis demnächst
              Matthias

              --
              Rosen sind rot.
              1. Bisher habe ich mich immer erfolgreich gegen JavaScript verweigert. Spätestens jetzt sollte ich mich endlich mit JavaScript auseinandersetzen.

                Jan

              2. Hallo

                ich habe es geschafft! 😀 JavaScript ist ja gar nicht so schwer und dank der perfekten Vorarbeit von Gunnar Bittersmann habe ich es in relativ kurzer Zeit geschafft. Vielen Dank!

                So funktioniert es:

                  var tableElement = document.querySelectorAll('table');
                  var theadElement;
                  var tbodyElement;
                  var firstRowCellElements;
                  var i, j, maxRowSpan = 0;
                  
                  for (j = 0; j < tableElement.length; j++) {
                    theadElement = tableElement[j].createTHead();
                    tbodyElement = tableElement[j].tBodies[0];
                    firstRowCellElements = tbodyElement.rows[0].cells;
                    
                    for (i = 0; i < firstRowCellElements.length; i++)
                    {
                    	maxRowSpan = Math.max(maxRowSpan, firstRowCellElements[i].rowSpan);
                    }
                    
                    for (i = 0; i < maxRowSpan; i++)
                    {
                    	theadElement.appendChild(tbodyElement.rows[0]);
                    }
                  }
                

                Danke Euch allen!

                Jan