Eine leichte Mauerwerkslösung
Im Mai habe ich erfahren, dass Firefox Mauerwerkslayout -Funktionalität in CSS -Gitter hinzugefügt hat. Mauerwerkslayout war etwas, das ich schon immer von Grund auf neu implementieren wollte, aber ich habe nie gewusst, wo ich anfangen soll. Also habe ich mir natürlich die Demo angesehen und dann hatte ich einen Blitz der Inspiration, als ich verstand, wie dieses neue CSS -Feature funktioniert.
Derzeit ist die Unterstützung auf Firefox beschränkt (und auch dort, nur wenn bestimmte Flags aktiviert sind), aber dies gibt mir immer noch einen Ausgangspunkt für eine JavaScript -Implementierung, mit der Browser, die derzeit fehlen, abdecken können.
Firefox implementiert das Mauerwerkslayout in CSS durch Einstellen grid-template-rows
(wie im Beispiel gezeigt) oder grid-template-columns
auf masonry
Mauerwerkswert.
Mein Ansatz ist es, diese Funktion zu nutzen, um den Browser zu unterstützen. Lassen Sie uns sehen, wie dies mit einem bestimmten Fall eines Bildnetzes erreicht werden kann.
Aktivieren Sie zunächst Flags
Dazu besuchen wir about:config
in Firefox und suchen Sie nach "Mauerwerk". Dadurch werden das Flag der layout.css.grid-template-masonry-value.enabled
angezeigt, das wir aktivieren können, indem wir doppelklicken, um seinen Wert von false
(dem Standardwert) auf true
zu ändern.
Beginnen wir mit einigen Markups
Die HTML -Struktur lautet wie folgt:
<img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174364597525146.jpg" class="lazy" alt="Eine leichte Mauerwerkslösung">
Lassen Sie uns nun einige Stile anwenden
Zunächst stellen wir das oberste Element als CSS -Raster -Container fest. Als nächstes definieren wir die maximale Breite für das Bild, zum Beispiel 10em
. Wir möchten auch, dass diese Bilder auf einen beliebigen Raum schrumpfen, der dem Raster -Inhaltsbox zur Verfügung steht. Wenn das Ansichtsfenster zu eng wird, um ein einzelnes 10em
-Spaltenraster aufzunehmen, ist der Wert tatsächlich Min(10em, 100%)
. Da reaktionsschnelles Design heutzutage sehr wichtig ist, adören wir automatisch so viele Spalten dieser Breite wie möglich an, anstatt eine feste Anzahl von Spalten zu verwenden:
$ w: min (10em, 100%); .Grid-masonry { Anzeige: Grid; Grid-Template-Säulen: Wiederholen (automatisch, $ w); > * {Breite: $ w; } }
Beachten Sie, dass wir Min()
anstelle von min()
verwendet haben, um Sass -Konflikte zu vermeiden.
OK, das ist ein Netz!
Es ist jedoch kein sehr schönes Netz. Lassen Sie uns den Inhalt horizontal zentriert und dann die Gitterlücke und Füllung hinzufügen, beide gleich einem Abstandswert ( $s
). Wir haben auch einen Hintergrund für die einfachere Anzeige eingerichtet.
$ s: .5em; /* Mauerwerksnetzstil*/ .Grid-masonry { /* Gleich wie vorheriger Stil*/ Justify-Content: Center; Raster-Lack: $ S; Polsterung: $ S; } /* Verschönerungsstil*/ html {Hintergrund: #555; }
Nach einer kleinen Verschönerung des Netzes haben wir uns dem Gitterprojekt (d. H. Das Bild) zum gleichen verwandelt. Wenden wir einen Filter an, damit er etwas gleichmäßiger aussieht und gleichzeitig einen zusätzlichen Stil mit leicht abgerundeten Ecken und Schatten hinzufügt.
img { Border-Radius: 4px; Box-Shadow: 2px 2px 5px RGBA (#000, .7); Filter: Sepia (1); }
Für Browser, die Mauerwerkslayouts unterstützen, müssen wir sie nur erklären:
.Grid-masonry { /* Gleich wie vorheriger Stil*/ Grid-Template-Reihen: massiv; }
Während dies in den meisten Browsern nicht funktioniert, werden in Firefox mit den zuvor erklärten Flaggen die erwarteten Ergebnisse erzielt.
Aber was ist mit anderen Browsern? Das brauchen wir ...
JavaScript -Fallback -Lösung
Um den JavaScript-Code zu speichern, den der Browser ausführen muss, prüfen wir zunächst, ob es auf der Seite ein .grid--masonry
-Element gibt und ob der Browser masonry
von grid-template-rows
verstanden und angewendet hat. Beachten Sie, dass dies ein allgemeiner Ansatz ist, vorausgesetzt, auf unserer Seite kann es mehrere solche Netze geben.
lass grids = [... document.querySelectorAll ('. Grid-Masonry')]; if (grids.length && getComputedStyle (Grids [0]). GridTemplaterows! == 'Mauerwerk') { console.log ('oops, Mauerwerkslayout unterstützt nicht?'); } anders { console.log ('Zu gut, keine Operation erforderlich!'); }
Wenn die neue Mauerwerksfunktion nicht unterstützt wird, erhalten wir für jedes Mauerwerksnetz die Zeilenlücke und Maschen.
lass grids = [... document.querySelectorAll ('. Grid-Masonry')]; if (grids.length && getComputedStyle (Grids [0]). GridTemplaterows! == 'Mauerwerk') { grids = grids.map (grid => ({{ _el: Raster, Lücke: Parsefloat (GetComputedstyle (Grid) .Gridrowgap), Elemente: [... Grid.Childnodes] .Filter (c => c.nodetype === 1), NCOL: 0 })); grids.foreach (grid => console.log (`grid item: $ {grid.items.length}; Grid Gap: $ {grid.gap} px`)); }
Beachten Sie, dass wir sicherstellen müssen, dass die untergeordneten Knoten Elementknoten sind (dies bedeutet, dass ihr nodeType
1 ist). Andernfalls können wir Textknoten haben, die aus Wagenrenditen im Projektarray bestehen.
Bevor wir fortfahren, müssen wir sicherstellen, dass die Seite geladen ist und sich die Elemente noch bewegen. Sobald wir uns mit diesem Problem befasst haben, nehmen wir jedes Netz und lesen seine aktuelle Anzahl von Spalten. Wenn sich dies von dem Wert unterscheidet, den wir bereits haben, aktualisieren wir den alten Wert und ordnen die Netzelemente neu an.
if (grids.length && getComputedStyle (Grids [0]). GridTemplaterows! == 'Mauerwerk') { grids = grids.map (/* ist die gleiche wie vor*/); Funktionslayout () { grids.foreach (grid => { /* Die Spaltennummer der Größen-/geladenen Spaltennummer erhalten*/ Sei ncol = getComputedStyle (grid._el) .gridTemPlateColumns.Split ('') .Length; if (grid.ncol! == ncol) { grid.ncol = ncol; console.log ('Raster -Gitterartikel neu ordnen'); } }); } AddEventListener ('Load', e => { Layout(); /* Anfängliche Last*/ addEventListener ('Größe', Layout, Falsch); }, FALSCH); }
Beachten Sie, dass das Aufrufen layout()
-Funktion eine Operation ist, die wir durchführen müssen, wenn sowohl die anfängliche Belastung als auch die Änderung der Größe sind.
Um die Netzelemente neu zu ordnen, besteht der erste Schritt darin, den oberen Rand von allen Elementen zu entfernen (dies kann auf einen Wert ungleich Null eingestellt werden, um den Mauerwerkseffekt vor der Stromgrößenänderung zu erreichen).
Wenn das Ansichtsfenster eng genug ist und wir nur eine Spalte haben, dann sind wir fertig!
Andernfalls überspringen wir die ersten ncol
-Elemente und schleifen den Rest durch. Für jeden berücksichtigten Artikel berechnen wir die Unterkanteposition des obigen Elements und seine aktuelle Position der oberen Kante. Auf diese Weise können wir berechnen, wie viel vertikale Bewegung benötigt wird, damit sich die Oberkante in einer Gitterlücke unterhalb der unteren Rand des obigen Projekts befindet.
/* Wenn sich die Anzahl der Spalten geändert hat*/ if (grid.ncol! == ncol) { /* Anzahl der aktualisierten Spalten*// grid.ncol = ncol; /* Erstpositionierung wiederherstellen, kein Rand*/ Grid.Items.foreach (c => C.Style.RemoveProperty ('Margin-Top')); /* Wenn wir mehr als eine Spalte haben*/ if (grid.ncol> 1) { grid.items.lice (ncol) .foreach ((c, i) => { Sei prev_fin = grid.items [i] .GetBoundingClientRect (). Unten, unten des obigen Projekts* / Curr_ini = C.GetBoundingClientRect (). Top; /* Oberkante des aktuellen Projekts*/ C.Style.Margintop = `$ {prev_fin grid.gap - curr_ini} px`; }); } }
Jetzt haben wir eine funktionierende Cross-Browser-Lösung!
Einige geringfügige Verbesserungen
Eine realistischere Struktur
In der realen Welt wickeln wir jedes Bild mit größerer Wahrscheinlichkeit in einen Link zu seinem Bild in voller Größe ein, damit das große Bild in der Lichtkiste geöffnet werden kann (oder wir navigieren als Fallback).
<a href="https://www.php.cn/link/849c1f472f609bb4a3bacafef177f541"> <img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174364597550777.jpg" class="lazy" alt="Eine leichte Mauerwerkslösung"> </a>
Dies bedeutet, dass wir auch das CSS ein wenig ändern müssen. Obwohl wir die Breite der Netzelemente nicht mehr explizit festlegen müssen - weil sie jetzt Links sind - müssen wir align-self: start
, da sie im Gegensatz zu Bildern standardmäßig die gesamte Zeilenhöhe abdecken, die unseren Algorithmus stört.
.Grid-masonry> * {Align-Self: Start; } img { Anzeige: Block; /* Vermeiden Sie seltsamen zusätzlichen Platz unten*/// Breite: 100%; /* Gleich wie vorheriger Stil*/ }
Machen Sie das erste Element das Netz überspannen
Wir können auch das erste Projekt horizontal über das gesamte Netz umfassen (was bedeutet, dass wir wahrscheinlich auch seine Höhe begrenzen und sicherstellen sollten, dass das Bild nicht überflutet oder verformt):
.Grid-masonry>: Erstkind { Grid -Säule: 1 / -1; maximalhöhe: 29 VH; } img { Max-Höhe: Erbe; Objekt-Fit: Deckung; /* Gleich wie vorheriger Stil*/ }
Wir müssen auch einen weiteren Filter hinzufügen, wenn wir die Liste der Netzelemente erhalten, um diesen gestreckten Element auszuschließen:
grids = grids.map (grid => ({{ _el: Raster, Lücke: Parsefloat (GetComputedstyle (Grid) .Gridrowgap), Elemente: [... Grid.Childnodes] .Filter (c => c.nodetype === 1 && GetComputedStyle (C) .GridColumnend! == -1 ), NCOL: 0 }));
Handle Grid -Elemente mit variablen Seitenverhältnissen behandeln
Angenommen, wir möchten diese Lösung für Zwecke wie Bloggen verwenden. Wir behalten genau die gleichen JS und nahezu identischen Mauerwerks-spezifischen CSS-wir ändern nur die maximale Breite der Säule und entfernen die max-height
-Grenze für das erste Element.
Wie aus der folgenden Demonstration hervorgeht, funktioniert unsere Lösung in diesem Fall perfekt und wir haben ein Blog -Post -Raster:
Sie können das Ansichtsfenster auch ändern, um zu sehen, wie es in diesem Fall funktioniert.
Wenn wir jedoch möchten, dass die Spaltenbreite beispielsweise eine gewisse Flexibilität hat:
$ w: minmax (min (20em, 100%), 1fr);
Dann werden wir bei der Größe auf Probleme stoßen:
Die Kombination der Änderung der Breite der Netzelemente und die Tatsache, dass der Textinhalt jedes Elements unterschiedlich ist, bedeutet, dass wir, wenn ein bestimmter Schwellenwert überschritten wird, eine unterschiedliche Anzahl von Textzeilen für Gitterelemente erhalten (und somit die Höhe ändern), andere Elemente jedoch nicht. Wenn sich die Anzahl der Spalten nicht geändert hat, ist der vertikale Offset nicht neu berechnet und wir haben überlappende oder größere Lücken.
Um dieses Problem zu lösen, müssen wir den Offset neu berechnen, wenn sich die aktuelle Gitterhöhe von mindestens einem Element ändert. Dies bedeutet, dass wir auch testen müssen, ob es im aktuellen Netz mehr als Nullartikel gibt, die ihre Höhe geändert haben. Dann müssen wir diesen Wert am Ende if
-Blocks zurücksetzen, damit wir die Elemente beim nächsten Mal nicht unnötig neu ordnen müssen.
if (grid.ncol! == ncol || grid.mod) { /* Wie früher*/ grid.mod = 0; }
OK, aber wie ändern wir diesen grid.mod
? Meine erste Idee ist es, ResizeObserver
zu verwenden:
if (grids.length && getComputedStyle (Grids [0]). GridTemplaterows! == 'Mauerwerk') { Sei O = New ReiseBerver (Einträge => { Einträge.foreach (Eintrag => { grids.find (grid => grid._el === Eintrag.target.Parentelement) .mod = 1; }); }); /* Wie früher*/ AddEventListener ('Load', e => { /* Wie früher*/ grids.foreach (grid => {grid.items.foreach (c => o.observe (c));}); }, FALSCH); }
Dies ermöglicht es, die Netzelemente bei Bedarf neu zu ordnen, auch wenn sich die Anzahl der Netzspalten nicht geändert hat. Es macht es aber auch bedeutungslos, auch if
die Bedingungen nicht verfügbar sind!
Dies liegt daran, dass das grid.mod
auf 1 wechselt, wenn sich die Höhe oder Breite von mindestens einem Element ändert. Die Höhe des Projekts ändert sich aufgrund des Textausfalls, der durch Veränderung der Breite verursacht wird. Die Veränderung der Breite wird jedoch jedes Mal stattfinden, wenn wir die Ansichtsfenstergröße anpassen, und sie löst nicht unbedingt die Höhenänderung aus.
Aus diesem Grund habe ich mich entschlossen, frühere Projekthöhen zu speichern und zu prüfen, ob sie sich bei der Änderung geändert haben, um festzustellen, ob grid.mod
bei 0 bleibt:
Funktionslayout () { grids.foreach (grid => { grid.items.foreach (c => { let new_h = c.GetBoundingClientRect (). Höhe; if (new_h! == c.dataset.h) { C.Dataset.h = new_h; grid.mod; } }); /* Wie früher*/ }); }
Das war's! Jetzt haben wir eine schöne leichte Lösung. Der komprimierte JavaScript beträgt weniger als 800 Bytes, während strenge Stile im Zusammenhang mit Mauerwerk weniger als 300 Bytes beträgt.
Aber jedoch, aber ...
Wie ist Browser -Unterstützung?
Nun, @supports
bietet zufällig eine bessere Browser-Unterstützung als jede neuere CSS-Funktion, die hier verwendet wird, sodass wir das gute Zeug einsetzen und ein grundlegendes nicht masonriges Netz für nicht unterstützte Browser bereitstellen können. Diese Version ist rückwärtskompatibel für IE9.
Es mag anders aussehen, aber es sieht gut aus und hat eine perfekte Funktion. Die Unterstützung eines Browsers bedeutet nicht, alle visuellen Effekte dafür zu kopieren. Dies bedeutet, dass die Seite funktioniert und nicht beschädigt oder hässlich aussieht.
Was ist mit der Situation ohne JavaScript?
Nun, wir können nur ausgefallene Stile anwenden, wenn das Root -Element js
-Klasse hat, die wir über JavaScript hinzugefügt haben! Andernfalls erhalten wir für alle Gegenstände ein Basisnetz von gleicher Größe.
Das obige ist der detaillierte Inhalt vonEine leichte Mauerwerkslösung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen











Zu Beginn eines neuen Projekts erfolgt die SASS -Zusammenstellung im Blinzeln eines Auges. Dies fühlt sich gut an, besonders wenn es mit Browsersync kombiniert ist, das nachlädt

Versuchen wir, hier einen Begriff zu prägen: "Statischer Formanbieter". Sie bringen Ihre HTML

In der Zusammenfassung der Plattformnachrichten in dieser Woche stellt Chrome ein neues Attribut für das Laden, Zugänglichkeitspezifikationen für Webentwickler und die BBC -Bewegungen ein

Zwei Artikel veröffentlichten genau den selben Tag:

In dem ersten Teil dieser zweiteiligen Serie werden beschrieben, wie wir einen Zwei-Daumen-Schieberegler erhalten können. Jetzt sehen wir uns einen allgemeinen Multi-Thumb-Fall an, aber mit einem anderen und

Ich schaue mir das HTML -Element zum ersten Mal an. Ich habe es für eine Weile dessen bewusst, aber Haven ' Es wurde es noch nicht für einen Dreh genommen. Es hat einige ziemlich cool und

Goofonts ist ein Nebenprojekt, das von einer Entwicklerin und einem Designer-Ehemann signiert wurde, beide große Fans der Typografie. Wir haben Google markiert

Der Dokumentkopf ist vielleicht nicht der glamouröseste Teil einer Website, aber was darauf einfließt
