Sådan oprettes responsive tabeller med ren CSS ved hjælp af Grid Layout Module

TL; DR

Den mest populære måde at vise en samling af lignende data på er at bruge tabeller, men HTML-tabeller har den ulempe, at de er vanskelige at gøre responsive.

I denne artikel bruger jeg CSS Grid Layout Module og CSS Properties (og intet Javascript) til layouttabeller, der omslutter kolonner afhængigt af skærmbredde, hvilket yderligere skifter til et kort baseret på layout til små skærme.

For utålmodige, se på følgende pen for en prototypisk implementering.

En lille historie om responsive HTML-tabeller

Responsive tabeller er ikke et nyt emne, og der er mange løsninger, der allerede er blevet foreslået. “Responsive Table Data Roundup”, der først blev offentliggjort i 2012 af Chris Coyier, har ting opsummeret meget pænt (inklusive en opdatering fra 2018).

“Virkelig responsive tabeller ved hjælp af CSS3 Flexbox” af Vasan Subramanian viser en idé om indpakning af kolonner, implementeret med Flexbox.

Selvom der er blevet foreslået mange interessante ideer, vælger biblioteker som bootstrap vandret rulning til små skærme.

Da vi nu har CSS Grid, tror jeg, at vi kunne have et bedre fælles alternativ til vandret rulning.

HTML-tabeller

Startende med det grundlæggende er en tabel i HTML et layoutformat til at vise samlinger af emner gennem en matrix med rækker og kolonner. Elementer er anbragt i rækker med de samme dataattributter i de samme kolonner, hvor rækkerne ofte er sorteret med en eller flere sorterbare attributter. Formatet giver dig et fugleperspektiv, så du hurtigt kan forstå og undersøge store mængder data.

For eksempel er her en hypotetisk tabel over indkøbsordredetaljer, som du muligvis kan se i en indkøbsprogram.

En vare, i dette tilfælde, er en indkøbsordredetalje, der har attributter som varenummer, delbeskrivelse osv.

Når du bruger HTML-tabeller, er layoutet af data hårdkodet som rækker og kolonner (f.eks. Og ). Dette kan være tilstrækkeligt til brug af en skærm, der passer til hele bordbredden, men i virkeligheden gælder dette ikke for det utal af enheder, der findes i dag. Med hensyn til hacks kan du ændre displayegenskaberne for tabeller og bruge ethvert layout, du kan gøre med CSS generelt, men det virker ikke semantisk korrekt.

Omdefinerede tabeller (= Varesamling)

Lad os starte med at omdefinere, hvordan tabeldata skal udtrykkes i HTML.

Da tabeldata i det væsentlige er en ordnet samling af varer, synes det som tidligere nævnt naturligt at bruge ordnede lister. Da tabeller ofte bruges til at supplere tekstbeskrivelser, synes det også naturligt at vedlægge dette i et afsnit, men det afhænger af konteksten for, hvordan tabeldataene bruges.


    
  1. # Part Number Part Description ...
  2. 1 100-10001 Description of part ...
  3. ...

Vanille bruges til at udtrykke elementattributter, da HTML5 ikke definerer et passende tag til dette. Nøglen her er at udtrykke semantisk lignende attributter som et hierarki . Denne struktur vil blive brugt til at definere, hvordan dataene skal udlægges. Jeg kommer tilbage til dette i næste afsnit om emnet styling.

Hvad angår de faktiske data inde i elementet, er det første element på listen overskriften, og resten af ​​elementerne er de faktiske data.

Nu er det tid til at begynde at tale om styling af emnerne med CSS Grid.

Styling Item Collections

Den grundlæggende idé her er at vise alle attributter for varen som en normal tabel, hvor skærmbredden tillader det. Dette layout har den luksus at kunne se så mange genstande (rækker) som muligt.

Når skærmens bredde bliver smallere, stables nogle attributter lodret for at spare vandret plads. Valget af stableattributter skal baseres på:

  1. Giver attributterne mening, når de stables lodret? og,
  2. Når det stables lodret, sparer det vandret plads?

Når bredden yderligere krymper til størrelsen på en mobilenhed, vises hvert element som et kort. Dette layout har redundans, fordi attributnavne gentagne gange vises på hvert kort og har mindst mulig synlighed, men ikke kompromitterer anvendeligheden (f.eks. Vandret rulning, super lille tekst osv.).

