Para que los saltos de línea simples del texto fuente se interpreten como espacios y las líneas en blanco inicien párrafos, crea la estructura de párrafos antes de aplicar el ajuste normal del texto. En Mac, puedes probarlo en una página local del navegador; CSS por sí solo no distingue entre ambos casos.

Esta guía está dirigida a quienes preparan prosa en inglés para una página web sencilla o una vista previa de Markdown. El objetivo es conservar líneas legibles en el texto fuente y, a la vez, crear párrafos fluidos que se reajusten cuando cambie el ancho de la ventana del navegador.

Por qué una propiedad CSS de espacios en blanco no resuelve ambos requisitos

Considera este texto fuente de ejemplo. Cada párrafo ocupa dos líneas en el texto fuente y una línea vacía separa los párrafos:

Panel A introduces the layout
and describes the first section.

Panel B introduces another section
and describes the remaining space.

El resultado deseado son dos párrafos. Dentro de cada párrafo, el salto de línea del texto fuente se convierte en un espacio. Luego, el navegador determina los saltos de línea visibles según el ancho disponible.

Con white-space: normal, los saltos de línea del texto fuente se contraen junto con los demás espacios en blanco que se pueden contraer. Esto incluye los saltos de línea consecutivos: una línea vacía en el texto fuente no crea un párrafo. Con white-space: pre-line, los caracteres de salto de línea se conservan como saltos de línea, incluidos los saltos simples que querías unir. MDN describe estos comportamientos en su referencia de la propiedad white-space.

Propiedad aplicada a un bloque de texto Salto de línea simple en el texto fuente Línea vacía en el texto fuente ¿Adecuada para esta tarea?
white-space: normal Se contrae junto con los espacios en blanco También se contrae Solo después de crear los párrafos
white-space: pre-line Conserva un salto de línea Conserva los saltos No
white-space: pre-wrap Conserva un salto de línea Conserva los saltos No
Elementos de párrafo separados con white-space: normal El texto fluye dentro de cada párrafo Se representa mediante un límite de párrafo Sí

El W3C describe el procesamiento de espacios en blanco como una operación de representación que deja intactos los datos subyacentes del documento. Sus reglas para los saltos de segmento también dependen del texto circundante; reemplazar un salto de línea por un espacio es apropiado para la prosa en inglés que se usa aquí, pero no constituye una transformación universal para todo tipo de texto. Consulta CSS Text Module Level 3.

Por lo tanto, la solución práctica consta de dos etapas: reconocer los párrafos en el texto fuente y, luego, dejar que el navegador distribuya el texto. El estándar HTML de WHATWG define el elemento p como la representación de un párrafo. Su separación visual se puede controlar de forma independiente mediante estilos. Consulta el elemento p.

Elige la opción adecuada para tu texto fuente

Antes de cambiar nada, usa la siguiente guía de decisión. Separa la interpretación del texto fuente de su apariencia, lo que ayuda a evitar que corrijas la capa equivocada.

Lo que tienes Qué hacer
Texto sin formato que contiene solo prosa Divide por líneas vacías, une los saltos de línea simples dentro de cada párrafo y crea elementos de párrafo
Markdown con encabezados, listas o bloques de código Usa un analizador de Markdown y comprueba cómo maneja los saltos de línea suaves
HTML existente con elementos de párrafo separados Comprueba los estilos de espacios en blanco y espaciado de los párrafos
Una página que contiene elementos explícitos de salto de línea Corrige el texto fuente o la configuración de representación si esos saltos no son intencionales
Una página que solo puedes consultar Usa un flujo de trabajo disponible para el texto fuente o la exportación; los ejemplos de aquí requieren que puedas controlar el documento

No reemplaces cada salto de línea por un espacio antes de identificar los párrafos: eso elimina los separadores necesarios para distinguirlos. Del mismo modo, no sustituyas la estructura de párrafos por elementos br repetidos. WHATWG define br como un salto de línea e indica que no debe usarse para separar grupos temáticos dentro de un párrafo. Consulta el elemento br.

Crea un ejemplo local funcional con TextEdit

