Vai al contenuto
OneKitly

Costruire una tabella Markdown da zero, senza contare i trattini a mano

Pubblicato il 30/07/2026 · 13 min di lettura · Strumenti per sviluppatori

Daniel Okonkwo

Daniel OkonkwoSviluppatore front-end e redattore Tech presso OneKitly

Performance web · Formati di file

Verificato su 4 fonti

Vedi il profilo
In breve

La tabella Markdown minima valida sono due righe, non tre: una riga di intestazione e una riga delimitatrice sotto. | Nome | Ruolo | seguito da | --- | --- | è una tabella GitHub completa e valida, con intestazione e senza corpo: la specifica lo dice esplicitamente, e l'HTML prodotto semplicemente non ha tbody. Ciò che non puoi fare è omettere la riga delimitatrice. Una riga di intestazione da sola è un paragrafo con delle barre dentro, e comparirà come testo letterale. Quella fila non è ornamento né zucchero d'allineamento: in GitHub Flavored Markdown è il segnale che trasforma un paragrafo ordinario in una tabella, ed è per questo che qui è obbligatoria mentre motori con un'altra sintassi di tabelle non ne hanno bisogno. Ne discendono due regole. La riga delimitatrice deve avere esattamente tante celle quante l'intestazione, o la tabella non viene riconosciuta affatto. E ogni altra riga può avere un numero qualsiasi di celle: se sono poche vengono inserite celle vuote, se sono troppe l'eccesso viene scartato. Le barre iniziali e finali sono facoltative — la specifica le raccomanda per chiarezza — e gli spazi che allineano le colonne non incidono sull'output in alcun modo. Le tabelle a barre non fanno parte di CommonMark. La specifica centrale, versione 0.31.2, definisce blocchi foglia e blocchi contenitore e non contiene alcun costrutto di tabella; quelle di GitHub sono un'estensione sovrapposta. Una tabella perfetta in una pull request può dunque uscire come testo grezzo in un processore CommonMark rigoroso, e il Markdown originale del 2004 non aveva tabelle neanche lui. Prima di scriverne una, guarda quale motore la leggerà.

La cosa più piccola che sia ancora una tabella sono due righe: una riga di intestazione e una riga delimitatrice. Ecco perché la seconda è obbligatoria in GitHub Flavored Markdown, dove le tabelle a barre non esistono affatto, e che cosa fa un generatore che scrivere a mano non può fare.

La cosa più piccola che sia ancora una tabella

Scrivi una riga nel generatore — Nome,Ruolo — e ne produce due: | Nome | Ruolo | sopra, | --- | --- | sotto. È tutta la tabella. Ha un'intestazione, nessuna riga di dati, ed è valida: la specifica di GitHub Flavored Markdown include un esempio esattamente di questa forma e nota soltanto che nell'HTML non viene generato alcun elemento tbody. Non manca nulla. Se sia utile è un'altra questione, ma la sintassi è completa.

Ora cancella la seconda riga e non hai nulla. Una riga di intestazione da sola è un paragrafo che contiene barre verticali, e ogni motore GFM la stamperà come tale: Nome | Ruolo, in testo, barre comprese. È la causa numero uno del fallimento di una tabella scritta a mano, e la ragione è strutturale e non stilistica. Un analizzatore Markdown decide che cos'è un blocco guardando come comincia. Un cancelletto fa un titolo, un segno di maggiore una citazione, quattro spazi del codice. Un paragrafo con delle barre potrebbe essere qualsiasi cosa: una pipeline di shell, una tavola di verità, un pezzo di prosa sulla probabilità. La riga delimitatrice è l'unica cosa che dice all'analizzatore che quel paragrafo è una tabella, e senza di essa non c'è modo di dedurlo.

Il generatore non può dimenticarla, ed è lì che sta gran parte del valore dell'usarne uno. Costruisce l'intestazione, la riga delimitatrice e ogni riga di dati da un unico conteggio di colonne, quindi le tre non possono mai discordare. Dagli un'intestazione senza corpo ed emette la tabella di due righe. Disattiva l'interruttore «la prima riga è l'intestazione» e si inventa Colonna 1, Colonna 2 e così via, perché la sintassi non ha una forma senza intestazione e inventare nomi è l'unica cosa onesta rimasta. Dagli righe di lunghezza disuguale e le squadra, riempiendo le corte con celle vuote e dicendoti, sopra il risultato, quante righe ha dovuto riempire.