Lad os nu dykke ned i detaljerne.

Styling Trin 1: Fuld tabel

Her er et visuelt resume af, hvordan tingene vil blive implementeret med CSS Grid.

For at få kolonner til at ombrydes defineres flere gitterbeholdere som et hierarki. Den røde boks er en gitterbeholder for hver række, og den blå boks er en beholder for hver søjlegruppe, der ombrydes.

Lad os starte med at indstille listen som en gitterbeholder ved at definere en kaldet klasse .item-containerog anvende den på

  • (den røde boks).

    .item-container { display: grid; grid-template-columns: 2em 2em 10fr 2fr 2fr 2fr 2fr 5em 5em; }

    The number of explicit columns specified with grid-template-columns is nine, which is the number of top-level 's, directly  under

  • .

    The column’s width is defined in relative length to make the columns wrap. The actual fraction has to be fine-tuned, based on the content.

    The columns that don’t wrap are defined in absolute length to maximize width usage for the wrapping columns. In the purchase order details example, the second column is a two-digit Id, so I set the width to double that size of 2 m’s.

    Next, we define another grid container called .attribute-container and apply it on all intermediate ’s under the list (the blue box).

    .attribute-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(var(--column-width-min), 1fr)); }

    The minimum column width for all grid items under .attribute-container is specified with a CSS variable called --column-width-min(more on this later) using the minmax function, with the maximum set to take the rest of the space (e.g. one fraction). Since grid-template-columns are repeated, available horizontal space will be split into the maximum number of columns that could take at least --column-width-min, and the rest of the columns would go to the next line. The column’s width will be stretched if there is excess horizontal space because the repeat is auto-fited.

    Styling Step 2: Wrapping Table

    Next, --column-width-min needs to be specified independently for each column in order to wrap. Just to be clear, the variables need to be specified in order for the full table to render properly as well. To do this, a class is set for each .attribute-container, and a different --column-width-min is specified for each class scope.

    Let’s take a look at the HTML where .part-id is applied,

     Part Number Part Description 

    and the CSS:

    .part-id { --column-width-min: 10em; }

    This specific grid container will have two columns, as long as the available width is wider than 10em for each grid item (e.g. the grid container is wider than 20em). Once the grid container’s width becomes narrower than 20em, the second grid item will go to the next row.

    When we combine CSS properties like this, we need only one grid container .attribute-container, with the details changing where the class is applied.

    We can further nest .attribute-containers, to have multiple levels of wrapping with different widths, as in the following exert.

     Part Number Part Description Vendor Number Vendor Name .part-information { --column-width-min: 10em; } .part-id { --column-width-min: 10em; } .vendor-information { --column-width-min: 8em; }

    All of the above is enclosed in the following media query. The actual breakpoint should be selected based on the width necessary when your table is wrapped to the extreme.

    @media screen and (min-width: 737px) { ... }

    Styling Step Three: Card Layout

    The card layout will look like a typical form with attribute names in the first column and attribute values in the second column.

    To do this, a class called .attribute is defined and applied to all leaf tags under the

  • .

    .attribute { display: grid; grid-template-columns: minmax(9em, 30%) 1fr; }

    The attribute names are taken from a custom attribute of the leaf   called data-name, for example , and a pseudo-element is created. The pseudo-element will be subject to the grid container’s layout.

    .attribute::before { content: attr(data-name); }

    The first item in the list is the header and does not need to be displayed.

    /* Don't display the first item, since it is used to display the header for tabular layouts*/ .collection-container>li:first-child { display: none; }

    And finally, the cards are laid out in one column for mobile devices, but two for screens with a little bit more width, but not enough for displaying a table.

    /* 2 Column Card Layout */ @media screen and (max-width: 736px) { .collection-container { display: grid; grid-template-columns: 1fr 1fr; grid-gap: 20px; } ... } /* 1 Column Card Layout */ @media screen and (max-width:580px) { .collection-container { display: grid; grid-template-columns: 1fr; } }

    Finishing Notes

    Accessibility is an area that wasn’t considered at all and may have some space for improvement.

    If you have any ideas or second thoughts, please feel free to comment!

    And of course, thanks for reading.