- 1 Concetti di base
- 2 Flexbox
- 3 Griglia e sottogriglia
- 4 Query container
- 5 Overlay nativi, posizionamento degli ancoraggi e contesti di impilamento
- 6 Monitoraggio dell'overflow e stabilità del layout
- 7 Meccanica della finestra visibile e distribuzione delle tracce
- 8 corsie della griglia (ovvero layout a griglia)
1 Fundamentals
Quando possibile, utilizza il motore di layout del browser per migliorare le prestazioni. Utilizza il dimensionamento intrinseco, le proprietà logiche e aspect-ratio prima di ricorrere a dimensioni impostate come hardcoded o a query supporti complicate.
1.1 Quale modalità di layout utilizzare?
Esamina l'albero decisionale dall'alto verso il basso e fermati alla prima corrispondenza. Tieni presente che i layout possono essere nidificati l'uno nell'altro e ogni decisione si basa sul caso d'uso di quel container.
- Si tratta di una semplice riga O colonna di elementi? Utilizza flexbox: 1D, incentrato sui contenuti, i contenuti vengono distribuiti lungo un singolo asse.
- Un elemento nidificato deve essere allineato alle tracce della griglia principale? Utilizza subgrid: 2D, incentrato sulle relazioni, eredita le tracce principali in modo che i nipoti possano allinearsi tra i fratelli.
- Si tratta di una pagina o di una struttura di componenti complessa con righe E colonne? Utilizza grid: 2D, basato sul layout, definisci lo scheletro e i contenuti lo riempiono.
- I contenuti sono un lungo flusso di prosa che dovrebbe essere suddiviso in colonne bilanciate? Utilizza più colonne: flusso 1D, stile giornale.
- Gli articoli hanno altezze diverse e devono essere imballati in modo compatto? Utilizza grid con
grid-auto-flow: denseoggi; utilizza il layout a griglia nativo (noto anche come "corsie della griglia") solo quando viene fornito nel tuo target Baseline (vedi §8). - Un elemento deve fluttuare sopra la pagina e rimanere legato spazialmente a un trigger, anche attraverso i confini del DOM o i contesti di impilamento? Utilizza il posizionamento di ancoraggio:
anchor-namesull'attivatore,position-anchorsull'overlay (vedi §5).
1.2 Principi di funzionamento
- Utilizza le proprietà logiche (
inline-size,block-size,margin-inline,padding-block,inset-inline-start) per le dimensioni e la spaziatura del layout. Per una copertura completa, consulta CSS: Modern Architecture. - Applica il modello mentale "prima i contenuti" rispetto a "prima il layout": flexbox quando gli elementi determinano il flusso, griglia quando definisci prima lo scheletro.
- Utilizza le abbreviazioni
place-*(place-content,place-items,place-self) per l'allineamento su entrambi gli assi in un'unica dichiarazione. - Utilizza il dimensionamento intrinseco (
min-content,max-content,fit-content()) e le tracce flessibili (fr,minmax()) prima diwidth/heightfisse: meno query supporti, layout più resilienti. - NON utilizzare
overflow: hiddenper mascherare i problemi di layout, ma risolvili alla fonte. Ad esempio, alcuni elementi sostituiti come<canvas>,<img>,<svg>,<video>,<iframe>utilizzanodisplay: inlineper impostazione predefinita, il che può aggiungere uno spazio in alcuni layout. Anziché ritagliare lo spazio conoverflow, rimuovilo applicando un valore display-outside di blocco (ad es.display: block,grid,flexe così via). - Utilizza
aspect-ratioper riservare spazio ai contenuti multimediali e impedire la variazione del layout prima del caricamento degli asset.
.sidebar { inline-size: max-content; } /* Size to longest unbreakable token. */
.main-content { inline-size: fit-content; } /* Grow to available space, no further. */
.media { aspect-ratio: 16 / 9; inline-size: 100%; block-size: auto; }
body.centered { display: grid; place-content: center; min-block-size: 100dvb; }
Per
calc-size()e il dimensionamento intrinseco basato sui vincoli, consulta Calcola con dimensioni intrinseche.
2 Flexbox
Layout monodimensionale: gli elementi scorrono lungo un unico asse principale con allineamento sull'asse incrociato. Utilizzalo per barre di navigazione, barre degli strumenti, righe di elementi e qualsiasi distribuzione di singole righe o colonne.
Cosa fare:
- Stabilisci un contesto con
display: flexe imposta l'asse principale conflex-direction(rowpredefinito). - Utilizza
flex-wrap: wrapogni volta che è possibile un overflow:nowrapsenzaoverflow: auto/hiddensi riverserà su viewport stretti. - Applica
flex-wrap: balancedopoflex-wrap: wrapsulle righe con ritorno a capo di elementi compatti (come tag cloud, pillole di filtro, gruppi di pulsanti o link di navigazione) per distribuire gli elementi in modo uniforme tra le righe ed evitare un singolo elemento orfano nell'ultima riga; i browser senza supporto eseguono il fallback awrap. - Utilizza la sintassi abbreviata
flex<grow> <shrink> <basis>(ad es.flex: 1 1 250px) sugli elementi anziché impostareflex-grow/flex-shrink/flex-basissingolarmente. - Utilizza
gap(o la forma estesarow-gap/column-gap) per la spaziatura tra gli elementi anziché i margini secondari. - Aggiungi il prefisso di allineamento posizionale con
safe(ad es.align-items: safe center) in modo che i contenuti attivabili non vengano ritagliati quando il container è più stretto dei contenuti. - Spingi un singolo elemento all'estremità dell'asse principale con
margin-inline-start: auto(omargin-block-start: auto): questa è la soluzione standard. - Esegui l'override dell'allineamento trasversale per elemento con
align-self. - Utilizza
align-itemsper centrare tutti gli elementi sull'asse trasversale; utilizzamargin: autosu un singolo elemento per centrarlo su entrambi gli assi in modo indipendente; utilizzaalign-contentsolo quando il contenitore va a capo e ha spazio aggiuntivo tra le righe. - Imposta
min-inline-size: 0(omin-width: 0) sugli elementi flessibili che contengono contenuti lunghi non separabili (URL, codice, stringhe lunghe). Per impostazione predefinita, gli elementi flessibili non si riducono al di sotto delle dimensioni dei contenuti, causando un overflow.
Cosa non fare:
- Non utilizzare
justify-selfsugli elementi flessibili: funziona solo su layout a griglia, a blocchi e con posizionamento assoluto. Utilizza invece i margini automatici. - Non utilizzare
orderoflex-direction: *-reverseper riordinare i contenuti interattivi. Modificano solo l'ordine visivo; l'ordine DOM determina comunque lo stato attivo sequenziale, quindi il flusso di tabulazione della tastiera non corrisponderà a ciò che l'utente vede. - Non confondere
space-around(metà spazio alle estremità) conspace-evenly(spazi uguali prima, tra e dopo). - Non dimenticare l'inversione degli assi: quando
flex-direction: column,justify-contentsi allinea sull'asse del blocco ealign-itemssi allinea sull'asse in linea, l'opposto del valore predefinito. - Non dimensionare sia il contenitore che i relativi elementi secondari in modo che si riempiano a vicenda: questa è una causa comune di overflow e risultati imprevisti. Assegna a un lato una dimensione definita.
- Non impostare sia
flex-basissiawidth/inline-sizesullo stesso elemento:flex-basisha la precedenza in un contesto flessibile ewidthviene ignorato. Utilizzaflex-basis(o la forma abbreviataflex) come unica fonte di dati per il dimensionamento degli elementi flessibili.
.card-grid { display: flex; flex-flow: row wrap; gap: 1rem; }
.card-item { flex: 1 1 250px; } /* grow, shrink, basis */
.card-item-action { margin-inline-start: auto; } /* Push to main-axis end. */
.toolbar { display: flex; align-items: safe center; }
.tag-list { display: flex; flex-wrap: wrap; flex-wrap: balance; gap: 0.5rem; }
3 Griglia e sottogriglia
Layout bidimensionale: definisci righe E colonne in modo esplicito o lascia che il motore le ricavi. Subgrid consente a una griglia nidificata di ereditare le tracce della griglia principale, in modo che gli elementi secondari si allineino tra gli elementi di pari livello.
Scelta delle caratteristiche della griglia:
- Sai esattamente di quante colonne hai bisogno?
- Sì: utilizza canali espliciti (
grid-template-columns: 200px 1fr,repeat(3, 1fr)e così via) - Le diverse colonne richiedono dimensioni diverse (barra laterale + principale, intestazione che si estende su tutte)? → utilizza
grid-template-areasper le regioni denominate e leggibili - Tutte le colonne sono uniformi o posizionate esclusivamente in base al numero di riga? → utilizza
repeat(N, ...)o linee con nome - No (responsive, numero di elementi sconosciuto): utilizza
repeat(auto-fit, minmax(min, 1fr)) - Gli elementi dell'ultima riga devono essere estesi per riempire lo spazio rimanente? →
auto-fit - Le tracce vuote dell'ultima riga devono mantenere le dimensioni minime (preservando gli slot fantasma delle colonne)? →
auto-fill
- Sì: utilizza canali espliciti (
- Devi posizionare un elemento in una posizione specifica?
- Sì: utilizza
grid-column: <start> / <end>ogrid-area: <name> - No (si estende solo su più tracce, la posizione del flusso non è importante): utilizza
grid-column: span <n>
- Sì: utilizza
- Gli elementi secondari devono ereditare le dimensioni delle tracce della griglia principale (allineamento con bordi irregolari tra elementi di pari livello)?
- Sì: utilizza la griglia secondaria sull'asse interessato
- Il numero di elementi secondari per cella è variabile? → subgrid one axis only; use
grid-auto-rows/grid-auto-columnsfor the other - Il numero di elementi secondari è fisso? → subgrid su entrambi gli assi va bene
- No: griglia standard, non è necessaria una sottogriglia
Cosa fare:
- Stabilisci un contesto con
display: grid. - Utilizza
grid-template-areasper layout complessi a livello di pagina: i nomi delle aree sono autoesplicativi e la dichiarazione può essere allineata in righe e colonne per una leggibilità immediata. - Utilizza
repeat(auto-fit, minmax(200px, 1fr))per griglie di schede adattabili che estendono le tracce riempite per riempire la riga oauto-fillper mantenere le tracce ripetute vuote alla loro dimensione minima. - Utilizza
frper la distribuzione proporzionale delle tracce eminmax(min, max)per le tracce flessibili ma limitate. - Posiziona gli elementi con
grid-column: span <n>per ridimensionarli tra le tracce,grid-column: <start> / <end>per posizionarli in righe specifiche ogrid-area: <name>per le regioni con nome. - Utilizza la griglia secondaria (
grid-template-columns: subgridogrid-template-rows: subgrid) per risolvere il problema del "bordo irregolare" negli elenchi di schede: gli elementi interni come titoli, metadati e CTA si allineano tra gli elementi di pari livello. - Abbina una dichiarazione subgrid a una dichiarazione
grid-template-rows/-columnsesplicita precedente come riserva della stessa struttura a cascata per i browser meno recenti.
Cosa non fare:
- Non aspettarti che le dimensioni della traccia
auto-fit/auto-fillprovengano dai contenuti dell'elemento, ma dall'argomento delle dimensionirepeat(). - Non utilizzare
grid-auto-flow: densesui contenuti interattivi. Dispone gli elementi in modo efficiente, ma li riordina visivamente, interrompendo il flusso di tabulazione della tastiera nell'ordine del DOM. - Non applicare la griglia secondaria a entrambi gli assi quando il numero di elementi secondari è variabile. Gli elementi aggiuntivi vengono inseriti nell'ultima traccia; utilizza invece
grid-auto-rows/grid-auto-columnsper l'asse implicito. - Non confondere
justify-items/align-items(allinea i contenuti degli elementi all'interno della relativa traccia) conjustify-content/align-content(allinea le tracce della griglia all'interno del container). L'utilizzo di quello sbagliato non ha alcun effetto. - Non utilizzare
repeat(auto-fit/auto-fill, ...)senza uninline-sizedefinito sul container. All'interno didisplay: inline-grido di un elemento flessibile non dimensionato, il container non ha una larghezza da dividere, il che rende imprevedibile il numero di tracce.
3.1 Esempio di codice: griglia e sottogriglia
Shell della pagina: <main class="page-layout"> contiene <header>, <aside>, un <section class="card-grid"> con <div class="card"> elementi secondari e <footer>.
/* Align grid-template-areas in rows and columns for readability. */
.page-layout {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-areas:
"header header header"
"sidebar main main"
"footer footer footer";
gap: 1.5rem;
}
header { grid-area: header; }
aside { grid-area: sidebar; }
footer { grid-area: footer; }
.card-grid {
grid-area: main;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
grid-template-rows: auto 1fr; /* title block, body block */
gap: 1rem;
}
.card {
grid-row: span 2;
display: grid;
/* Same-cascade fallback: ignored when subgrid is supported. */
grid-template-rows: auto 1fr;
grid-template-rows: subgrid;
}
4 Query container
Eseguire query sulle dimensioni (o sullo stile calcolato) di un contenitore predecessore anziché dell'area visibile. Modello mentale: query contenitore = contesto del componente; query supporti = layout di pagina globale e preferenze dell'utente (prefers-color-scheme, prefers-reduced-motion).
Cosa fare:
- Stabilisci un contesto di contenimento con
container-type: inline-size(query solo sulla larghezza) ocontainer-type: size(entrambi gli assi) su un wrapper prima che i relativi discendenti possano essere interrogati. - Assegna un nome ai container con
container-name(o la forma abbreviata dicontainer:container: card / inline-size) quando i contesti nidificati potrebbero entrare in conflitto. - Includi le unità di query container nel calcolo del tipo e della spaziatura fluidi:
cqi/cqb(inline/blocco logico),cqw/cqh(fisico),cqmin/cqmax. - Assegna al container un
block-sizedefinito ogni volta che viene utilizzatocontainer-type: size. In caso contrario, gli elementi discendenti vengono compressi perché il contenimento delle dimensioni forza il container a ignorare i suoi contenuti.
Cosa non fare:
- Non utilizzare
block-sizecome valorecontainer-type, perché non è valido. Utilizzasizeper entrambi gli assi. - Non aspettarti che le dimensioni intrinseche degli elementi secondari influenzino il contenitore dopo aver dichiarato
container-type. Una volta attivato il contenimento, il container viene calcolato come se non avesse elementi secondari. - Non fare affidamento sulle unità di query container all'interno dei discendenti di un predecessore non idoneo; viene eseguito il fallback all'area visibile piccola (
svw/svh).
4.1 Esempio di codice: tipografia fluida che utilizza unità di query container
.card-wrapper {
container: card / inline-size; /* shorthand for container-name / container-type */
}
@container card (inline-size > 400px) {
.content {
display: flex;
gap: 2rem;
}
}
.title {
/* Fluid type bound to the container width, not the viewport. */
font-size: clamp(1rem, 4cqi, 2rem);
}
Per i pattern di stile adattabile basati sui componenti, consulta Stile basato sulle dimensioni e Scalabilità fluida.
5 Overlay nativi, posizionamento degli ancoraggi e contesti di impilamento
Quando utilizzare ciascuna primitiva di overlay:
- Utilizza
popoverper UI temporanee e non modali (flyout, toast, tooltip): si trova nel livello superiore, non è necessaria la gestione diz-index. - Utilizza
<dialog>con.showModal()per le interazioni modali che richiedono il blocco dello stato attivo e uno sfondo inerte. - Non combinare
popovere.showModal()sullo stesso elemento: sono stati di runtime che si escludono a vicenda.
Posizionamento dell'ancoraggio (layout spaziale degli overlay):
- Utilizza
position-area(oanchor()per gli inserti) eanchor-size()per posizionare e ridimensionare un overlay rispetto al relativo trigger. - Utilizza
position-try-fallbacks: flip-block(oflip-inline) per consentire al browser di riposizionare l'overlay quando supera l'area visibile. - Non combinare parole chiave fisiche e logiche in un unico valore
position-area: scegli un sistema di coordinate. - Rileva le funzionalità con
@supports (anchor-name: --x)e fornisci un'alternativa con posizione assoluta.
Per i dettagli completi sull'implementazione, le strategie di polyfill e il riferimento al valore
popover, consulta Controllo dichiarativo di finestre di dialogo e popover e Tooltip sensibili alla posizione. Per il posizionamento degli ancoraggi applicato a menu a discesa, menu espandibili e indicatori di schede, consulta Menu a discesa sensibili alla visualizzazione e Sottolineatura della scheda di posizionamento degli ancoraggi.
6 Monitoraggio dell'overflow e stabilità del layout
Gestisci le variazioni del layout, le barre di scorrimento e il ritaglio in modo prevedibile.
Cosa fare:
- Utilizza
overflow: autoin modo che le barre di scorrimento vengano visualizzate solo quando i contenuti superano effettivamente i limiti. - Utilizza
overflow: clipper ritagliare i contenuti senza stabilire un container di scorrimento; attiva lo spillover conoverflow-clip-margin. - Utilizza
scrollbar-gutter: stableper riservare spazio alle barre di scorrimento e impedire variazioni del layout quando i contenuti aumentano. - Utilizza
overscroll-behavior: contain(onone) nelle regioni di scorrimento nidificate (come barre laterali, finestre modali ed elenchi) per impedire che le catene di scorrimento si propaghino nella pagina, oppureoverscroll-behavior: chainnei wrapper di scorrimento intermedi (come le tracce di scorrimento per mostrare) quando lo scorrimento in eccesso deve propagarsi a uno scroller principale senza attivare un rimbalzo locale. Utilizza la triade
-webkit-line-clamp+display: -webkit-box+-webkit-box-orient: verticalper il troncamento su più righe. Nonostante il prefisso, questo pattern è completamente specificato e non è deprecato. Dichiara la sintassi abbreviataline-clampsenza prefisso insieme a questa; i browser che non la supportano ancora ignorano la proprietà senza problemi. Cosa non fare:Non utilizzare
overflow: scrollquandoautoè sufficiente:scrollforza le barre di scorrimento anche quando non c'è nulla da scorrere.Non utilizzare
overflow: hiddenquando vuoi solo ritagliare:hiddenstabilisce un contenitore di scorrimento che può essere fatto scorrere in modo programmatico.
.scrollable-list {
max-block-size: 400px;
overflow-y: auto;
scrollbar-gutter: stable; /* Reserve scrollbar space. */
overscroll-behavior: contain; /* No scroll chaining into the page. */
}
.snippet {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
line-clamp: 3; /* Ignored where unsupported. */
overflow: clip;
}
Per informazioni dettagliate su
overflow: clipeoverflow-clip-margin, consulta Controllo del ritaglio dell'overflow. Per l'handoff dello scorrimento nidificato conoverscroll-behavior: chainnell'interfaccia utente di scorrimento per mostrare, consulta Scorri per mostrare. Per il colore, le dimensioni e i temi della barra di scorrimento, consulta Personalizza il colore o lo spessore di una barra di scorrimento, Modalità Buio e Adatta la barra di scorrimento alle preferenze di contrasto elevato.
7 Meccanismi della finestra visibile e distribuzione dei canali
- Utilizza
dvh/dvwper i contenitori di layout mobile che devono tenere conto dello spostamento della UI del browser (compressione/espansione della barra degli URL). - Non utilizzare
100vwper il layout a larghezza intera, in quanto ignora la larghezza della barra di scorrimento e causa un overflow orizzontale. Utilizza invece100%,100dvwo100svw.
Per il punto di accesso del responsive design (unità viewport dinamiche, prenotazione di spazio per i contenuti multimediali, tipografia fluida), consulta Responsive design.
8 Corsie della griglia (ovvero masonry)
La specifica è in fase di sviluppo con il nome "grid lanes" (ad es. display: grid-lanes), mentre i prototipi sperimentali precedenti utilizzavano grid-template-rows: masonry.
Cosa fare:
- Utilizza la griglia con
grid-auto-flow: denseper un posizionamento compatto oggi, accettando che l'ordine DOM potrebbe non corrispondere all'ordine visivo. - Utilizza il layout a più colonne (
columns: 3; column-gap: 1rem) per un flusso simile a una griglia con molti contenuti quando gli elementi sono frammenti di documenti anziché schede di pari importanza. - Considera
grid-template-rows: masonrysolo come un potenziamento progressivo: esegui il rilevamento delle funzionalità con@supports.
Cosa non fare:
- Non lanciare
grid-template-rows: masonrycome requisito obbligatorio finché il tuo target Baseline non si aggiorna.
.gallery { columns: 3 200px; column-gap: 1rem; }
.gallery > * { break-inside: avoid; margin-block-end: 1rem; }
@supports (grid-template-rows: masonry) {
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-template-rows: masonry;
gap: 1rem;
columns: unset;
}
}