La siguiente página completa requiere TextEdit y un navegador con JavaScript habilitado. Incluye un campo editable para el texto fuente y una vista previa independiente. No usa bibliotecas externas.

  1. Abre TextEdit y selecciona File > New y, luego, Format > Make Plain Text.
  2. Pega el ejemplo completo que aparece a continuación.
  3. Selecciona File > Save y ponle al archivo el nombre paragraph-demo.html.
  4. Si aparece un mensaje sobre la extensión, selecciona Use .html.
  5. Abre el archivo guardado en Safari u otro navegador de escritorio.

Apple documenta los pasos para crear un archivo de texto sin formato y elegir la extensión en Trabajar con documentos HTML en TextEdit en Mac. Si vuelves a abrir el archivo para editarlo, usa el ajuste de TextEdit Display HTML files as HTML code instead of formatted text, disponible en TextEdit > Settings > Open and Save.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Paragraph flow demo</title>
  <style>
    body {
      max-width: 46rem;
      margin: 2rem auto;
      padding: 0 1rem;
      font: 1rem/1.6 system-ui, sans-serif;
    }
    label { display: block; }
    textarea {
      box-sizing: border-box;
      width: 100%;
      min-height: 12rem;
      font: 1rem/1.5 monospace;
    }
    #preview p {
      white-space: normal;
      margin: 0;
    }
    #preview p + p { margin-top: 1em; }
  </style>
</head>
<body>
  <h1>Paragraph flow demo</h1>
  <label for="source">Source text</label>
  <textarea id="source">Panel A introduces the layout
and describes the first section.

Panel B introduces another section
and describes the remaining space.</textarea>
  <h2>Preview</h2>
  <div id="preview"></div>
  <script>
    function toParagraphs(source) {
      return source.replace(/\r\n?/g, '\n')
        .split(/\n[ \t]*\n(?:[ \t]*\n)*/)
        .map(block => block
          .replace(/^[ \t\n]+|[ \t\n]+$/g, '')
          .replace(/[ \t]*\n[ \t]*/g, ' '))
        .filter(text => text.length > 0);
    }

    const source = document.getElementById('source');
    const preview = document.getElementById('preview');

    function render() {
      const paragraphs = toParagraphs(source.value).map(text => {
        const paragraph = document.createElement('p');
        paragraph.textContent = text;
        return paragraph;
      });
      preview.replaceChildren(...paragraphs);
    }

    source.addEventListener('input', render);
    render();
  </script>
</body>
</html>

Primero, el convertidor normaliza los finales de línea CR y CRLF como LF. Luego, divide el texto allí donde una línea esté vacía o contenga únicamente espacios y tabulaciones normales. Dentro de cada bloque resultante, reemplaza cada salto de línea restante, junto con los espacios o tabulaciones adyacentes, por un espacio normal.

Estas son reglas explícitas para este ejemplo, no un analizador general de documentos. Varias líneas vacías producen un solo límite de párrafo. Se eliminan los espacios en blanco normales iniciales y finales. Una entrada vacía no produce ningún párrafo. El texto fuente original permanece visible en el campo de entrada, así que puedes comparar ambas versiones.

El texto de cada párrafo de salida se asigna mediante textContent. MDN documenta que asignar esta propiedad reemplaza los nodos secundarios de un nodo por un nodo de texto. Aquí solo se asigna a párrafos vacíos recién creados. Consulta Nodo: propiedad textContent.

La función de conversión superó seis comprobaciones deterministas en Node.js: entrada de párrafo normal, entrada con CRLF, entrada con CR, entrada que solo contiene líneas vacías, líneas vacías repetidas y conservación de un espacio de no separación. Durante la preparación no se ejecutó la representación en el navegador; usa las comprobaciones visuales que aparecen a continuación para verificarla en tu Mac.

Comprueba por separado los límites entre párrafos y el ajuste de línea

Empieza con el ejemplo incluido. La vista previa debe mostrar Panel A introduces the layout and describes the first section. como un párrafo, seguido del párrafo correspondiente del Panel B. Con la ventana estrecha, cualquiera de los dos párrafos puede ocupar varias líneas visibles.