Dove una tabella a barre semplicemente non esiste

Il Markdown come John Gruber lo pubblicò nel 2004 non ha tabelle. Leggi il documento di sintassi originale e ci troverai titoli, citazioni, elenchi, blocchi di codice, linee orizzontali, link, enfasi, immagini e HTML in linea — e niente sulle colonne. Le tabelle non ci sono mai state, e la via d'uscita che il documento offre per tutto ciò che non copre è scrivere HTML grezzo.

CommonMark, lo sforzo di dare a Markdown una specifica non ambigua, non le ha aggiunte. La versione 0.31.2, datata gennaio 2024, definisce blocchi foglia — linee tematiche, titoli, blocchi di codice, blocchi HTML, paragrafi — e blocchi contenitore — citazioni, elementi di elenco, elenchi — e non c'è alcuna sezione sulle tabelle. La specifica stessa riconosce che alcuni dialetti hanno esteso la sintassi originale con convenzioni per note a piè di pagina e tabelle, il che colloca le tabelle nettamente fuori dal nucleo. Quelle di GitHub vivono in un documento separato, la specifica GFM, sotto il titolo Tables (extension).

La conseguenza pratica è che dove la tua tabella si renderizza dipende dalle estensioni che il processore ha attive, e non da Markdown in quanto tale. Un README di repository su GitHub è sicuro. Un generatore di siti statici, una build di documentazione, un client di chat, una casella di commento in un tracker di bug: ognuno è una decisione a sé di chi l'ha assemblato. Se la destinazione conta, la prova da due minuti è incollare lì la tabella minima di due righe e guardare. Se compare come tabella con una riga di intestazione, l'estensione è attiva e il resto funzionerà; se compare come una riga di testo con dei trattini sotto, scrivi l'HTML al suo posto, oppure usa un elenco.

Che cosa conta il generatore e tu no

La riga delimitatrice ha un pavimento di tre caratteri, e non è arbitrario: :-: è la cella più corta che possa ancora portare un marcatore di allineamento a ciascuna estremità. Il generatore applica quel pavimento a ogni colonna, quindi un'intestazione di una lettera esce come | a | sopra | --- |, mai sopra | - |. Calcola inoltre la larghezza di ogni colonna dalla cella più larga di quella colonna, intestazione compresa: l'aritmetica che nessuno vuole fare a mano su una tabella di dodici righe.

La parte interessante è come misura una cella, perché un carattere non è una colonna. Questo generatore conta colonne di visualizzazione, non caratteri: gli ideogrammi 東京 sono due caratteri e ne conta quattro, una é scritta come e più accento combinante sono due caratteri e ne conta uno, un singolo emoji sono due unità UTF-16 e ne conta due. Contare i caratteri è ciò che fa un generatore ingenuo, e storce la sorgente non appena i dati escono dall'alfabeto latino. L'emoji di famiglia è il caso che frega i contatori ingenui: quattro figure saldate da giunzioni a larghezza zero, sette punti di codice, undici unità UTF-16 e un solo glifo largo due colonne. Questo generatore annuncia due, perché una giunzione a larghezza zero non occupa alcuna colonna e toglie la sua al punto di codice che la segue. Nulla di tutto ciò arriva alla tabella renderizzata: il riempimento serve a far quadrare la sorgente in un editor, ed è l'unico posto in cui può essere giusto o sbagliato.

Esiste una modalità compatta che toglie del tutto il riempimento. Con essa la separatrice tiene i suoi tre caratteri — | :-- | :-: | --: | per sinistra, centro e destra — e ogni altra cella è scritta senza alcun riempimento. È l'impostazione che vuoi per una tabella larga in un file versionato, perché una tabella riempita rifà l'intera colonna appena un valore si allunga, e una correzione di una parola diventa un diff che tocca ogni riga.

Modificare una tabella che hai già

Il generatore accetta in ingresso una tabella Markdown già esistente, che è il modo più rapido per aggiungere una colonna o correggere un refuso senza riallineare nulla. Incolla la tabella: il separatore viene rilevato come la barra, le celle vuote iniziali e finali vengono tolte, la fila di trattini viene riconosciuta e scartata, e ciò che resta è la tua griglia. Le barre con escape sopravvivono al viaggio: una cella che dice ps \| grep viene riportata a ps | grep in entrata e riscappata in uscita, quindi la tabella torna identica e non una colonna più larga. Il convertitore CSV di questo sito chiude lo stesso anello dal suo capo: fa l'escape della barra rovesciata prima della barra, così una cella che conteneva già \| sopravvive a una nuova conversione.

