Construire un tableau Markdown de zéro, sans compter les tirets à la main
Publié le 30/07/2026 · 14 min de lecture · Outils pour développeurs
Daniel Okonkwo — Développeur front-end et rédacteur Tech chez Allin
Performance web · Formats de fichiers
Vérifié à partir de 4 sources
Le tableau Markdown minimal valide tient en deux lignes, pas trois : une ligne d'en-tête et une ligne de séparation en dessous. | Nom | Rôle | suivi de | --- | --- | est un tableau GitHub complet et valide, avec un en-tête et pas de corps — la spécification le dit explicitement, et le HTML produit n'a tout simplement pas de tbody. Ce que tu ne peux pas faire, c'est omettre la ligne de séparation. Une ligne d'en-tête seule est un paragraphe contenant des barres, et elle s'affichera en texte littéral. Cette rangée n'est ni un ornement ni du sucre d'alignement : en GitHub Flavored Markdown, c'est le signal qui transforme un paragraphe ordinaire en tableau, d'où son caractère obligatoire ici, alors que des moteurs à syntaxe de tableau différente n'en ont pas besoin. Deux règles en découlent. La ligne de séparation doit compter exactement autant de cellules que l'en-tête, sinon le tableau n'est pas reconnu du tout. Et toute autre rangée peut avoir n'importe quel nombre de cellules : trop peu, des cellules vides sont insérées ; trop, l'excédent est ignoré. Les barres de début et de fin sont facultatives — la spécification les recommande pour la lisibilité — et les espaces qui alignent les colonnes n'ont aucun effet sur le rendu. Les tableaux à barres ne font pas partie de CommonMark. La spécification centrale, version 0.31.2, définit des blocs feuilles et des blocs conteneurs et ne contient aucune construction de tableau ; ceux de GitHub sont une extension posée par-dessus. Un tableau parfait dans une pull request peut donc s'afficher en texte brut dans un processeur CommonMark strict, et le Markdown original de 2004 n'avait pas non plus de tableaux. Avant d'en écrire un, vérifie quel moteur va le lire.
La plus petite chose qui soit encore un tableau tient en deux lignes : une ligne d'en-tête et une ligne de séparation. Voici pourquoi la seconde est obligatoire en GitHub Flavored Markdown, où les tableaux à barres n'existent pas du tout, et ce qu'un générateur fait que la saisie manuelle ne peut pas faire.
La plus petite chose qui soit encore un tableau
Tape une ligne dans le générateur — Nom,Rôle — et il en produit deux : | Nom | Rôle | au-dessus, | --- | --- | en dessous. C'est tout le tableau. Il a un en-tête, aucune rangée de données, et il est valide : la spécification de GitHub Flavored Markdown contient un exemple exactement de cette forme et note seulement qu'aucun élément tbody n'est généré dans le HTML. Rien ne manque. Savoir si c'est utile est une autre affaire, mais la syntaxe est complète.
Supprime maintenant la deuxième ligne et tu n'as plus rien. Une ligne d'en-tête seule est un paragraphe qui contient des barres verticales, et tout moteur GFM l'imprimera comme tel : Nom | Rôle, en texte, barres comprises. C'est la première cause d'échec d'un tableau tapé à la main, et la raison est structurelle et non stylistique. Un analyseur Markdown décide de la nature d'un bloc en regardant comment il commence. Un dièse fait un titre, un chevron une citation, quatre espaces du code. Un paragraphe contenant des barres pourrait être n'importe quoi : un enchaînement shell, une table de vérité, un bout de prose sur les probabilités. La ligne de séparation est la seule chose qui dise à l'analyseur que ce paragraphe-là est un tableau, et rien ne permet de le deviner sans elle.
Le générateur, lui, ne peut pas l'oublier, et c'est là l'essentiel de son intérêt. Il construit l'en-tête, la ligne de séparation et chaque rangée de données à partir d'un seul nombre de colonnes : les trois ne peuvent jamais diverger. Donne-lui un en-tête sans corps et il produit le tableau de deux lignes. Décoche « la première ligne est l'en-tête » et il invente Colonne 1, Colonne 2 et ainsi de suite, parce que la syntaxe n'a pas de forme sans en-tête et qu'inventer des noms est la seule chose honnête qui reste. Donne-lui des rangées de longueurs inégales et il les rend rectangulaires, remplissant les courtes de cellules vides et t'indiquant, au-dessus du résultat, combien de rangées il a dû compléter.
Là où le tableau à barres n'existe tout simplement pas
Le Markdown tel que John Gruber l'a publié en 2004 n'a pas de tableaux. Lis le document de syntaxe d'origine : tu y trouveras titres, citations, listes, blocs de code, filets horizontaux, liens, emphase, images et HTML en ligne — et rien sur les colonnes. Les tableaux n'y ont jamais figuré, et l'issue de secours que le document propose pour tout ce qu'il ne couvre pas est d'écrire du HTML brut.
CommonMark, l'effort pour donner à Markdown une spécification sans ambiguïté, ne les a pas ajoutés. La version 0.31.2, datée de janvier 2024, définit des blocs feuilles — filets, titres, blocs de code, blocs HTML, paragraphes — et des blocs conteneurs — citations, éléments de liste, listes — et il n'y a pas de section tableau. La spécification reconnaît elle-même que certains dialectes ont étendu la syntaxe d'origine avec des conventions pour les notes de bas de page et les tableaux, ce qui place les tableaux nettement hors du noyau. Ceux de GitHub vivent dans un document séparé, la spécification GFM, sous l'intitulé Tables (extension).
La conséquence pratique est que l'endroit où ton tableau s'affiche dépend des extensions activées dans le processeur, et non de Markdown en tant que tel. Un README de dépôt sur GitHub est sûr. Un générateur de site statique, une chaîne de documentation, un client de messagerie, une zone de commentaire dans un outil de suivi de bugs : chacun résulte d'une décision distincte de celui qui l'a assemblé. Si la destination compte, le test de deux minutes consiste à y coller le tableau minimal de deux lignes et à regarder. S'il s'affiche en tableau avec une ligne d'en-tête, l'extension est active et le reste suivra ; s'il s'affiche en ligne de texte surmontant des tirets, écris le HTML à la place, ou passe à une liste.
Ce que le générateur compte et que tu ne peux pas compter
La ligne de séparation a un plancher de trois caractères, et ce n'est pas arbitraire : :-: est la cellule la plus courte pouvant encore porter un marqueur d'alignement à chaque extrémité. Le générateur applique ce plancher à chaque colonne : un en-tête d'une lettre ressort en | a | au-dessus de | --- |, jamais de | - |. Il calcule aussi la largeur de chaque colonne d'après la cellule la plus large de la colonne, en-tête compris — l'arithmétique que personne n'a envie de faire à la main sur un tableau de douze rangées.
Le point intéressant est la façon dont il mesure une cellule, car un caractère n'est pas une colonne. Ce générateur compte des colonnes d'affichage, pas des caractères : les idéogrammes 東京 font deux caractères et il en compte quatre, un é écrit e plus accent combinant fait deux caractères et il en compte un, un emoji simple fait deux unités UTF-16 et il en compte deux. Compter les caractères, c'est ce que fait un générateur naïf, et cela désaligne le source dès que les données quittent l'alphabet latin. L'emoji de famille est le cas qui piège les compteurs naïfs : quatre personnages soudés par des liants de largeur nulle, sept points de code, onze unités UTF-16, et un seul glyphe de deux colonnes. Ce générateur annonce deux, parce qu'un liant de largeur nulle n'occupe aucune colonne et prive de la sienne le point de code qui le suit. Rien de tout cela n'atteint le tableau rendu — l'alignement existe pour que la source tombe droit dans un éditeur, et c'est le seul endroit où il peut être juste ou faux.
Il existe un mode compact qui coupe entièrement l'alignement. Avec lui, la séparation garde ses trois caractères — | :-- | :-: | --: | pour gauche, centre et droite — et toute autre cellule est écrite sans le moindre espace de remplissage. C'est le réglage qu'il faut pour un large tableau dans un fichier versionné, car un tableau aligné réagence toute sa colonne dès qu'une valeur s'allonge, et une correction d'un mot devient un diff qui touche chaque rangée.
Modifier un tableau que tu as déjà
Le générateur accepte un tableau Markdown existant en entrée, ce qui est le moyen le plus rapide d'ajouter une colonne ou de corriger une coquille sans tout réaligner. Colle le tableau : le séparateur est détecté comme la barre, les cellules vides de début et de fin sont retirées, la rangée de tirets est reconnue et écartée, et ce qui reste est ta grille. Les barres échappées survivent au voyage : une cellule valant ps \| grep est déséchappée en ps | grep à l'entrée et ré-échappée à la sortie, si bien que le tableau revient identique et non élargi d'une colonne. Le convertisseur CSV de ce site referme la même boucle par son propre bout : il échappe l'antislash avant la barre, si bien qu'une cellule contenant déjà \| survit à une nouvelle conversion.
L'alignement survit lui aussi au voyage, ce qui est moins évident qu'il n'y paraît, puisque la ligne qui le porte est justement celle qu'il faut jeter. L'outil lit les deux-points sur la ligne de séparation avant de la filtrer — :--- à gauche, ---: à droite, :---: au centre, un --- tout court ne dit rien — et initialise le réglage de chaque colonne avec ce qu'il a lu. Colle un tableau dont la règle est | :--- | ---: | et la colonne de nombres alignée à droite revient alignée à droite. Ce que tu règles à la main l'emporte toujours : les sélecteurs par colonne et les boutons Par défaut, Gauche, Centre et Droite au-dessus du tableau écrasent ce qui a été lu, donc tu peux changer un alignement exprès. Ce que tu ne peux plus, c'est en perdre un par accident.
| Partie | Obligatoire ? | Ce qui arrive si elle manque ou est fausse |
|---|---|---|
| Ligne d'en-tête | Oui | Il n'existe pas de forme sans en-tête ; le générateur invente Colonne 1, Colonne 2 plutôt que de l'omettre |
| Ligne de séparation en tirets | Oui | Aucun tableau — l'en-tête s'affiche en paragraphe contenant des barres |
| Nombre de cellules de séparation égal à l'en-tête | Oui | Le tableau n'est pas reconnu et retombe en texte littéral |
| Rangées de données | Non | En-tête plus séparation forme un tableau valide ; le HTML n'a simplement pas de tbody |
| Nombre de cellules d'une rangée de données | Non | Trop peu, des cellules vides sont insérées ; trop, l'excédent est ignoré |
| Barres de début et de fin | Non | Facultatives ; la spécification les recommande pour la clarté et pour éviter l'ambiguïté d'analyse |
| Espaces d'alignement | Non | Aucun effet sur le rendu ; ils existent pour qu'un humain lise le source |
| Une ligne vide dans le tableau | Jamais | Le tableau s'interrompt à la première ligne vide ou au début d'un autre bloc |
Questions fréquentes
- Quel est le plus petit tableau Markdown valide ?
- Deux lignes : une ligne d'en-tête et une ligne de séparation en dessous. | Nom | au-dessus de | --- | est un tableau complet à une colonne, une cellule d'en-tête et aucun corps, et la spécification GFM contient un exemple exactement comme celui-là, notant seulement qu'aucun élément tbody n'apparaît dans le HTML. On ne peut pas faire plus petit. Il n'existe pas de tableau d'une ligne, et il n'existe pas de moyen d'avoir des rangées de données sans en-tête — si tes données n'ont pas d'en-tête naturel, le générateur écrit Colonne 1, Colonne 2 et ainsi de suite, ce que la syntaxe impose. La plus petite cellule de séparation fait trois caractères, car :-: est la forme la plus courte portant encore un marqueur d'alignement aux deux bouts.
- Pourquoi GitHub exige-t-il la rangée de tirets quand d'autres moteurs s'en passent ?
- Parce qu'une barre verticale ne signifie rien en Markdown. Toute autre construction de bloc s'annonce par un caractère en début de ligne — dièse, chevron, tiret, un nombre suivi d'un point — mais une ligne contenant des barres est indiscernable de la prose. La syntaxe de tableaux de GitHub résout cela en exigeant une seconde ligne dont les cellules ne contiennent que des tirets et éventuellement des deux-points, ce qu'aucun paragraphe ne produirait par accident. Les moteurs à syntaxe de tableau différente n'ont pas ce problème, car ils marquent les tableaux autrement : certains wikis utilisent un jeton d'ouverture propre, et des formats comme reStructuredText dessinent le tableau avec une grille de caractères. L'exigence découle de la notation, ce n'est pas une règle inventée par GitHub pour être sévère.
- Peut-on faire un tableau sans en-tête ?
- Pas dans la syntaxe. La première rangée est toujours l'en-tête, et la séparation se place toujours en dessous : un tableau sans en-tête ne peut pas s'exprimer. Le générateur gère cela en inventant des noms — Colonne 1, Colonne 2 — quand tu décoches « la première ligne est l'en-tête », ce qui est un compromis et non une solution. Deux solutions de rechange si l'en-tête n'a réellement rien à dire : donne aux colonnes des cellules vides, ce qui est légal et s'affiche en rangée d'en-tête vide sur GitHub, ou écris le tableau en HTML et supprime complètement le thead. L'astuce de l'en-tête vide rend généralement mieux que les noms inventés, et une seule modification sépare l'une de l'autre.
- Mon tableau s'affiche sur GitHub mais pas sur mon site de documentation. Pourquoi ?
- Parce que les tableaux sont une extension et que ta chaîne de documentation ne l'a pas activée. CommonMark 0.31.2 n'a aucune construction de tableau : tout processeur qui implémente la spécification centrale et rien d'autre traitera ton tableau comme trois paragraphes ordinaires. Les tableaux de GitHub vivent dans un document séparé, sous l'intitulé Tables (extension). La plupart des générateurs de sites statiques les prennent en charge, mais cette prise en charge est un greffon ou un drapeau de configuration, pas un acquis. Vérifie la configuration Markdown de la chaîne, cherche une option GFM ou « pipe tables », et s'il n'y en a pas, ajoute le greffon ou replie-toi sur un tableau HTML, que tout moteur autorisant le HTML en ligne affichera correctement.
- Si je recolle un tableau pour le modifier, garde-t-il son alignement ?
- Oui. La ligne de séparation doit toujours être retirée — sinon les tirets arriveraient comme une ligne de données — mais les deux-points y sont lus d'abord et deviennent l'alignement de départ de chaque colonne : :--- revient en :---, ---: en ---:, :---: en :---:, et un --- tout court reste tout court. Les quatre formes GFM font l'aller-retour. Le reste du voyage est fidèle aussi : les cellules vides de début et de fin sont retirées, et un \| échappé est déséchappé à l'entrée puis ré-échappé à la sortie, si bien qu'une cellule ps \| grep ne se transforme pas en deux colonnes. Ce que tu choisis toi-même écrase toujours ce qui a été lu : prends un alignement dans le sélecteur d'une colonne, ou l'un des boutons au-dessus du tableau, et c'est le tien qui gagne. C'est l'ordre voulu : le tableau collé propose, ton réglage dispose.
Articles qui pourraient t'intéresser
Tous les guides →Outils similaires
Ceci décrit le comportement d'un format de fichier et d'un moteur de rendu, vérifié sur la spécification citée et sur le code de l'outil tel qu'il existe aujourd'hui. Les moteurs de rendu divergent : GitHub, GitLab, un générateur de site statique et l'aperçu de ton éditeur sont quatre implémentations différentes, et ce qui passe dans l'une peut échouer dans l'autre. Rien ici n'est une garantie sur ta chaîne de publication — teste le résultat là où il sera réellement publié, et considère tout outil, celui-ci compris, comme quelque chose à vérifier et non à croire.
Sources
- GitHub — GitHub Flavored Markdown Spec, version 0.29-gfm (2019-04-06), section 4.10 Tables (extension): the delimiter row is required and must match the header row in cell count; body rows may vary in length, with missing cells inserted empty and excess cells ignored; leading and trailing pipes are recommended but optional; the table is broken at the first empty line or the beginning of another block-level structure
- CommonMark — CommonMark Spec version 0.31.2 (2024-01-28): the core specification defines leaf blocks (thematic breaks, headings, code blocks, HTML blocks, paragraphs) and container blocks (block quotes, list items, lists) and contains no table construct — tables are named in the introduction as one of the extensions others added to the original syntax
- Daring Fireball — Markdown: Syntax, the original 2004 specification by John Gruber — covers headers, blockquotes, lists, code blocks, horizontal rules, links, emphasis, images and inline HTML, and contains no table syntax at all; the documented fallback for anything it does not cover is to write HTML
- GitHub Docs — Organizing information with tables: the practical rules as GitHub documents them, including escaping a pipe as \| inside a cell and the fact that the vertical bars of a row do not need to line up
Tu as repéré une erreur dans cet article ?