Ahora haz estos cambios controlados:

  1. Reemplaza por un espacio el salto de línea simple que aparece después de layout. La estructura de párrafos de la vista previa debe mantenerse igual.
  2. Restaura ese salto de línea y elimina la línea vacía entre los dos bloques. La vista previa debe convertirse en un solo párrafo.
  3. Añade entre los bloques una línea vacía que contenga solo espacios o tabulaciones. La vista previa debe volver a mostrar dos párrafos.
  4. Añade varias líneas vacías allí. El espacio debe seguir siendo el de un solo límite entre párrafos.
  5. Cambia el tamaño de la ventana del navegador. El límite entre párrafos debe mantenerse fijo, mientras que las líneas dentro de cada párrafo se ajustan de nuevo.

Esta secuencia distingue los límites del texto fuente del ajuste de línea que realiza el navegador. En el ejemplo, la separación entre párrafos se debe a la regla de margen entre párrafos adyacentes. Si cambias ese margen, cambia el espacio visible, pero no la forma en que se analiza el texto fuente.

Si usas white-space: normal sin este convertidor, que el texto se vea unido no significa que el salto de línea del texto fuente se haya eliminado. MDN explica que los espacios en blanco del contenido de texto ordinario permanecen en el DOM, aunque CSS los contraiga al representar el contenido. Consulta Manejo de los espacios en blanco.

Usa un analizador de Markdown para documentos Markdown

Markdown ya proporciona la convención de párrafos necesaria. CommonMark define un párrafo como líneas consecutivas no vacías que no pertenecen a otro tipo de bloque; las líneas vacías separan los párrafos. Un salto de línea normal dentro de un párrafo es un salto suave, que el procesador puede convertir en un salto de línea o en un espacio. Consulta Párrafos de CommonMark y saltos de línea suaves.

Pega el ejemplo en la vista del texto fuente de tu editor de Markdown y revisa la vista previa. Si cada salto de línea simple produce un salto visible, consulta las opciones de representación documentadas del editor. No des por sentado que todas las aplicaciones de Markdown ofrecen el mismo ajuste.

Si un proyecto usa la biblioteca markdown-it, su opción documentada breaks tiene como valor predeterminado false. Si se establece en true, los saltos de línea de los párrafos se convierten en elementos br. Si se mantiene en false, se obtienen párrafos fluidos, siempre que el CSS de salida también contraiga los espacios en blanco. Consulta MarkdownItOptions.

Los saltos duros explícitos de Markdown también requieren atención. Según CommonMark, dos o más espacios al final de la línea o una barra invertida final pueden crear un salto de línea duro. Elimina esos marcadores solo cuando no sean intencionales. Las reglas se documentan en saltos de línea duros.

No ejecutes el convertidor de texto sin formato en un documento Markdown completo. No reconoce encabezados, listas, bloques de código delimitados ni reglas de sangría. Deja que un analizador de Markdown conserve esas estructuras y aplica los estilos de espacios en blanco a los párrafos de prosa resultantes.

Respeta los límites de representación del navegador y de composición tipográfica

Siempre que sea práctico, conserva el texto continuo en cada párrafo de prosa. El ejemplo crea un nodo de texto por párrafo y deja que el navegador se encargue del ajuste de línea y la composición de los glifos. No mide palabras ni inserta un elemento independiente alrededor de cada carácter.

Ese límite es importante para la tipografía. El W3C especifica las circunstancias en las que la composición debe continuar a través de los límites entre elementos en línea y aquellas en las que debe interrumpirse, incluidos ciertos cambios de espaciado y alineación. Evita añadir elementos en línea innecesarios solo para controlar la posición de las líneas. Consulta Composición tipográfica a través de los límites entre elementos.

Usa el convertidor solo si cada salto de línea aislado del texto fuente representa un ajuste editorial de línea. Si un salto de línea divide intencionalmente etiquetas o aparece dentro de una palabra, unirlo con un espacio cambia el contenido. El ejemplo también trata como contenido una línea que contiene un espacio de no separación, en lugar de usarla como separador vacío; MDN distingue los espacios de no separación de los espacios en blanco ordinarios que se pueden contraer en un documento, en Manejo de los espacios en blanco.

Para la prosa en inglés, establece primero los límites entre párrafos y deja que el navegador ajuste las líneas dentro de ellos. El ejemplo local permite inspeccionar esta regla: el texto fuente conserva sus líneas editables, la vista previa contiene párrafos reales y, al cambiar el tamaño de la ventana, solo se modifica el ajuste visible de las líneas.

Fuentes