Flexible CSS-Rastertabellen


Liste der Leads anzeigen (kalte Kontakte)

Da wir bereits begonnen haben, kann ich endlich über ein geheimes Projekt sprechen, an dem ich in den letzten zwei Jahren gearbeitet habe. Eine der interessanten Funktionen von Teamwork CRM ist eine Listenansicht.

Dies ist eine leistungsstarke Komponente, die in der Anwendung sieben Mal vorkommt. In der Tat eine Tabelle über Steroide. Ich könnte viel erzählen, aber ich möchte dich nicht langweilen. Ich werde mich darauf konzentrieren, wie wir diese Flexibilität mit nur wenigen Zeilen CSS (Grid) implementiert haben. Das heißt, wie wir umfangreiche Datentabellen erstellen, wie wir die Größenänderung von Spalten unterstützen und vieles mehr.

Zunächst muss der Kontext erläutert werden, beginnend mit dem Zweck und den Entwurfsaufgaben dieser Tabellen. Wenn dies nicht von Interesse ist, zögern Sie nicht, sofort mit der technischen Implementierung fortzufahren.

Mit unserer Lösung können Kunden zunächst schnell Listen anzeigen, z. B. Leads oder Kontakte, und wichtige Details erkennen. Es sieht nicht wie eine Excel-Tabelle aus - wir sollten uns besser mit dem Datenlayout befassen, wenn es viele davon gibt.

Absolut alles funktioniert in einem adaptiven flexiblen Design. Wir beginnen mit der engsten Option und passen das Layout basierend auf Inhalt, Design und Anwendungsfällen an (wir haben keine geräteorientierten Haltepunkte).

Bei der minimalen Bildschirmbreite werden Spalten vertikal gestapelt und nehmen die gesamte Bildschirmbreite ein.


Wie die Liste auf einem schmalen Bildschirm aussieht

Flexible Tische sind nicht einfach zu machen. Sie können aus mehreren vorhandenen Vorlagen auswählen. Überlegen Sie, nach welchen Informationen Benutzer suchen, und wählen Sie sie mit Bedacht aus.

Sobald wir genug Pixel auf dem Bildschirm haben, wechseln wir zu einem typischeren Layout, sodass die Spalten ... nun, zu Spalten werden. Dann gibt es keine wesentlichen Änderungen im Layout, aber wir möchten die Spalten dennoch so bequem wie möglich für den Kunden anzeigen.

Angenommen, wir haben viele Spalten (später werden wir uns ansehen, wie der Benutzer sie anpassen kann). Zunächst sollte die Tabelle mindestens die Breite des Bildschirms ausfüllen. Zweitens sollte die Breite der Spalten durch ihren Inhalt und die Art der Werte bestimmt werden. Zum Beispiel Kurz- / Langtext, Datum, Nummer, URL usw. Spalten mit einem Datum sollten weniger Platz einnehmen als Spalten mit Langtext.

Spalten müssen eine Mindestbreite haben. Das Ergebnis ist häufig eine Tabelle, die sowohl vertikal als auch horizontal scrollt.


Wie das Layout hängt, hängt von der Breite des Fensters ab. Entschuldigung für das zuckende GIF, ich werde Ihnen später einige interaktive Beispiele geben.

Zunächst verwenden wir maximal das reguläre CSS der alten Schule für die Tabelle. Dann verbessern wir es mit CSS Grid. Dann werde ich zeigen, wie Benutzer die Größe von Spalten mithilfe von Grid-Tools ändern können, was mit normalem CSS viel unpraktischer war.

Nun zeige schon CSS Grid


Ich bin kein CSS Grid-Experte, aber es gefällt mir. Dies ist ein äußerst leistungsfähiges und einfaches Tool, das komplexe Layouts mit minimalem Code implementiert. Hier werde ich die Einführung in die Technologie überspringen. Sie können die neuen CSS-Layouts von Rachel Andrew oder The Complete Grid Guide lesen. Wenn Sie darüber nachgedacht haben, wo dieses Werkzeug Ihr ganzes Leben lang war, kommen Sie zu mir zurück.

