Een alternatief voorstel voor CSS-metselwerk

Het Chrome-team wil graag een implementatie van metselwerklay-outs op internet zien. We zijn echter van mening dat het implementeren ervan als onderdeel van de CSS Grid-specificatie, zoals voorgesteld in het recente WebKit-bericht, een vergissing zou zijn. We zijn ook van mening dat de WebKit-post pleitte tegen een versie van metselwerk die niemand voorstelde.

Daarom is dit bericht bedoeld om uit te leggen waarom wij bij Chrome zorgen hebben over het implementeren van metselwerk als onderdeel van de CSS Grid Layout-specificatie, en om precies te verduidelijken wat het alternatieve voorstel mogelijk maakt. In het kort:

  • Het Chrome-team wil heel graag metselwerk deblokkeren, we weten dat ontwikkelaars dit willen.
  • Het toevoegen van metselwerk aan de rasterspecificatie is problematisch om andere redenen dan of u denkt dat metselwerk een raster is of niet.
  • Het definiëren van metselwerk buiten de rasterspecificatie verhindert niet dat er meerdere spoorgroottes voor metselwerk zijn, of dat eigenschappen zoals uitlijning of openingen worden gebruikt, of andere kenmerken die in de rasterindeling worden gebruikt.

Moet metselwerk deel uitmaken van het raster?

Het Chrome-team is van mening dat metselwerk een aparte opmaakmethode moet zijn, gedefinieerd met behulp van display: masonry (of een ander trefwoord als er een betere naam wordt gekozen). Verderop in dit bericht kun je enkele voorbeelden zien van hoe dat er in code uit zou kunnen zien.

Er zijn twee verwante redenen waarom we van mening zijn dat metselwerk beter gedefinieerd kan worden buiten de rasteropmaak: het potentieel voor problemen met de prestatie van de layout, en het feit dat zowel het metselwerk als het raster eigenschappen hebben die zinvol zijn in de ene layoutmethode, maar niet in de andere.

Prestatie

Raster en metselwerk zijn tegengesteld in de manier waarop de browser omgaat met afmetingen en plaatsing. Wanneer een raster is opgemaakt, worden alle items vóór de lay-out geplaatst en weet de browser precies wat er in elke track staat. Dit maakt de complexe intrinsieke afmetingen mogelijk die zo nuttig zijn in rasters. Bij metselwerk worden de items geplaatst zoals ze zijn ingedeeld, en weet de browser niet hoeveel er in elke track staan. Dit is geen probleem bij alle tracks met een intrinsiek formaat of bij alle tracks met een vast formaat, maar wel als je vaste en intrinsieke tracks mixt. Om dit probleem te omzeilen, moet de browser een pre-lay-outstap uitvoeren waarbij elk item op elke mogelijke manier wordt ingedeeld om metingen te verkrijgen. Met een groot raster zou dit bijdragen aan problemen met de lay-outprestaties.

Daarom, als je een metselwerklay-out hebt met een trackdefinitie van grid-template-columns: 200px auto 200px - wat heel gebruikelijk is om in raster te doen - begin je problemen tegen te komen. Deze problemen worden exponentieel zodra u subrasters toevoegt .

Er is een argument dat de meeste mensen hier niet mee te maken zullen krijgen, maar we weten al dat mensen zeer grote netwerken hebben . We willen niet iets op de markt brengen dat beperkingen kent aan de manier waarop het kan worden gebruikt, als er een alternatieve aanpak is.

Wat doen we met de dingen die niet logisch zijn in elke lay-outmethode?

Toen flexbox en grid onderdeel werden van CSS, hadden ontwikkelaars vaak het gevoel dat ze zich inconsistent gedroegen. De inconsistentie die ze ervoeren kwam voort uit lang gekoesterde aannames over hoe de lay-out werkte, gebaseerd op de bloklay-out. In de loop van de tijd zijn ontwikkelaars inzicht gaan krijgen in de opmaakcontexten. Wanneer we overschakelen naar een raster- of flex-opmaakcontext, gedragen sommige dingen zich anders. U weet bijvoorbeeld dat wanneer u zich in flexbox bevindt, niet alle uitlijningsmethoden beschikbaar zijn, omdat flexbox eendimensionaal is.

Het bundelen van metselwerk in een raster verbreekt deze duidelijke link tussen de opmaakcontext en de beschikbaarheid van zaken als uitlijningseigenschappen, die zijn gedefinieerd in de Box Alignment-specificatie per opmaakcontext.

Als we besluiten om het eerder geschetste prestatieprobleem aan te pakken door gemengde intrinsieke en vaste spoordefinities illegaal te maken in metselwerk, dan zul je moeten onthouden dat een veel voorkomend patroon voor rasterindelingen niet werkt voor metselwerk.

Er zijn ook patronen die zinvol zouden zijn in metselwerk, bijvoorbeeld grid-template-columns: repeat(auto-fill, max-content) , omdat je geen kruisbeperkingen hebt, maar ongeldig moet blijven in grid. Het volgende is een lijst met eigenschappen waarvan we verwachten dat ze zich anders gedragen of verschillende geldige waarden hebben.

  • grid-template-areas : In metselwerk kunt u alleen de eerste rij in de niet-metselwerkrichting opgeven.
  • grid-template : De afkorting zou rekening moeten houden met alle verschillen.
  • Volg de groottewaarden voor grid-template-columns en grid-template-rows vanwege verschillen in wettelijke waarden.
  • grid-auto-flow is niet van toepassing op metselwerk en masonry-auto-flow is niet van toepassing op grid. Het samenvoegen ervan zou problemen veroorzaken met dingen die ongeldig zijn vanwege de lay-outmethode waarin u zich bevindt.
  • Raster heeft vier plaatsingseigenschappen ( grid-column-start enzovoort), metselwerk heeft er maar twee.
  • Grid kan alle zes de justify-* en align-* eigenschappen gebruiken, maar Masonry gebruikt slechts een subset zoals flexbox.

