CSS table, WebKit, Blink e il pixel mancante a larghezza 100%

Dice il saggio:

Se non hai mai provato a centrare verticalmente un testo, non sai nulla di CSS

Le CSS table sono lo strumento principale che i browser, da IE8 compreso in su, ci mettono a disposizione per effettuare operazioni tipografiche fondamentali come centrare verticalmente un testo all’interno di un contenitore, senza sapere ne l’altezza del contenitore ne l’ingombro del testo in termini di grandezza e numero di righe, senza di esse la proprietà  vertical-align:middle è praticamente carta straccia.

Un tipico esempio è la didascalia all’interno di una immagine, che tramite CSS table si riesce ad impostare in modo che quando il testo è su una singola riga o più righe ma comunque di grandezza inferiore al contenitore resta centrato, altrimenti il contenitore cresce in altezza rispetto al testo stesso.

In questo caso l’effetto che si desidera ottenere è che il contenitore della didascalia copra in larghezza il contenitore padre, motivo per cui si applica la proprietà width:100%, e fintanto che la dimensione del contenitore padre resta fissa tutto funziona come da programma.

1px bug

I problemi sorgono sui browser basati su WebKit e Blink, ovvero su tutte le versioni desktop e mobile di Chrome, Safari ed Opera.
Se la dimensione del contenitore padre è a sua volta variabile, ovvero impostata con un’unità di misura percentuale, si noterà uno strano effetto: ridimensionando l’elemento padre, il figlio con display di tipo table con larghezza 100% non si sovrapporrà perfettamente al padre in tutti gli stadi del ridimensionamento, si noterà invece una sorta di sfarfallio di 1px, sul lato destro o sinistro dell’elemento a seconda del tipo di positionfloat applicato.

Nel caso della demo precedente, aggiungendo un’animazione si coglie meglio il problema, se l’elemento è in position:relative e si applica  un float:right si può osservare lo sfarfallamento sul lato sinistro, si nota inoltre come il testo “tremi” durante l’animazione a causa della dimensione del box che non viene calcolata correttamente:

Il bug è illustrato anche nella seguente GIF mentre si manifesta sul lato destro, in rosso sono evidenziati gli elementi a cui sono applicati valori display di tipo table,  se l’elemento è in position:absolute il flickering avverrà sempre sul lato destro dell’elemento anche  se si applica un float:right, comportamento osservato in Chrome Mac Versione 39.0.2171.95 (64-bit):

css-table-width

Di seguito la demo da cui è tratta la GIF precedente, in cui sono testati tutti i tipi di display, applicando larghezza 100% ed un’animazione al contenitore padre di tutti gli elementi, si nota anche come tutti gli elementi con display appartenente alla categoria table ma che non osservano affatto la proprietà  width:100%, quando il padre si restringe abbastanza da costringerli ad adattarsi in larghezza manifestano lo stesso comportamento dei valori table e inline-table:

Workaround

Ci sono due possibili porkaround workaround per questo bug che vanno valutati in base alle necessità contingenti:

  1. Assegnare anche al contenitore il  display di tipo table, così che adottando lo stesso algoritmo di calcolo della larghezza il bug non sia individuabile.
  2. Annidare l’elemento con display:table dentro un altro elemento con display di qualunque altro tipo che può osservare correttamente la proprietà  width:100%.

Il primo metodo evita di introdurre HTML aggiuntivo e “risolve” con una sola dichiarazione CSS in più, tuttavia se l’elemento in questione fa parte ad esempio di una colonna con altri elementi che hanno tutti la stessa larghezza rischia di spostare il bug piuttosto che risolverlo, permette tuttavia di applicare la proprietà min-height direttamente sull’elemento  table in modo tale che l’altezza resti dinamica, permettendo una migliore gestione dei casi limite.

Il secondo metodo ha l’effetto indesiderato di aggiungere un ulteriore elemento HTML “superfluo”, ed in più sarà necessario applicargli una  height esplicita affinchè il contenitore table si espanda in altezza al 100% permettendo quindi di centrare il suo contenuto, tuttavia questo comporta che qualora il contenuto ecceda lo spazio disponibile il contenitore esterno non si espanderà per accoglierlo ed entreranno in gioco le direttive della proprietà  overflow.

Questo bug si manifesta all’occhio solo nei casi in cui l’elemento  table che viene ridimensionato espone un colore di sfondo o dei bordi, quindi se non si usano questi attributi visivi si può fare a meno di applicare una fix. Nessuna delle due soluzioni è ottimale per ogni casistica, andrà quindi valutato il male minore caso per caso, non è bellissimo ma “Bisogna fare quello che bisogna fare“.

Bugzillas

Nella speranza che questo baco fastidioso venga prima o poi risolto ho aperto un issue su bugzilla rispettivamente per WebKit e Blink, se gli issue verranno arricchiti da ulteriori segnalazioni la probabilità che qualcuno li prenda in carico e li risolva una volta per tutte sarà più alta, si spera contemporaneamente (W i fork!).

https://sresc.io/5TM

1 thoughts on “CSS table, WebKit, Blink e il pixel mancante a larghezza 100%”

Lascia un commento

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.