Wenden Sie zunächst display:grid auf <table> an, um die Tabelle in ein Raster umzuwandeln. Dies wird nichts kaputt machen: Wenn der Browser Grid nicht unterstützt, verwendet er display:table . Die <thead> Elemente <thead> und <tbody> werden zu <tbody> . Wir müssen nicht an <thead> , <tbody> oder sogar <tr> denken. Wir möchten unser <th> und <td> in diesem Raster anordnen, indem wir auf jedes von ihnen display:grid anwenden (d. H. Gitter innerhalb der Gitter), aber dies ist nicht ideal. Jedes <tr> -Raster ist unabhängig von den anderen, und dies ist nicht gut (Sie werden später feststellen, dass das gleiche Problem mit Flexbox auftritt).

Die Problemumgehung besteht darin, display:contents <thead> auf <thead> , <tbody> und <tr> . Dadurch werden sie im Grunde genommen aus dem Raster entfernt und die untergeordneten Elemente ( <th> und <td> ) nach vorne <td> .

Dann verwenden wir die magische Regel grid-template-columns , um die Gitterelemente zu steuern. Ja, nur eine Zeile CSS. Wenn wir beispielsweise eine Datumsspalte und eine URL-Spalte haben, sieht diese ungefähr so ​​aus:

 grid-template-columns: minmax(150px, 1.33fr) minmax(150px, 2.33fr); 

Wir verwenden für alle Spalten dieselbe Mindestgröße, aber der Maximalwert ( fr ) wird durch den Datentyp der Spalte bestimmt. Ich habe auto und max-content ausprobiert, aber wir haben eine bessere Option gefunden. Hier ist ein vereinfachtes Beispiel: eine interaktive Tabelle mit Code . Versuchen Sie, die Fenstergröße zu ändern.

Ändern der Spaltenbreite mit Raster


Außerdem können Sie in unseren Tabellen tauschen, die Breite ändern und die Spalten ausblenden. Letzteres ist wichtig, da viele Spalten mit unterschiedlichen Datentypen unterstützt werden: Dies sind die Eigenschaften des Elements selbst (z. B. Leads), die Eigenschaften verwandter Elemente (z. B. eines mit einem Lead verknüpften Unternehmens) und benutzerdefinierte Felder.

Beispielsweise kann ein Benutzer ein benutzerdefiniertes Feld (Datum) für Kontakte mit dem Namen "Geburtsdatum" erstellen, das für jeden Kontakt im System verfolgt wird.

Da beim Erstellen eines benutzerdefinierten Felds der Typ "Datum" ausgewählt ist, verarbeitet das System dieses Feld unter Berücksichtigung dieses Typs. Zunächst werde ich erklären, wie sich die Breite ändert.

  1. Wenn der Benutzer den Cursor über die Spaltenüberschrift bewegt, wird rechts eine Größenänderungsmarkierung angezeigt. Wir hören uns das mousedown Ereignis auf dem Größenänderungsregler an.
  2. Wenn der Benutzer auf den Schieberegler klickt, binden wir einige weitere Methoden, um auf die Ereignisse zum mousedown der mousemove und zum mousedown der mousemove (im window ) zu mousedown . In dieser Phase fügen wir auch einige Klassen für die Dekoration hinzu.
  3. Wenn der Benutzer die Maus bewegt, berechnen wir die neue Spaltenbreite unter Berücksichtigung der Cursorposition, der Bildlaufposition der Tabelle und des festgelegten Minimums. Dann setzen wir die grid-template-columns Regel für <table> (über das Stilattribut) zurück und ersetzen diesmal den Maximalwert ( fr ) durch einen Pixelwert. Beispiel grid-template-columns: minmax(150px, 1.33fr) 296px; . Dies geschieht mit requestAnimationFrame , um eine möglichst reibungslose Animation zu gewährleisten.
  4. Wenn mouseup eintrifft, mouseup wir die Ereignis-Listener ab und löschen die Klassen.

Probieren Sie dieses vereinfachte Beispiel aus .

Bemerkenswerterweise reicht es aus, nur ein Element im DOM und nicht jede Zelle zu aktualisieren.

Wir entwickeln immer eine Benutzeroberfläche, die auf Berührungseingaben basiert. In diesem Fall ist es jedoch normal, diese nicht zu unterstützen. Dies ist eine zu genaue Aktion. Selbst wenn ich die Größe der Spalte auf dem Touchscreen ändern wollte, würde ich wahrscheinlich eine weitere Interaktion erwarten, beispielsweise durch eine Multi-Touch-Geste.

Spalten mit fester Breite


