Πώς να δημιουργήσετε αποκριτικούς πίνακες με καθαρό CSS χρησιμοποιώντας το Grid Layout Module

TL; Δρ

Ο πιο δημοφιλής τρόπος εμφάνισης μιας συλλογής παρόμοιων δεδομένων είναι η χρήση πινάκων, αλλά οι πίνακες HTML έχουν το μειονέκτημα ότι είναι δύσκολο να ανταποκριθούν.

Σε αυτό το άρθρο, χρησιμοποιώ CSS Grid Layout Module και CSS Properties (και όχι Javascript) για τη διάταξη πινάκων που τυλίγουν στήλες ανάλογα με το πλάτος της οθόνης, οι οποίες αλλάζουν περαιτέρω σε μια κάρτα με βάση τη διάταξη για μικρές οθόνες.

Για τους ανυπόμονους, δείτε την ακόλουθη πένα για μια πρωτότυπη εφαρμογή.

Ένα μικρό ιστορικό απόκριτων πινάκων HTML

Οι αποκριτικοί πίνακες δεν είναι ένα νέο θέμα και υπάρχουν πολλές λύσεις που έχουν ήδη προταθεί. Το "Responsive Table Data Roundup" που δημοσιεύθηκε για πρώτη φορά το 2012 από τον Chris Coyier, έχει τα πράγματα συνοπτικά πολύ τακτοποιημένα (συμπεριλαμβανομένης της ενημέρωσης του 2018).

"Πραγματικά ανταποκρινόμενοι πίνακες χρησιμοποιώντας το CSS3 Flexbox" του Vasan Subramanian δείχνει μια ιδέα για την αναδίπλωση στηλών, που υλοποιείται με το Flexbox.

Παρόλο που έχουν προταθεί πολλές ενδιαφέρουσες ιδέες, βιβλιοθήκες όπως το bootstrap επιλέγουν οριζόντια κύλιση για μικρές οθόνες.

Καθώς έχουμε πλέον CSS Grid, νομίζω ότι θα μπορούσαμε να έχουμε μια καλύτερη κοινή εναλλακτική λύση αντί της οριζόντιας κύλισης.

Πίνακες HTML

Ξεκινώντας με τα βασικά, ένας πίνακας σε HTML είναι μια μορφή διάταξης για την εμφάνιση συλλογών στοιχείων μέσω ενός πίνακα γραμμών και στηλών. Τα στοιχεία εκτίθενται σε σειρές, με τα ίδια χαρακτηριστικά δεδομένων στις ίδιες στήλες, με τις σειρές να ταξινομούνται συχνά με ένα ή περισσότερα χαρακτηριστικά ταξινόμησης. Η μορφή σάς προσφέρει μια πανοραμική θέα για γρήγορη κατανόηση και εξέταση μεγάλων ποσοτήτων δεδομένων.

Για παράδειγμα, εδώ είναι ένας υποθετικός πίνακας λεπτομερειών εντολής αγοράς, τον οποίο μπορεί να δείτε σε μια εφαρμογή αγοράς.

Ένα αντικείμενο, σε αυτήν την περίπτωση, είναι μια λεπτομέρεια παραγγελίας αγοράς, που έχει χαρακτηριστικά όπως αριθμός εξαρτήματος, περιγραφή εξαρτήματος κ.λπ.

Όταν χρησιμοποιείτε πίνακες HTML, η διάταξη των δεδομένων είναι κωδικοποιημένη ως σειρές και στήλες (π.χ. και ). Αυτό μπορεί να είναι αρκετό για χρήση από μια οθόνη που ταιριάζει σε ολόκληρο το πλάτος του πίνακα, αλλά στην πραγματικότητα, αυτό δεν ισχύει για πολλές συσκευές που υπάρχουν σήμερα. Όσον αφορά τις εισβολές, μπορείτε να αλλάξετε την ιδιότητα εμφάνισης των πινάκων και να χρησιμοποιήσετε οποιαδήποτε διάταξη μπορείτε να κάνετε με το CSS γενικά, αλλά αυτό δεν φαίνεται σημασιολογικά σωστό.

Επαναπροσδιορισμός πινάκων (= Συλλογή αντικειμένων)

