Stefan: CSS - Visuelle Orientierung in Tabelle

Ich versuche eine visuelle Orientierung in einer Tabelle zu erstellen, sodass man - ähnlich wie in Excel - bei einem Mouseover über ein Feld oben bzw. rechts visuell angezeigt bekommt in welcher Spalte und welcher Zeile man sich befindet.

Um es nicht zu verkomplizieren, wäre mein erster Zugang nun eine SVG-Grafik zu erstellen und den einzelnen Feldern dann in Klassen und Unterklassen so zu ordnen, dass sie entsprechend reagieren.

Wär das auch euer Zugang oder gäbe es noch einen einfacheren Weg?

  1. Servus!

    Ich versuche eine visuelle Orientierung in einer Tabelle zu erstellen, sodass man - ähnlich wie in Excel - bei einem Mouseover über ein Feld oben bzw. rechts visuell angezeigt bekommt in welcher Spalte und welcher Zeile man sich befindet.

    ok!

    Die Reihen kannst Du über tr:hover formatieren, evtl. den Hintergrund farbig, oder einen Schatten.

    HTML/Tabellen/Gestaltung_mit_CSS

    Kapitel 2.8

    Die Spalten sind nur mit JS möglich

    Tabellenspalte bei :hover markieren

    Um es nicht zu verkomplizieren, wäre mein erster Zugang nun eine SVG-Grafik zu erstellen und den einzelnen Feldern dann in Klassen und Unterklassen so zu ordnen, dass sie entsprechend reagieren.

    Das mit den Klassen funzt so nicht. Deshalb die Pseudoklasse :hover.

    Wär das auch euer Zugang oder gäbe es noch einen einfacheren Weg?

    Herzliche Grüße

    Matthias Scharwies

    --
    Ich habe heute rausgefunden, dass in das Pizzafach meines Rucksacks auch ein Laptop passt!
    1. @@Matthias Scharwies

      Die Spalten sind nur mit JS möglich

      Sagt wer? 😏

      Tabellenspalte bei :hover markieren

      Das Wiki jetzt nicht mehr. 😇

      Ich habe das dortige Beispiel mit Javascript mal ohne Javascript nachgebaut. Könnte das jemand von CodePen ins Wiki übertragen? Danke.

      Ich hab mich nicht so richtig getraut zu editieren, aber ich denke, der ganze alte Kram kann weg, also der Verweis auf Chris Coyiers Ding mit Pseudoelementen weg und die JavaScript-Lösung weg.

      🖖 Живіть довго і процвітайте

      --
      „Ukončete, prosím, výstup a nástup, dveře se zavírají.“
      1. Hallo Gunnar,

        done. Guck bitte noch mal drüber und erweitere auch deinen Pen, damit er für th und td funktioniert. Das war auch ein Bug der JS Version (den ich gefixt habe).

        Ich kann den Pen auch in den Wiki-Beispielraum kopieren.

        Solange :has im FF noch hinter einem Schalter steckt, hat die JS-Lösung noch noch Existenzberechtigung. Find ich…

        Rolf

        --
        sumpsi - posui - obstruxi
        1. @@Rolf B

          done. Guck bitte noch mal drüber und erweitere auch deinen Pen, damit er für th und td funktioniert.

          Du meinst, ich solle ⌘Z drücken? 😄

          Ich hatte es tatsächlich erst mit :is(th, td), dann aber gesehen, dass das JavaScript-Beispiel etwas anders funktioniert und es daran angepasst. Ich finde es charmant, dass es dadurch einfacher wurde. Das Beispiel soll ja die Anwendung von :has() zeigen, nicht die Sache durch :is() verkomplizieren.

          Ob man bei einer Tabelle auch beim Hovern über die Kopfzelle die Spalte highlighten möchte, hängt sicher von der Abwendung ab und schwankt zwischen ‚unbedingt‘ und ‚völlig überflüssig‘.

          Da sollte man nochmal kurz drüber nachdenken, was hier besser wäre – auch im Kontext, dass der Kalender als Beispiel für eine beliebige Tabelle herhält.

          Und wenn man schon beim Nachdenken ist, vielleicht die Tabelle um Zeilenköpfe erweiten (Kalenderwoche). Dann wären wir beim Einmaleins – wo ich den Hover-Effekt auch nur für die Datenzellen, nicht für die Kopfzellen vorgesehen habe.

          Solange :has im FF noch hinter einem Schalter steckt, hat die JS-Lösung noch noch Existenzberechtigung. Find ich…

          Das Problem im Firefox ist gar nicht mal der Schalter, sondern dass auch bei gesetztem Flag :has() noch nicht richtig funktioniert. Es tut’s wohl schon mit einfachen Selektoren als Argument, aber wenn in der Klammer was Komplexeres steht, steigt Firefox noch aus.

          Ich würde die Reihenfolge aber umdrehen: erst die CSS-Lösung, dann die JavaScript-Lösung. Und bei der CSS-Lösung auch den Satz drinlassen, dass der Hovereffekt ein nützliche Ergänzung (progressive enhancement) ist, aber nicht zwingend erforderlich. Dass man also die JavaScript-Lösung nicht unbedingt braucht.

          🖖 Живіть довго і процвітайте

          --
          „Ukončete, prosím, výstup a nástup, dveře se zavírají.“
          1. Hallo Gunnar Bittersmann,

            ich werdes es ganz anders machen. Es gibt nämlich eine Seite zum Thema Tabellen - Gestaltung mit CSS.

            Dort werde ich deine Lösung einfügen.

            Und bei :has() darauf verweisen.

            Ich habe aber noch eine Verständnisfrage. Im Artikel zur JS Lösung steht

            Chris Coyier von css-tricks machte es mit Pseudoelementen, was aber nicht zugänglich ist.[2]

            Okay, klar. Screennreader arbeiten nicht ordentlich mit ::after/::before zusammen. Aber ich frage mich…

            • Wieso soll eine JS Lösung, die von keinerlei aria-Attributen belastet ist und lediglich eine Klasse hover setzt, zugänglicher sein?
            • Muss eine mausbezogene Zeilen- oder Spaltenmarkierung überhaupt zugänglich sein?
            • Würde ein zugängliches Zeilen-/Spalten-Highlighting nicht implizieren, dass ich Zellen mit der Tastatur highlighten kann, um dann vom Screenreader jeweils Zeile, Spalte und Zelle genannt zu bekommen?

            Und bleibt für mich die Frage unbefriedigend beantwortet, warum die ::after/::before-Lösung schlechter als die JavaScript-Lösung ist. Ein Argument könnte sein, dass die großen Pseudoelemente gerendert werden müssen und Speicher kosten. Aber sie sind temporär und liegen im Viewport, so schlimm kann das nicht sein.

            Rolf

            --
            sumpsi - posui - obstruxi
            1. @@Rolf B

              • Muss eine mausbezogene Zeilen- oder Spaltenmarkierung überhaupt zugänglich sein?

              Wenn man sowas schon macht, sollte der Farbkontrast ausreichend sein, dass man nicht mit einem War-da-was?-Gefühl dasteht.

              • Würde ein zugängliches Zeilen-/Spalten-Highlighting nicht implizieren, dass ich Zellen mit der Tastatur highlighten kann, um dann vom Screenreader jeweils Zeile, Spalte und Zelle genannt zu bekommen?

              Screenreader-Nutzer sollten sich innerhalb der Tabelle zurechtfinden, vorausgesetzt, die Tabelle ist vernünfitg ausgezeichnet, d.h. Kopfzellen als th. Die Zuordnung mit scope-Attribut schadet nicht, ist aber AFAIK bei einfachen Tabellen nicht erforderlich, sondern nur dann, wenn es mehrere Kopfzellen für eine Spalte/Zeile gibt, davon solche mit colspan/rowspan.

              Und bleibt für mich die Frage unbefriedigend beantwortet, warum die ::after/::before-Lösung schlechter als die JavaScript-Lösung ist. Ein Argument könnte sein, dass die großen Pseudoelemente gerendert werden müssen und Speicher kosten. Aber sie sind temporär und liegen im Viewport, so schlimm kann das nicht sein.

              Ich würde weder in die Pseudoelement- noch in die JavaScript-Lösung noch viel Gehirnschmalz stecken. Man hat die :has()-Lösung (no pun intended) und kann darauf setzen, dass die in ein paar Wochen auch im Firefox funktioniert.

              🖖 Живіть довго і процвітайте

              --
              „Ukončete, prosím, výstup a nástup, dveře se zavírají.“
          2. Hallo Gunnar und Matthias,

            ich habe das jetzt sortiert und Gunnars Technik in ein (attributiertes) Beispiel im Selfwiki übertragen. Guckt bitte nochmal drauf.

            Rolf

            --
            sumpsi - posui - obstruxi
  2. Ich hab das versucht. Leider klappt das mit dem Hover (#a1:hover ~ #t1 {fill: red;} mit zwei IDs gleichzeitig nicht.

    Das Ziel wäre hier, dass bei hover auf #a1 sich auch #t1 und #z1 auf den definierten fill Wert ändern.

    <?xml version="1.0" encoding="UTF-8"?>
    <svg id="auswahl" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 601 395">
      <defs>
        <style>
    
    	  
    #a1 {fill: orange;}
    #t1 {fill: green;} 
    #a1:hover {fill: red;}	  
    #a1:hover ~ #t1 {fill: red;}
    
    
    
        </style>
      </defs>
      <g id="t3">
        <rect class="cls-3" x="195" width="128" height="98"/>
      </g>
      <g id="t2">
        <rect class="cls-3" x="325" y="0" width="128" height="98"/>
      </g>
      <g id="t1">
        <rect class="cls-3" x="455" y="0" width="128" height="98"/>
      </g>
      <g id="z3">
        <rect class="cls-2" x="2" y="97" width="128" height="98"/>
      </g>
      <g id="z2">
        <rect class="cls-2" x="1" y="197" width="128" height="98"/>
      </g>
      <g id="z1">
        <rect class="cls-2" y="297" width="128" height="98"/>
      </g>
      <g id="a3">
        <rect class="cls-1" x="174" y="110" width="128" height="98"/>
      </g>
      <g id="a2">
        <rect class="cls-1" x="344" y="120" width="128" height="98"/>
      </g>
      <g id="a1">
        <rect class="cls-1" x="473" y="120" width="128" height="98"/>
      </g>
    </svg>
    
    1. Hallo Stefan,

      oh. Sag das doch, dass deine Tabelle kein <table> Element ist.

      Der Hover auf dem a1 Element funktioniert bei mir.

      Der Hover per Nachbarselektor funktioniert deshalb nicht, weil das #t1 Element im DOM for dem #a1 Element steht. Aber weil dies SVG ist, kannst Du die Überschriften-Elemente auch ans Ende des SVG stellen. Dann geht's auch mit dem Hover.

      Die Datenzellen einer Spalte solltest Du dann mit einer Klasse versehen und nicht mit einer ID, dann ist das im CSS einfacher zu formulieren.

      Ich halte diese SVG basierende Lösung aber für sehr mühsam. Muss das in einem SVG passieren?

      Rolf

      --
      sumpsi - posui - obstruxi
  3. Hallo Stefan,

    oben bzw. rechts visuell angezeigt bekommt in welcher Spalte und welcher Zeile man sich befindet.

    Lechts und rinks ist schwierig, wervexele ich auch ständig.

    Zumindest in meinem Excel sind die Zeilennummern links 😉

    Zeilenweise ist das, was Du möchtest, mit der Pseudoklasse :hover machbar.

    <table>
    <thead>
    </thead>
    <tbody>
    <tr><th></th><td></td><td></td><td></td><td></td></tr>
    <tr><th></th><td></td><td></td><td></td><td></td></tr>
    <tr><th></th><td></td><td></td><td></td><td></td></tr>
    </tbody>
    </table>
    
    tbody tr:hover th {
       background-color: #ffc;
    }
    

    Damit würde die th Zelle in den body-Rows eine gelbe Hintergrundfarbe bekommen, wenn die Maus irgendwo in der Zeile schwebt.

    Für Spalten geht das nicht. Es gibt zwar das col-Element, mit dem Du Spaltenbreiten definieren kannst, und dem Du auch eine Hintergrundfarbe zuweisen könntest. Aber weil die td-Elemente keine Kind-Elemente von col sind und die Relation zwischen col und td nur im Table-Anzeigemodell ist, wird der hover über einem td-Element nicht auf das col-Element übertragen.

    Es gibt böse Tricks draußen im Web. Beispielsweise

    td:hover::before {
       content: " ";
       position:absolute;
       height: 10000px
       width: 100%;
    }
    

    D.h. wenn man über einem td hovert, wird diesem td ein Pseudoelement verpasst, das riesig hoch ist und die ganze Spalte überdeckt. Mittels overflow:hidden auf der table wird dann verhindert, dass dieses Pseudoelement aus der Tabelle hinausschaut.

    Aus meiner Sicht: NICHT tun. Ein solches Element belastet die Layout-Engine des Browsers massiv. Besser wären wohl col-Elemente und eine JavaScript-Lösung, die auf mouseenter und mouseleave reagiert und dem col-Element, das zum td-Element gehört, eine Highlight-Klasse zuweist. Die Nummer des col-Elements bekommst Du über die cellIndex-Eigenschaft des td Elements (vorausgesetzt, dass keine colspans verwendet werden).

    Das ist natürlich nur für Menschen nutzbar, die eine Maus verwenden. Manche Touch-Geräte simulieren mouseenter und mouseleave bei Touch-Aktionen. Das Feature wird also nicht für jeden verfügbar sein.

    Rolf

    --
    sumpsi - posui - obstruxi
    1. @@Rolf B

      tbody tr:hover th {
         background-color: #ffc;
      }
      

      Damit würde die th Zelle in den body-Rows eine gelbe Hintergrundfarbe bekommen, wenn die Maus irgendwo in der Zeile schwebt.

      Eben: irgendwo. Auch über der Kopfzelle. Soll die Kopfzelle auch gehighlightet werden, wenn sich der Zeiger über dieser befindet? Oder nur, wenn sich der Zeiger über einer Datenzellen in dieser Zeile befindet? Ich denke, letzteres. Also den Selektor angepasst:

      tbody tr:has(td:hover) th {
         background-color: #ffc;
      }
      

      Für Spalten geht das nicht.

      🤣 Hold my beer!

      Klar geht das:

      thead:has(~ tbody td:nth-child(2):hover) th:nth-child(2),
      thead:has(~ tbody td:nth-child(3):hover) th:nth-child(3),
      thead:has(~ tbody td:nth-child(4):hover) th:nth-child(4) {
         background-color: #ffc;
      }
      

      Für wieviele Spalten man das vorsehen muss, hängt von der jeweiligen Tabelle ab. Und ein CSS-Präprozessor ist dabei hilfreich.

      Einfach wie das kleine Einmaleins.

      Funktioniert in Safari und Chromia. Firefox hinkt bei :has() noch etwas hinterher. Da es sich hierbei um ein sinnvolles, aber nicht zwingend notweniges Feature handelt, kann man auf progressive enhancement setzen. Irgendwann in nicht allzuferner Zukunft wird es auch im Firefox funktionieren, ohne dass man dazu nochmal was am Code ändern müsste.

      🖖 Живіть довго і процвітайте

      --
      „Im Vergleich mit Elon Musk bei Twitter ist ein Elefant im Porzellanladen eine Ballerina.“
      — @Grantscheam auf Twitter
      1. @@Gunnar Bittersmann

        Und ein CSS-Präprozessor ist dabei hilfreich.

        Zuerst hatte ich im Codepen zu stehen:

        tbody > tr:has(td:hover) > th {
        	background-color: var(--th-highlight-background-color);
        	color: var(--th-highlight-text-color);
        }
        
        @for $col from 2 through 11 {
        	thead:has(~ tbody td:nth-child(#{$col}):hover) th:nth-child(#{$col}) {
        		background-color: var(--th-highlight-background-color);
        		color: var(--th-highlight-text-color);
        	}
        }
        

        Dadurch werden viele Regeln mit immer wieder denselben Deklarationen generiert, was das Stylesheet unnötig aufbläht.

        Besser: in der Schleife die Selektorliste zusammenbauen, dann eine Regel generieren:

        $selectors: "tbody > tr:has(td:hover) > th";
        
        @for $column from 2 through 11 {
        	$selectors: "#{$selectors}, thead:has(~ tbody td:nth-child(#{$column}):hover) th:nth-child(#{$column})";
        }
        
        #{$selectors} {
        	background-color: var(--th-highlight-background-color);
        	color: var(--th-highlight-text-color);
        }
        

        🖖 Живіть довго і процвітайте

        PS: Beachte auch die Umbenennung von $col in $column. 😏

        --
        „Im Vergleich mit Elon Musk bei Twitter ist ein Elefant im Porzellanladen eine Ballerina.“
        — @Grantscheam auf Twitter
        1. @@Gunnar Bittersmann

          Dadurch werden viele Regeln mit immer wieder denselben Deklarationen generiert, was das Stylesheet unnötig aufbläht.

          Besser: in der Schleife die Selektorliste zusammenbauen, dann eine Regel generieren:

          Das kann man aber auch anders haben – einfacher, mit Sass-Bordmittel @extend

          %highlighted {
          	background-color: var(--th-highlight-background-color);
          	color: var(--th-highlight-text-color);	
          }
          
          tbody > tr:has(td:hover) > th {
          	@extend %highlighted;
          }
          
          @for $column from 2 through 11 {
          	thead:has(~ tbody td:nth-child(#{$column}):hover) th:nth-child(#{$column}) {
          		@extend %highlighted;
          	}
          }
          

          ☞ neuer Codepen

          🖖 Живіть довго і процвітайте

          --
          „Ukončete, prosím, výstup a nástup, dveře se zavírají.“