Sie haben vielleicht bemerkt, dass Sie über etwas geschwiegen haben. Tatsächlich ändert sich nicht nur die Breite einer Spalte, sondern aller Spalten. Vielleicht haben Sie das gar nicht bemerkt, denn so sollte es funktionieren.

Anfangs dachte ich, Benutzer würden es mögen: Wenn sie Spalten dehnen oder zusammendrücken, passen sich auch andere an. Wenn die Spalten die Breite des Bildschirms gut ausfüllen und Sie eine davon einschränken, können die anderen erweitert werden, wenn Inhalte vorhanden sind, die nicht in eine Zeile passen. Probieren Sie dieses Beispiel aus .

Nach einigen Benutzertests stellte sich jedoch heraus, dass dies für Menschen ein unerwartetes Verhalten ist. Der Benutzer verspürt einen gewissen Kontrollverlust, wenn seine Handlungen unvorhersehbare Nebenwirkungen verursachen.

Wir sollten keine Annahmen treffen, die darauf beruhen, welche Spalten interagierten und welche nicht. Bei der Größenänderung einer Spalte kann der Benutzer bereits implizit entscheiden, dass die Breite des Rests perfekt ist.

Wenn Sie die Anwendung zum ersten Mal öffnen, werden die Spalten daher optimal angeordnet. Wenn Sie die Bildschirmgröße ändern, ändern sich auch die Spalten nach demselben Prinzip. Sobald Sie den Schieberegler berühren, um die Größe einer Spalte zu ändern, wird die Breite aller sichtbaren Spalten festgelegt.


Vor, während und nach dem Ändern der Spaltenbreite. Wieder tut es mir leid, dass das GIF ein bisschen zuckt

Jedes Mal, wenn die Größe einer Spalte geändert oder festgelegt wird, erstellen wir einen unabhängigen localStorage-Datensatz, der der Spaltenkennung mit einem Pixelwert entspricht, um die Benutzereinstellungen beizubehalten.

Ich kann mich nicht genau erinnern, warum wir beschlossen haben, einen festen Wert in Pixel festzulegen, keine adaptive Option. Vielleicht der Einfachheit halber. Oder weil ohne Unterstützung für Grid und display:contents ein Rollback zu einem archaischeren Ansatz zum Anpassen der Breite der Spalten erfolgt.

Wahrscheinlich entspricht die adaptive Option in keinem Fall den Absichten des Benutzers. Wir können nicht davon ausgehen, dass es für ihn am wichtigsten ist, alle Spalten kleiner zu machen, damit sie alle auf dem Bildschirm bleiben. Wenn eine Person die Breite der Spalte geändert hat, möchte sie eine bestimmte Menge an Inhalten in dieser Spalte sehen. Wenn wir einen adaptiven Block haben und dieser dann in einem kleineren Fenster enger wird, ignorieren wir die Wahl der Person. Er muss die Spaltenbreite erneut ändern, um den gleichen Inhalt zu sehen. Es ist unwahrscheinlich, dass der Benutzer denkt: "Hmm, ich möchte, dass diese Spalte 20% des Fensters einnimmt, auch wenn ich sie ändere." Ich gehe jedoch zu tief in die Grenzsituation ein: Tatsächlich ändern Benutzer die Größe von Fenstern selten.

Spalten verschieben und löschen



Schnittstelle zum Anpassen der angezeigten Spalten

Stellen Sie sich vor, ein Benutzer hat über diese Schnittstelle eine Reihe von Spalten geändert. Wenn keine der ausgewählten Spalten zuvor geändert wurde, werden sie je nach Datentyp mit den Standardwerten grid-template-column angezeigt. Zum Beispiel minmax(150px, 3.33fr) .

Wenn die Breite einer Spalte in localStorage festgelegt ist, legen wir die Breite aller ausgewählten Spalten fest und speichern diese Werte auch in localStorage.

Im Laufe der Zeit behalten immer mehr Spalten eine feste Breite. Für Benutzer besteht die einzige Möglichkeit, zum reaktionsschnellen Design zurückzukehren, darin, die Spalten zurückzusetzen.

Wir speichern auch ein Array von Spaltenkennungen in localStorage, getrennt von den Breiteneinträgen.

"Warum hast du nicht einfach {{libraryName}} verwendet?"


Mit der JavaScript-Bibliothek ist die Lösung schwer, nervös, bietet keine Interaktivität und unterstützt möglicherweise <table> überhaupt nicht. Ich wollte so etwas auch nicht schreiben. Ich dachte: "Es muss einen besseren Weg geben."