Ας ξεκινήσουμε επαναπροσδιορίζοντας πώς τα δεδομένα πίνακα πρέπει να εκφράζονται σε HTML.

Όπως αναφέρθηκε νωρίτερα, δεδομένου ότι τα δεδομένα πίνακα είναι ουσιαστικά μια παραγγελθείσα συλλογή αντικειμένων, φαίνεται φυσικό να χρησιμοποιείτε παραγγελίες. Επίσης, δεδομένου ότι οι πίνακες χρησιμοποιούνται συχνά για τη συμπλήρωση περιγραφικών κειμένων, φαίνεται φυσικό να το συμπεριλάβουμε σε μια ενότητα, αλλά αυτό θα εξαρτηθεί από το πλαίσιο του τρόπου με τον οποίο χρησιμοποιούνται τα δεδομένα πίνακα.


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

Οι βανίλια χρησιμοποιούνται για την έκφραση χαρακτηριστικών στοιχείων, καθώς το HTML5 δεν ορίζει κατάλληλη ετικέτα για αυτό. Το κλειδί εδώ είναι να εκφράσουμε σημασιολογικά παρόμοια χαρακτηριστικά με μια ιεραρχία του . Αυτή η δομή θα χρησιμοποιηθεί κατά τον καθορισμό του τρόπου με τον οποίο θα πρέπει να σχεδιάζονται τα δεδομένα. Θα επανέλθω σε αυτό στην επόμενη ενότητα για το θέμα του στυλ.

Όσον αφορά τα πραγματικά δεδομένα μέσα στο στοιχείο, το πρώτο στοιχείο στη λίστα είναι η κεφαλίδα και τα υπόλοιπα στοιχεία είναι τα πραγματικά δεδομένα.

Τώρα, ήρθε η ώρα να αρχίσετε να μιλάτε για το στυλ των αντικειμένων με το CSS Grid.

Συλλογές στοιχείων στυλ

Η βασική ιδέα εδώ είναι να εμφανιστούν όλα τα χαρακτηριστικά του αντικειμένου ως κανονικός πίνακας, επιτρέποντας το πλάτος οθόνης. Αυτή η διάταξη έχει την πολυτέλεια να βλέπει όσο το δυνατόν περισσότερα αντικείμενα (σειρές).

Όταν το πλάτος της οθόνης μειώνεται, ορισμένα χαρακτηριστικά στοιβάζονται κάθετα, για εξοικονόμηση οριζόντιου χώρου. Η επιλογή των χαρακτηριστικών στοίβαξης πρέπει να βασίζεται σε:

  1. Έχουν νόημα τα χαρακτηριστικά όταν στοιβάζονται κάθετα; και,
  2. Όταν στοιβάζονται κάθετα, εξοικονομεί οριζόντιο χώρο;

Όταν το πλάτος συρρικνωθεί περαιτέρω στο μέγεθος μιας κινητής συσκευής, κάθε στοιχείο εμφανίζεται ως κάρτα. Αυτή η διάταξη έχει πλεονασμό, επειδή τα ονόματα των χαρακτηριστικών εμφανίζονται επανειλημμένα σε κάθε κάρτα, και έχει τη μικρότερη ορατότητα, αλλά δεν θέτει σε κίνδυνο τη χρηστικότητα (π.χ. οριζόντια κύλιση, εξαιρετικά μικρό κείμενο, κ.λπ.).

Τώρα ας δούμε τις λεπτομέρειες.

Styling Βήμα 1: Πλήρης πίνακας

Ακολουθεί μια οπτική περίληψη για το πώς θα εφαρμοστούν τα πράγματα με το CSS Grid.

Προκειμένου να γίνει αναδίπλωση στηλών, τα πολλαπλά δοχεία πλέγματος ορίζονται ως ιεραρχία. Το κόκκινο πλαίσιο είναι ένα κοντέινερ πλέγματος για κάθε σειρά και το μπλε πλαίσιο είναι ένα κοντέινερ για κάθε ομάδα στηλών που τυλίγεται.

Ας ξεκινήσουμε ορίζοντας τη λίστα ως κοντέινερ πλέγματος, ορίζοντας μια κλάση που ονομάζεται .item-containerκαι εφαρμόζοντάς την στο

  • (το κόκκινο κουτί).

    .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.