Anche l'allineamento sopravvive al viaggio, il che è meno ovvio di quanto sembri, perché la riga che lo trasporta è proprio quella da buttare. Lo strumento legge i due punti sulla riga separatrice prima di filtrarla — :--- a sinistra, ---: a destra, :---: al centro, un --- semplice non dice nulla — e imposta da lì la partenza di ogni colonna. Incolla una tabella la cui regola sia | :--- | ---: | e la colonna di numeri allineata a destra torna allineata a destra. Ciò che imposti a mano continua a vincere: i selettori per colonna e i pulsanti Predefinito, Sinistra, Centro e Destra sopra la tabella scavalcano quanto è stato letto, così puoi cambiare un allineamento apposta. Quello che non puoi più fare è perderne uno per sbaglio.

Ogni parte di una tabella GFM: che cos'è, se è obbligatoria e che cosa succede quando è sbagliata
ParteObbligatoria?Che cosa succede se manca o è sbagliata
Riga di intestazioneNon esiste una forma senza intestazione; il generatore inventa Colonna 1, Colonna 2 invece di ometterla
Riga delimitatrice di trattiniNessuna tabella — l'intestazione appare come paragrafo con delle barre
Numero di celle delimitatrici pari all'intestazioneLa tabella non viene riconosciuta e ricade su testo letterale
Righe di datiNoIntestazione più separatrice è una tabella valida; l'HTML semplicemente non ha tbody
Numero di celle in una riga di datiNoSe sono poche vengono inserite celle vuote; se sono troppe l'eccesso è ignorato
Barre iniziali e finaliNoFacoltative; la specifica le raccomanda per chiarezza e per evitare ambiguità di analisi
Spazi di riempimentoNoNessun effetto sull'output; esistono perché un umano legga la sorgente
Una riga vuota dentro la tabellaMaiLa tabella si interrompe alla prima riga vuota o all'inizio di un altro blocco
Generatore di tabelle MarkdownIncolla CSV, TSV o dati con punto e virgola e ottieni una tabella Markdown allineata, con allineamento per colonna, escape dei | e anteprima dal vivo.Prova lo strumento

Domande frequenti

Qual è la tabella Markdown valida più piccola?
Due righe: una riga di intestazione e una riga delimitatrice sotto. | Nome | sopra | --- | è una tabella completa con una colonna, una cella di intestazione e senza corpo, e la specifica GFM include un esempio esattamente così, notando soltanto che nell'HTML non compare alcun elemento tbody. Più piccolo non si può. Non esiste una tabella di una riga, né un modo di avere righe di dati senza intestazione: se i tuoi dati non hanno un'intestazione naturale, il generatore scrive Colonna 1, Colonna 2 e così via, che è ciò che la sintassi impone. La cella delimitatrice più piccola è di tre caratteri, perché :-: è la forma più corta che porti ancora un marcatore di allineamento a entrambe le estremità.
Perché GitHub ha bisogno della fila di trattini quando altri motori no?
Perché una barra verticale in Markdown non significa nulla. Ogni altro costrutto di blocco si annuncia con un carattere a inizio riga — cancelletto, maggiore, trattino, un numero seguito da un punto — ma una riga con delle barre è indistinguibile dalla prosa. La sintassi delle tabelle di GitHub risolve la cosa richiedendo una seconda riga le cui celle contengano soltanto trattini ed eventuali due punti, cosa che nessun paragrafo produrrebbe per caso. I motori con un'altra sintassi di tabelle non hanno il problema perché marcano le tabelle in modo diverso: alcuni wiki usano un simbolo di apertura proprio, e formati come reStructuredText disegnano la tabella con una griglia di caratteri. Il requisito discende dalla notazione, non è una regola che GitHub abbia inventato per severità.
Posso fare una tabella senza intestazione?
Nella sintassi no. La prima riga è sempre l'intestazione, e la riga delimitatrice sta sempre sotto, quindi una tabella senza intestazione non si può esprimere. Il generatore se la cava inventando nomi — Colonna 1, Colonna 2 — quando togli la spunta a «la prima riga è l'intestazione», il che è un compromesso e non una soluzione. Due alternative se l'intestazione davvero non ha contenuto: dai alle colonne celle vuote, cosa legale che su GitHub appare come riga di intestazione vuota, oppure scrivi la tabella in HTML e togli del tutto il thead. Il trucco dell'intestazione vuota di solito rende meglio dei nomi inventati, ed entrambi sono a una modifica di distanza.
La mia tabella si vede su GitHub ma non sul mio sito di documentazione. Perché?
Perché le tabelle sono un'estensione e la tua build di documentazione non l'ha attivata. CommonMark 0.31.2 non ha alcun costrutto di tabella, quindi ogni processore che implementi la specifica centrale e nient'altro tratterà la tua tabella come tre paragrafi ordinari. Le tabelle di GitHub vivono in un documento separato, sotto il titolo Tables (extension). La maggior parte dei generatori di siti statici le supporta, ma quel supporto è un plugin o un flag di configurazione, non un dato di fatto. Controlla la configurazione Markdown della build, cerca un'opzione GFM o pipe-table, e se non c'è aggiungi il plugin oppure ripiega su una tabella HTML, che ogni motore che consenta HTML in linea mostrerà correttamente.
Se reincollo una tabella per modificarla, mantiene il suo allineamento?
Sì. La riga separatrice va ancora tolta — altrimenti i trattini arriverebbero come una riga di dati — ma i due punti vengono letti prima e diventano l'allineamento di partenza di ogni colonna: :--- torna come :---, ---: come ---:, :---: come :---:, e un --- semplice resta semplice. Tutte e quattro le forme GFM reggono l'andata e ritorno. Il resto del viaggio è altrettanto fedele: le celle vuote agli estremi vengono tolte, e un \| con escape viene ripulito in ingresso e riescapato in uscita, così una cella ps \| grep non diventa due colonne. Quello che scegli tu continua a scavalcare ciò che è stato letto: prendi un allineamento nel selettore di una colonna, o uno dei pulsanti sopra la tabella, e vince il tuo. È l'ordine voluto: la tabella incollata propone, la tua impostazione dispone.