"Warum haben Sie nicht einfach Flexbox verwendet?"


Jede Zeile wird unabhängig voneinander ausgewertet / angezeigt. Die Spalte ist aufgrund des unterschiedlichen Inhaltsvolumens möglicherweise nicht an der obigen Spalte ausgerichtet.

Ich könnte für Spalten mit vertikal gruppierten Zellen zu <div> wechseln. Wollte das aber nicht. Ich wollte <table> verwenden. Darüber hinaus können leicht andere Probleme auftreten: beispielsweise eine Nichtübereinstimmung der Zellen in der Höhe zwischen den Spalten.

"Warum hast du nicht einfach <colgroup> ?"


In der Tat ist <colgroup> ein bequemes altes Element. Nach dem Definieren von Spalten mit <col> werden auf eine angewendete Stile effektiv auf alle Zellen in dieser Spalte angewendet.

Dies stellte sich jedoch als zu begrenzte Lösung heraus. Wir haben es versucht, aber sehr schnell abgelehnt. So schnell, dass ich mich nicht genau an die Probleme erinnern kann. Ich bin mir fast sicher, dass es unmöglich war, das gewünschte Maß an Anpassungsfähigkeit zu erreichen, und es hat mit Flexbox und Grid nicht funktioniert.

"Warum hast du nicht einfach das Tabellenlayout verwendet: behoben?"


Ich könnte das table-layout: fixed Regel auf die <table> anwenden und die Spaltenbreite als Prozentsatz festlegen. Aber als ich mir die Beispiele ansah und mit dieser Regel spielte, hatte ich den Eindruck, dass sie nur an 100% breiten Tischen funktioniert. Durch Ändern der Größe einer Spalte wird außerdem die Größe der anderen Spalten geändert, um eine Gesamtbreite von 100% zu erreichen.

"Aber Sie könnten mit einfachen Tischen auskommen!"


Ja, die sofort einsatzbereiten Tabellen sind zu vielen intelligenten Dingen fähig, aber sie können nicht alles effektiv unterstützen, was ich implementieren wollte. Nicht einverstanden? Okay Zauberer, lehre mich.

Gehen Sie mit display: content nicht zu weit


Der Wert display: contents darf das Tabellenlayout speichern. Verwenden Sie es nur, wenn Sie es wirklich brauchen. Einige Browser haben oder hatten zumindest Probleme mit der Barrierefreiheit und den Bildschirmleseprogrammen.

Wir haben eine seltsame display: contents Inhaltsfehler mit nativem Drag & Drop in Firefox.

Glücklicherweise wird in Kürze eine Subgrid-Funktion veröffentlicht, mit der untergeordnete Elemente korrekt in Grids integriert werden können. In unserer Anwendung möchten wir nur das Markup vereinfachen, aber die Subnetze öffnen die Türen zu wilden mehrdimensionalen Gitterorgien. Siehe „Warum anzeigen: Inhalt ist kein CSS-Rasterlayout“ .

Ich habe wohl etwas vergessen


Es scheint, dass beim Ändern der Spaltengröße immer noch ein Problem mit dem Textüberlauf aufgetreten ist, aber ich erinnere mich nicht genau.

Um die Tabellenüberschriften beim Scrollen nach unten zu speichern, verwenden wir position: sticky . Dies ist eine großartige Verbesserung und wird in älteren Browsern sehr gut beeinträchtigt. Für IE11-Benutzer haben wir jedoch Backup-JavaScript. In der Tat würde ich position: sticky nicht empfehlen position: sticky aufgrund von Schwierigkeiten beim horizontalen Scrollen.

Ich habe einige Funktionen unserer Listenansichten nicht einmal erwähnt. Beispielsweise können Benutzer benutzerdefinierte Filter anwenden, speichern und austauschen (z. B. Leads über 500 US-Dollar bei potenziellen Kunden in Europa anzeigen). In diesen Filtern können Sie sich eine Reihe von Spalten merken, um immer bestimmte Spalten für einen bestimmten Workflow anzuzeigen.

In Kürze werden wir die Massenbearbeitung in der Listenansicht implementieren und benutzerdefinierte Ansichten in CSV exportieren.

Trotzdem danke fürs Lesen.

Source: https://habr.com/ru/post/de452922/


All Articles