css flex inline
bearbeitet vonHallo ich,
ein Flexitem erzeugt einen eigenen Blockformatierungskontext und DESHALB geht das nicht.
Ausnahme: Das Flexitem ist selbst wieder ein Flex-Container. Dann erzeugt es einen Flexformatierungskontext. Aber der bricht auch nicht um.
Test:
~~~html
<div class="flex">
<div>Das ist das erste Flexitem, nur für mich</div>
<div><span>Das ist das</span><span>zweite Flexitem,</span><span>nur für dich</span></div>
</div>
~~~
~~~css
.flex {
display: inline-flex;
flex-flow: row wrap;
}
.flex div {
display: inline-flex;
flex-flow: row wrap;
gap: 0.25em;
}
~~~
bricht das zweite div trotzdem vollständig um.
Da die Anordnung mit `order` unzugänglich ist (ein Screenreader oder die Tab-Reihenfolge achten nicht auf order), würde ich Dir empfehlen, die Items im DOM mit JavaScript umzusortieren. Das ist etwas schwieriger, dürfte aber die wenigsten Probleme machen.
Ich zeige mal, wie man das macht.
~~~html
<ol class="orderable itemlist">
<li value="2">Das ist das erste Flexitem, nur für mich. </li>
<li value="4">Das ist das zweite Flexitem, nur für dich. </li>
<li value="1">Das ist das dritte Flexitem, für ihn, sie und them. </li>
<li value="3">Das ist das vierte Flexitem, für die ganze Welt. </li>
<li value="1">Das ist das fünfte Flexitem, für Selfhtml. </li>
</ol>
~~~
Ich verwende eine Liste, weil es für li Elemente das value-Attribut gibt, das die Nummer des Items angibt. Man muss es für alle setzen, bzw. wo es nicht gesetzt ist, ist der Wert 0.
Man iteriert nun über alle Listen mit den Klassen orderable und itemlist (fühle Dich frei, die zu sortierenden Container anders zu identifizieren) und sortiert die Items der gefundenen Listen anhand des value-Attributs um.
Dieses Iterieren kann man so formulieren:
~~~js
const orderables = document.querySelectorAll("ol.orderable.itemlist");
for (const orderable of orderables) {
...
}
~~~
oder kompakter so:
~~~js
for (const orderable of document.querySelectorAll("ol.orderable.itemlist")) {
...
}
~~~
Felix würde jetzt sagen: dafür nimmt man die forEach-Methode. Ich nicht, das ist aus meiner Sicht veraltet, ich bevorzuge bei iterierbaren Sammlungen die for...of Schleife.
Im Inneren der Schleife muss man jetzt die Listitems einsammeln. Das geht geschickt mit einem :scope-Selektor und dem Kind-Kombinator für querySelectorAll:
~~~js
items = orderable.querySelectorAll(":scope > li")
~~~
Das Ergebnis ist eine Nodelist. Zum Sortieren braucht man aber ein Array. Die moderne Methode, aus einem iterierbaren Objekt ein Array zu machen, ist ein Arrayliteral mit spread-Operator:
~~~js
const items = [ ...orderable.querySelectorAll(":scope > li") ];
~~~
Beachte: Es ist nicht nötig, die Zwischenergebnisse in Variablen zu speichern. Man kann direkt auf den Funktionsergebnissen weiterarbeiten.
DAS kann man nun mit der sort-Methode nach der order sortieren. Dafür braucht man sort mit Vergleichs-Callback. Da das value-Attribut immer numerisch ist, kann man `a.value - b.value` rechnen.
~~~js
const items = [ ...orderable.querySelectorAll(":scope > li") ]
.sort( (a,b) => a.value > b.value );
~~~
Sort liefert das sortierte Array zurück, d.h. wir können dieses Ergebnis nun durchlaufen. Die items-Variable brauchen wir nicht mehr…
~~~js
for (const orderable of document.querySelectorAll("ol.orderable.itemlist")) {
for (const sortedRef of
[...orderable.querySelectorAll(":scope > li")]
.sort( (a,b) => a.value - b.value )
) {
orderable.append(sortedRef)
}
}
~~~
Der append-Aufruf entfernt das Element von seiner aktuellen Position und hängt es hinten an die Liste der Kindelemente an. Bei gleicher value-Nummer sollten die Elemente so hintereinander stehen, wie sie vor dem Sortieren vorgefunden wurden.
Edit: Ich habe das überarbeitet, vorher waren es divs, jetzt ul/li, das ist viel einfacher und auch semantischer. Ich hoffe, ich habe nichts übersehen.
_Rolf_
--
sumpsi - posui - obstruxi
css flex inline
bearbeitet vonHallo ich,
ein Flexitem erzeugt einen eigenen Blockformatierungskontext und DESHALB geht das nicht.
Ausnahme: Das Flexitem ist selbst wieder ein Flex-Container. Dann erzeugt es einen Flexformatierungskontext. Aber der bricht auch nicht um.
Test:
~~~html
<div class="flex">
<div>Das ist das erste Flexitem, nur für mich</div>
<div><span>Das ist das</span><span>zweite Flexitem,</span><span>nur für dich</span></div>
</div>
~~~
~~~css
.flex {
display: inline-flex;
flex-flow: row wrap;
}
.flex div {
display: inline-flex;
flex-flow: row wrap;
gap: 0.25em;
}
~~~
bricht das zweite div trotzdem vollständig um.
Da die Anordnung mit `order` unzugänglich ist (ein Screenreader oder die Tab-Reihenfolge achten nicht auf order), würde ich Dir empfehlen, die Items im DOM mit JavaScript umzusortieren. Das ist etwas schwieriger, dürfte aber die wenigsten Probleme machen.
Beispiel:
~~~html
<div class="orderable itemlist">
<div data-order="2">Das ist das erste Flexitem, nur für mich. </div>
<div data-order="4">Das ist das zweite Flexitem, nur für dich. </div>
<div data-order="1">Das ist das dritte Flexitem, für ihn, sie und them. </div>
<div data-order="3">Das ist das vierte Flexitem, für die ganze Welt. </div>
<div data-order="1">Das ist das fünfte Flexitem, für ihn, sie und them. </div>
</div>
~~~
Ich verwende data-order, weil es kein order-Attribut gibt, das ist CSS, und es wäre Quatsch (find ich), für jedes Element erstmal die CSS-Eigenschaften einzusammeln (mit window.getComputedStyle(elem) oder elem.computedStyleMap()).
Man iteriert nun über alle Elemente mit den Klassen orderable und itemlist (fühle Dich frei, die zu sortierenden Container anders zu identifizieren) und sortiert die Kindelemente der gefundenen Container um.
Dieses Iterieren kann man so formulieren:
~~~js
const orderables = document.querySelectorAll(".orderable.itemlist");
for (const orderable of orderables) {
...
}
~~~
oder kompakter so:
~~~js
for (const orderable of document.querySelectorAll(".orderable.itemlist")) {
...
}
~~~
Felix würde jetzt sagen: dafür nimmt man die forEach-Methode. Ich nicht, das ist aus meiner Sicht veraltet, ich bevorzuge bei iterierbaren Sammlungen die for...of Schleife.
Im Inneren der Schleife muss man jetzt die Kindelemente mit data-order Attribut einsammeln. Das geht geschickt mit einem :scope-Selektor und dem Kind-Kombinator für querySelectorAll:
~~~js
items = orderable.querySelectorAll(":scope > [data-order]")
~~~
Das Ergebnis ist eine Nodelist. Zum Sortieren braucht man aber ein Array, und zum einfacheren Sortieren ein Array, das den data-order-Wert direkt enthält. Die moderne Methode, aus einem iterierbaren Objekt ein Array zu machen, ist ein Arrayliteral mit spread-Operator:
~~~js
const items = [ ...orderable.querySelectorAll(":scope > [data-order]") ];
~~~
und darauf kann man nun die map-Methode anwenden, um jedes gefundene Element in ein Objekt umzuwandeln, das die order-Nummer und das Element enthält:
~~~js
const items = [ ...orderable.querySelectorAll(":scope > [data-order]") ]
.map(item => ({ order: item.dataset.order, item}));
~~~
Beachte 1: Es ist nicht nötig, die Zwischenergebnisse in Variablen zu speichern. Man kann direkt auf den Funktionsergebnissen weiterarbeiten.
Beachte 2: Das Objektliteral muss eingeklammert werden, sonst denkt die Pfeilfunktion, das sei ein Statement-Block.
DAS kann man nun mit der sort-Methode nach der order sortieren. Dafür braucht man sort mit Vergleichs-Callback. Ich **könnte** einfach `a.order - b.order` rechnen, aber das setzt voraus, dass data-order immer korrekt numerisch gefüllt ist. Mit einem expliziten Vergleich ist das Ergebnis typsicherer:
~~~js
const items = [ ...orderable.querySelectorAll(":scope > [data-order]") ]
.map(item => ({ order: item.dataset.order, item}))
.sort( (a,b) => a.order > b.order
? 1
: (a.order < b.order ? -1 : 0) );
~~~
Sort liefert das sortierte Array zurück, d.h. wir können dieses Ergebnis nun durchlaufen. Die items-Variable brauchen wir nicht mehr…
~~~js
for (const orderable of document.querySelectorAll(".orderable.itemlist")) {
for (const sortedRef of
[...orderable.querySelectorAll(":scope > [data-order]")]
.map(item => ({ order: item.dataset.order, item}))
.sort( (a,b) => a.order > b.order ? 1 : (a.order < b.order ? -1 : 0) )) {
orderable.append(sortedRef.item)
}
}
~~~
_Rolf_
--
sumpsi - posui - obstruxi
css flex inline
bearbeitet vonHallo ich,
ein Flexitem erzeugt einen eigenen Blockformatierungskontext und DESHALB geht das nicht.
Ausnahme: Das Flexitem ist selbst wieder ein Flex-Container. Dann erzeugt es einen Flexformatierungskontext. Aber der bricht auch nicht um.
Test:
~~~html
<div class="flex">
<div>Das ist das erste Flexitem, nur für mich</div>
<div><span>Das ist das</span><span>zweite Flexitem,</span><span>nur für dich</span></div>
</div>
~~~
~~~css
.flex {
display: inline-flex;
flex-flow: row wrap;
}
.flex div {
display: inline-flex;
flex-flow: row wrap;
gap: 0.25em;
}
~~~
bricht das zweite div trotzdem vollständig um.
Da die Anordnung mit `order` unzugänglich ist (ein Screenreader oder die Tab-Reihenfolge achten nicht auf order), würde ich Dir empfehlen, die Items im DOM mit JavaScript umzusortieren. Das ist etwas schwieriger, dürfte aber die wenigsten Probleme machen.
Beispiel:
~~~html
<div class="orderable itemlist">
<div data-order="2">Das ist das erste Flexitem, nur für mich. </div>
<div data-order="4">Das ist das zweite Flexitem, nur für dich. </div>
<div data-order="1">Das ist das dritte Flexitem, für ihn, sie und them. </div>
<div data-order="3">Das ist das vierte Flexitem, für die ganze Welt. </div>
<div data-order="1">Das ist das fünfte Flexitem, für ihn, sie und them. </div>
</div>
~~~
Ich verwende data-order, weil es kein order-Attribut gibt, das ist CSS, und es wäre Quatsch (find ich), für jedes Element erstmal die CSS-Eigenschaften einzusammeln (mit window.getComputedStyle(elem) oder elem.computedStyleMap()).
Man iteriert nun über alle Elemente mit den Klassen orderable und itemlist (fühle Dich frei, die zu sortierenden Container anders zu identifizieren) und sortiert die Kindelemente der gefundenen Container um.
Dieses Iterieren kann man so formulieren:
~~~js
const orderables = document.querySelectorAll(".orderable.itemlist");
for (const orderable of orderables) {
...
}
~~~
oder kompakter so:
~~~js
for (const orderable of document.querySelectorAll(".orderable.itemlist")) {
...
}
~~~
Felix würde jetzt sagen: dafür nimmt man die forEach-Methode. Ich nicht, das ist aus meiner Sicht veraltet, ich bevorzuge bei iterierbaren Sammlungen die for...of Schleife.
Im Inneren der Schleife muss man jetzt die Kindelemente mit data-order Attribut einsammeln. Das geht geschickt mit einem :scope-Selektor und dem Kind-Kombinator für querySelectorAll:
~~~js
items = orderable.querySelectorAll(":scope > [data-order]")
~~~
Das Ergebnis ist eine Nodelist. Zum Sortieren braucht man aber ein Array, und zum einfacheren Sortieren ein Array, das den data-order-Wert direkt enthält. Die moderne Methode, aus einem iterierbaren Objekt ein Array zu machen, ist ein Arrayliteral mit spread-Operator:
~~~js
const items = [ ...orderable.querySelectorAll(":scope > [data-order]") ];
~~~
und darauf kann man nun die map-Methode anwenden, um jedes gefundene Element in ein Objekt umzuwandeln, das die order-Nummer und das Element enthält:
~~~js
const items = [ ...orderable.querySelectorAll(":scope > [data-order]") ]
.map(item => ({ order: item.dataset.order, item}));
~~~
Beachte: Es ist nicht nötig, die Zwischenergebnisse in Variablen zu speichern. Man kann direkt auf den Funktionsergebnissen weiterarbeiten.
DAS kann man nun mit der sort-Methode nach der order sortieren. Dafür braucht man sort mit Vergleichs-Callback. Ich **könnte** einfach `a.order - b.order` rechnen, aber das setzt voraus, dass data-order immer korrekt numerisch gefüllt ist. Mit einem expliziten Vergleich ist das Ergebnis typsicherer:
~~~js
const items = [ ...orderable.querySelectorAll(":scope > [data-order]") ]
.map(item => ({ order: item.dataset.order, item}))
.sort( (a,b) => a.order > b.order
? 1
: (a.order < b.order ? -1 : 0) );
~~~
Sort liefert das sortierte Array zurück, d.h. wir können dieses Ergebnis nun durchlaufen. Die items-Variable brauchen wir nicht mehr…
~~~js
for (const orderable of document.querySelectorAll(".orderable.itemlist")) {
for (const sortedRef of
[...orderable.querySelectorAll(":scope > [data-order]")]
.map(item => ({ order: item.dataset.order, item}))
.sort( (a,b) => a.order > b.order ? 1 : (a.order < b.order ? -1 : 0) )) {
orderable.append(sortedRef.item)
}
}
~~~
_Rolf_
--
sumpsi - posui - obstruxi