Construir una tabla Markdown desde cero, sin contar guiones a mano
Publicado el 30/7/2026 · 13 min de lectura · Herramientas para desarrolladores
Daniel Okonkwo — Desarrollador front-end y redactor de Tecnología en OneKitly
Rendimiento web · Formatos de archivo
Verificado con 4 fuentes
La tabla Markdown mínima válida son dos líneas, no tres: una fila de cabecera y una fila delimitadora debajo. | Nombre | Rol | seguido de | --- | --- | es una tabla de GitHub completa y válida, con cabecera y sin cuerpo: la especificación lo dice explícitamente, y el HTML que produce sencillamente no tiene tbody. Lo que no puedes hacer es omitir la fila delimitadora. Una línea de cabecera sola es un párrafo con barras dentro, y se mostrará como texto literal. Esa fila no es adorno ni azúcar de alineación: en GitHub Flavored Markdown es la señal que convierte un párrafo corriente en una tabla, y por eso es obligatoria aquí mientras que motores con otra sintaxis de tablas no la necesitan. De ahí salen dos reglas. La fila delimitadora debe tener exactamente tantas celdas como la cabecera, o la tabla no se reconoce en absoluto. Y cualquier otra fila puede tener el número de celdas que sea: si faltan, se insertan celdas vacías; si sobran, el exceso se descarta. Las barras de principio y fin son opcionales —la especificación las recomienda por claridad— y los espacios que cuadran las columnas no afectan al resultado en nada. Las tablas de barras no forman parte de CommonMark. La especificación central, versión 0.31.2, define bloques hoja y bloques contenedor y no contiene ninguna construcción de tabla; las de GitHub son una extensión encima. Así que una tabla que se ve perfecta en un pull request puede salir como texto crudo en un procesador CommonMark estricto, y el Markdown original de 2004 tampoco tenía tablas. Antes de escribir una, mira qué motor va a leerla.
Lo más pequeño que sigue siendo una tabla son dos líneas: una fila de cabecera y una fila delimitadora. Aquí está por qué la segunda es obligatoria en GitHub Flavored Markdown, dónde las tablas de barras no existen en absoluto, y qué hace un generador que teclear a mano no puede.
Lo más pequeño que sigue siendo una tabla
Escribe una línea en el generador —Nombre,Rol— y produce dos: | Nombre | Rol | arriba, | --- | --- | debajo. Esa es toda la tabla. Tiene cabecera, ninguna fila de datos, y es válida: la especificación de GitHub Flavored Markdown incluye un ejemplo exactamente de esa forma y solo apunta que no se genera ningún elemento tbody en el HTML. No falta nada. Si eso es útil es otra cuestión, pero la sintaxis está completa.
Ahora borra la segunda línea y no tienes nada. Una fila de cabecera sola es un párrafo que contiene barras verticales, y cualquier motor GFM lo imprimirá como tal: Nombre | Rol, en texto, barras incluidas. Es la causa número uno de que falle una tabla tecleada a mano, y la razón es estructural, no estilística. Un analizador Markdown decide qué es un bloque mirando cómo empieza. Una almohadilla hace un título, un signo mayor que una cita, cuatro espacios código. Un párrafo con barras podría ser cualquier cosa: una tubería de shell, una tabla de verdad, un trozo de prosa sobre probabilidad. La fila delimitadora es lo único que le dice al analizador que ese párrafo concreto es una tabla, y no hay forma de inferirlo sin ella.
El generador no puede olvidarla, y ahí está casi todo el valor de usar uno. Construye la cabecera, la fila delimitadora y cada fila de datos a partir de un único recuento de columnas, así que las tres nunca pueden discrepar. Dale una cabecera sin cuerpo y emite la tabla de dos líneas. Desactiva el interruptor de «la primera fila es la cabecera» e inventa Columna 1, Columna 2 y así, porque la sintaxis no tiene forma sin cabecera e inventar nombres es lo único honesto que queda. Dale filas de longitud desigual y las cuadra, rellenando las cortas con celdas vacías y diciéndote, encima del resultado, cuántas filas tuvo que rellenar.
Dónde la tabla de barras sencillamente no existe
El Markdown tal como lo publicó John Gruber en 2004 no tiene tablas. Lee el documento de sintaxis original y encontrarás títulos, citas, listas, bloques de código, líneas horizontales, enlaces, énfasis, imágenes y HTML en línea, y nada sobre columnas. Las tablas nunca estuvieron, y la salida de emergencia que el documento ofrece para todo lo que no cubre es escribir HTML crudo.
CommonMark, el esfuerzo por dar a Markdown una especificación sin ambigüedades, no las añadió. La versión 0.31.2, de enero de 2024, define bloques hoja —líneas temáticas, títulos, bloques de código, bloques HTML, párrafos— y bloques contenedor —citas, elementos de lista, listas—, y no hay sección de tablas. La propia especificación reconoce que algunos dialectos extendieron la sintaxis original con convenciones para notas al pie y tablas, lo que sitúa a las tablas claramente fuera del núcleo. Las de GitHub viven en un documento aparte, la especificación GFM, bajo el epígrafe Tables (extension).
La consecuencia práctica es que dónde se renderiza tu tabla depende de qué extensiones tenga activadas el procesador, no de Markdown como tal. Un README de repositorio en GitHub es seguro. Un generador de sitios estáticos, una compilación de documentación, un cliente de chat, una caja de comentarios en un gestor de incidencias: cada uno es una decisión aparte de quien lo montó. Si el destino importa, la prueba de dos minutos es pegar allí la tabla mínima de dos líneas y mirar. Si se ve como una tabla con una fila de cabecera, la extensión está activa y lo demás funcionará; si se ve como una línea de texto con guiones debajo, escribe el HTML en su lugar, o usa una lista.
Lo que el generador cuenta y tú no puedes
La fila delimitadora tiene un suelo de tres caracteres, y no es arbitrario: :-: es la celda más corta que aún puede llevar un marcador de alineación en cada extremo. El generador aplica ese suelo a cada columna, así que una cabecera de una letra sale como | a | sobre | --- |, nunca sobre | - |. También calcula el ancho de cada columna a partir de la celda más ancha de esa columna, cabecera incluida, que es la aritmética que nadie quiere hacer a mano en una tabla de doce filas.
Lo interesante es cómo mide una celda, porque un carácter no es una columna. Este generador cuenta columnas de pantalla, no caracteres: los ideogramas 東京 son dos caracteres y cuenta cuatro, una é escrita como e más acento combinante son dos caracteres y cuenta uno, un emoji suelto son dos unidades UTF-16 y cuenta dos. Contar caracteres es lo que hace un generador ingenuo, y desalinea la fuente en cuanto los datos salen del alfabeto latino. El emoji de familia es el caso que pilla a los contadores ingenuos: cuatro figuras soldadas por uniones de ancho cero, siete puntos de código, once unidades UTF-16 y un solo glifo de dos columnas. Este generador anuncia dos, porque una unión de ancho cero no ocupa columna alguna y le quita la suya al punto de código que la sigue. Nada de esto llega a la tabla renderizada: el relleno existe para que la fuente cuadre en un editor, y es el único sitio donde puede estar bien o mal.
Hay un modo compacto que quita el relleno por completo. Con él, la separadora conserva sus tres caracteres —| :-- | :-: | --: | para izquierda, centro y derecha— y cualquier otra celda se escribe sin ningún relleno. Es el ajuste que quieres para una tabla ancha en un fichero versionado, porque una tabla rellenada recompone toda su columna en cuanto un valor se alarga, y una corrección de una palabra se convierte en un diff que toca todas las filas.
Editar una tabla que ya tienes
El generador acepta como entrada una tabla Markdown ya existente, que es la forma más rápida de añadir una columna o corregir una errata sin realinear nada. Pega la tabla: el separador se detecta como la barra, las celdas vacías del principio y del final se quitan, la fila de guiones se reconoce y se descarta, y lo que queda es tu rejilla. Las barras escapadas sobreviven al viaje: una celda que diga ps \| grep se desescapa a ps | grep a la entrada y se vuelve a escapar a la salida, así que la tabla regresa idéntica y no una columna más ancha. El conversor de CSV de este sitio cierra el mismo círculo por su propio extremo: escapa la contrabarra antes que la barra, así que una celda que ya llevaba \| sobrevive a una nueva conversión.
La alineación también sobrevive al viaje, lo que es menos obvio de lo que parece, porque la fila que la lleva es justo la que hay que tirar. La herramienta lee los dos puntos de la fila separadora antes de filtrarla —:--- izquierda, ---: derecha, :---: centro, un --- a secas no dice nada— y arranca el ajuste de cada columna con lo que ha leído. Pega una tabla cuya regla sea | :--- | ---: | y la columna de números alineada a la derecha vuelve alineada a la derecha. Lo que fijas a mano sigue mandando: los selectores por columna y los botones Por defecto, Izquierda, Centro y Derecha encima de la tabla pisan lo leído, así que puedes cambiar una alineación a propósito. Lo que ya no puedes es perder una sin darte cuenta.
| Parte | ¿Obligatoria? | Qué pasa si falta o está mal |
|---|---|---|
| Fila de cabecera | Sí | No existe forma sin cabecera; el generador inventa Columna 1, Columna 2 antes que omitirla |
| Fila delimitadora de guiones | Sí | Ninguna tabla: la cabecera se muestra como un párrafo con barras |
| Recuento de celdas delimitadoras igual a la cabecera | Sí | La tabla no se reconoce y cae a texto literal |
| Filas de datos | No | Cabecera más separadora es una tabla válida; el HTML sencillamente no tiene tbody |
| Recuento de celdas en una fila de datos | No | Si faltan, se insertan celdas vacías; si sobran, el exceso se ignora |
| Barras de principio y fin | No | Opcionales; la especificación las recomienda por claridad y para evitar ambigüedad de análisis |
| Espacios de relleno | No | Ningún efecto en el resultado; existen para que un humano lea la fuente |
| Una línea en blanco dentro de la tabla | Nunca | La tabla se corta en la primera línea vacía o al empezar otro bloque |
Preguntas frecuentes
- ¿Cuál es la tabla Markdown válida más pequeña?
- Dos líneas: una fila de cabecera y una fila delimitadora debajo. | Nombre | sobre | --- | es una tabla completa con una columna, una celda de cabecera y sin cuerpo, y la especificación GFM incluye un ejemplo exactamente así, señalando solo que no aparece ningún elemento tbody en el HTML. No se puede ir más pequeño. No existe tabla de una línea, ni forma de tener filas de datos sin cabecera: si tus datos no tienen cabecera natural, el generador escribe Columna 1, Columna 2 y demás, que es lo que impone la sintaxis. La celda delimitadora más pequeña son tres caracteres, porque :-: es la forma más corta que aún lleva un marcador de alineación en ambos extremos.
- ¿Por qué GitHub necesita la hilera de guiones cuando otros motores no?
- Porque una barra vertical no significa nada en Markdown. Cualquier otra construcción de bloque se anuncia con un carácter al principio de línea —almohadilla, mayor que, guion, un número y un punto—, pero una línea con barras es indistinguible de la prosa. La sintaxis de tablas de GitHub lo resuelve exigiendo una segunda línea cuyas celdas solo contengan guiones y dos puntos opcionales, algo que ningún párrafo produciría por accidente. Los motores con otra sintaxis de tablas no tienen ese problema porque marcan las tablas de otro modo: algunos wikis usan un token de apertura propio, y formatos como reStructuredText dibujan la tabla con una rejilla de caracteres. El requisito se deriva de la notación, no es una regla que GitHub inventara por severidad.
- ¿Puedo hacer una tabla sin cabecera?
- En la sintaxis, no. La primera fila es siempre la cabecera, y la fila delimitadora va siempre debajo, así que una tabla sin cabecera no se puede expresar. El generador lo resuelve inventando nombres —Columna 1, Columna 2— cuando desmarcas el interruptor de «la primera fila es la cabecera», lo que es un apaño y no una solución. Dos alternativas si la cabecera de verdad no tiene contenido: dale a las columnas celdas vacías, lo cual es legal y se muestra como fila de cabecera vacía en GitHub, o escribe la tabla en HTML y quita el thead del todo. El truco de la cabecera vacía suele quedar mejor que los nombres inventados, y está a una edición de distancia de cualquiera de los dos.
- Mi tabla se ve en GitHub pero no en mi sitio de documentación. ¿Por qué?
- Porque las tablas son una extensión y tu compilación de documentación no la activó. CommonMark 0.31.2 no tiene construcción de tabla alguna, así que cualquier procesador que implemente la especificación central y nada más tratará tu tabla como tres párrafos corrientes. Las tablas de GitHub viven en un documento aparte, bajo el epígrafe Tables (extension). La mayoría de los generadores de sitios estáticos sí las admiten, pero ese soporte es un plugin o una opción de configuración, no algo dado. Revisa la configuración de Markdown de la compilación, busca una opción GFM o de tablas de barras, y si no la hay, añade el plugin o recurre a una tabla HTML, que cualquier motor que permita HTML en línea mostrará bien.
- Si vuelvo a pegar una tabla para editarla, ¿conserva su alineación?
- Sí. La fila separadora sigue teniendo que desaparecer —si no, los guiones llegarían como una fila de datos—, pero antes se leen sus dos puntos y pasan a ser la alineación inicial de cada columna: :--- vuelve como :---, ---: como ---:, :---: como :---:, y un --- a secas se queda a secas. Las cuatro formas de GFM hacen la ida y vuelta. El resto del viaje también es fiel: las celdas vacías de los extremos se quitan, y un \| escapado se desescapa a la entrada y se vuelve a escapar a la salida, de modo que una celda ps \| grep no se convierte en dos columnas. Lo que elijas tú sigue pisando lo leído: escoge una alineación en el selector de una columna, o uno de los botones de encima de la tabla, y gana la tuya. Ese es el orden buscado: la tabla pegada propone, tu ajuste dispone.
Artículos que podrían interesarte
Todas las guías →Herramientas relacionadas
Esto describe cómo se comportan un formato de archivo y un motor de renderizado, comprobado contra la especificación citada y contra el código de la herramienta tal y como está hoy. Los motores discrepan: GitHub, GitLab, un generador de sitios estáticos y la vista previa de tu editor son cuatro implementaciones distintas, y lo que funciona en una puede no funcionar en otra. Nada de esto garantiza nada sobre tu cadena de publicación: prueba el resultado donde vaya a publicarse de verdad, y trata cualquier herramienta, esta incluida, como algo que se comprueba y no como algo en lo que se confía.
Fuentes
- 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
¿Has detectado un error en este artículo?