Articoli che potrebbero interessarti

Tutte le guide
GuidaIncollare una tabella in una pull request: che cosa si rompe, e i due caratteri che la romponoUna tabella Markdown vieta esattamente due caratteri dentro una cella: la barra verticale e l'a capo. Ecco che cosa fa ciascuno, come li tratta un convertitore, perché l'escape va applicato nell'ordine giusto, e perché il riempimento non conta mai.TutorialMarkdown: guida per principiantiFormatta testo semplice con pochi simboli: # per i titoli, ** per il grassetto, - per le liste. Ecco cos'è il markdown, la sintassi base, perché è ovunque e i trucchi.GuidaTrasporre una tabella le cui righe avrebbero dovuto essere colonneChe ne è della riga di intestazione, delle righe di lunghezza diversa, dei tipi — e l'unica cosa con cui trasporre viene regolarmente confuso e che non può fare.GuidaLe liste di attività in Markdown e cosa viene reso davvero e doveLe liste di attività non sono in CommonMark. Sono un'estensione di GitHub Flavored Markdown, ed è per questo che lo stesso file mostra caselle in un posto e parentesi quadre letterali in un altro. La regola esatta del marcatore, cosa fa l'annidamento e una tabella di cosa è CommonMark, cosa è GFM e cosa non è nessuno dei due — verificato su entrambe le specifiche e quattro motori di resa.SpiegazioneConteggio parole: tempo di lettura e limitiUn conteggio parole sono parole separate da spazi. Ecco come si conta, perché esistono limiti, come si traduce in pagine e tempo di lettura, e quando contano i caratteri.GuidaFormattare o minificare: a cosa serve ciascuno e cosa cambia sul pesoQuattro fogli di stile veri passati nel minificatore, misurati grezzi e dopo gzip. Togliere tutti gli spazi ha fatto risparmiare 48, 103, 104 e 147 byte compressi; togliere i commenti 57, 1 358, 2 420 e 1 042. E i cinque input che questo minificatore rompe.

Strumenti correlati

Questo descrive il comportamento di un formato di file e di un motore di rendering, verificato sulla specifica citata e sul codice dello strumento così com'è oggi. I motori non concordano: GitHub, GitLab, un generatore di siti statici e l'anteprima del tuo editor sono quattro implementazioni diverse, e ciò che funziona in una può non funzionare in un'altra. Niente qui è una garanzia sulla tua catena di pubblicazione: prova il risultato dove verrà davvero pubblicato, e tratta ogni strumento, questo compreso, come qualcosa da verificare e non da credere.

Fonti

Hai notato un errore in questo articolo?