Er zal ook een vereiste zijn om te specificeren wat er gebeurt in alle nieuwe foutgevallen die worden veroorzaakt doordat ontwikkelaars een waarde gebruiken die niet geldig is in raster-met-metselwerk of raster-zonder-metselwerk. Het is bijvoorbeeld geldig om grid-template-columns: masonry of grid-template-rows: masonry te gebruiken, maar niet beide tegelijk. Wat gebeurt er als je beide tegelijk gebruikt? Deze details moeten worden gespecificeerd zodat alle browsers hetzelfde doen.

Vanuit specificatieoogpunt wordt dit allemaal ingewikkeld, nu en in de toekomst. We zullen ervoor moeten zorgen dat alles rekening houdt met metselwerk, en of het wel of niet werkt in metselwerk. Het is ook verwarrend vanuit het oogpunt van ontwikkelaars. Waarom zou je in je hoofd moeten houden dat ondanks het gebruik van display: grid sommige dingen niet werken vanwege het gebruik van metselwerk?

Een alternatief voorstel

Zoals eerder vermeld wil het Chrome-team metselwerk definiëren buiten de rasterspecificatie. Dit betekent niet dat het beperkt zou blijven tot een zeer eenvoudige lay-outmethode met identieke kolomgroottes. Alle demo's in de WebKit-post zouden nog steeds mogelijk zijn.

Klassieke metselwerkindeling

Wanneer de meeste mensen aan metselwerk denken, denken ze aan een indeling met meerdere kolommen van gelijke grootte. Dit zou worden gedefinieerd met behulp van de volgende CSS, die een regel minder code nodig heeft dan de equivalente rastergebundelde versie .

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, minmax(14rem, 1fr));
  gap: 1rem;
}

Sporen van gelijke grootte.

Gebruik de spoorgrootte van het rastertype voor verschillende kolombreedtes

Afgezien van het eerder genoemde probleem met gemengde intrinsieke en vaste spoorgroottes, zou u alle spoorgroottes kunnen gebruiken waar u van houdt op het raster. Zoals het voorbeeld uit de WebKit-blogpost , een patroon van herhalende smalle en bredere kolommen.

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, minmax(8rem, 1fr) minmax(16rem, 2fr)) minmax(8rem, 1fr);
  gap: 1rem;
}

Een patroon van brede en smalle sporen.

Extra spoorafmetingen voor metselwerk

Er zijn aanvullende opties voor de spoorgrootte die we in raster niet toestaan, omdat raster een tweedimensionale lay-outmethode is. Deze zouden nuttig zijn in metselwerk, maar het zou verwarrend zijn als ze dan niet in een raster zouden werken.

Automatisch vullende tracks met max-content .

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, max-content);
  gap: 1rem;
}

Automatisch vullende nummers met auto formaat, waardoor nummers van hetzelfde formaat worden gemaakt, automatisch aangepast om de grootste te kunnen bevatten.

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, auto);
  gap: 1rem;
}

Metselwerk met automatische rupsbanden.

Zorg ervoor dat de inhoud kolommen overspant en plaats items op de metselwerklay-out

Er is geen reden om inhoud die kolommen beslaat niet in een afzonderlijke metselwerkspecificatie op te nemen. Hierbij kan gebruik worden gemaakt van de eigenschap masonry-track , wat een afkorting is voor masonry-track-start en masonry-track-end omdat u in een metselwerkindeling slechts één dimensie heeft om dingen te overspannen.

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, auto);
}

.span-2 {
  masonry-track: span 2; /* spans two columns */
}

.placed {
  masonry-track: 2 / 5; /* covers tracks 2, 3, and 4 */
}

Metselwerk met geplaatste en overspannende elementen.

Ondermetselwerk of subraster met metselsporen

Dit zou kunnen worden ondersteund met een afzonderlijke metselspecificatie, opnieuw met de voorwaarde dat gemengde sporen met intrinsieke en vaste afmetingen niet zijn toegestaan. Hoe dat er precies uitziet, zal moeten worden gedefinieerd. Wij zien geen reden waarom dit niet zou werken.

Conclusie

We zouden graag tot een punt komen van een specificatie die interoperabel kan worden verzonden. Wij willen dat echter doen op een manier die nu en in de toekomst goed werkt en waar ontwikkelaars op kunnen vertrouwen. De enige manier om met de geschetste prestatieproblemen om te gaan, zou zijn om het tweede probleem – dat van het feit dat delen van het raster illegaal zijn in metselwerk – erger te maken. Wij denken niet dat dit een goede oplossing is, vooral als het mogelijk is om over alle gewenste rasterfuncties te beschikken, terwijl de verschillende zaken duidelijk gescheiden blijven.

Als u feedback heeft, neem dan deel aan de discussie in nummer 9041 .

Met dank aan Bramus, Tab Atkins-Bittner, Una Kravets, Ian Kilpatrick en Chris Harrelson voor de beoordeling van dit bericht en de discussies die eraan ten grondslag lagen.