Saltar al contenido
css-impresion.css · devschool

CSS para imprimir: @media print y @page

Lección 39 de 50 · 13 min de lectura · Actualizado el

En esta lección
  1. Estilos solo para imprimir: @media print
  2. Qué quitar: navegación, botones y adornos
  3. Adaptar el contenido al papel
  4. Mostrar la URL de los enlaces
  5. Configurar la hoja: @page
  6. Saltos de página
  7. Colores y fondos: print-color-adjust
  8. Un botón “Imprimir” y los eventos de impresión
  9. Una hoja de impresión completa
  10. Errores frecuentes
  11. Resumen

Aunque casi todo se lee en pantalla, la gente sigue imprimiendo: recetas, entradas de un concierto, facturas, horarios, apuntes, el resumen de una reserva. Si no has preparado tu web para ello, el resultado suele ser un desastre: el menú y el pie ocupan media hoja, el texto blanco sobre fondo oscuro desaparece, una tabla se corta por la mitad y los enlaces no dicen adónde llevan. En esta lección aprenderás a crear estilos solo para imprimir con @media print, a configurar la hoja con @page, a controlar los saltos de página, a esconder lo que no sirve en papel, a mostrar las URLs de los enlaces y a decidir qué colores se imprimen.

Estilos solo para imprimir: @media print

Las media queries no solo preguntan por el ancho de la pantalla: también por el tipo de medio. Los dos que usarás son screen (pantallas) y print (impresora y “Guardar como PDF”).

/* Se aplica siempre */
body {
  font-family: system-ui, sans-serif;
}

/* Solo al imprimir */
@media print {
  body {
    font-family: Georgia, serif;
    font-size: 12pt;
  }
}

Como @media print va al final, sus reglas ganan a las anteriores por la cascada: misma especificidad, gana la última. Solo tienes que escribir lo que cambia al imprimir.

También puedes llevarte esos estilos a un archivo aparte:

<link rel="stylesheet" href="css/estilos.css">
<link rel="stylesheet" href="css/imprimir.css" media="print">

El navegador descarga imprimir.css igualmente, pero con baja prioridad y sin bloquear el pintado de la página. Para unas pocas reglas, un bloque @media print al final de tu CSS es más cómodo.

Al revés, si algo debe verse solo en pantalla (una animación, un fondo con vídeo), usa @media screen.

Cómo probarlo sin gastar papel

  • Vista previa de impresión: pulsa Ctrl + P (Cmd + P en Mac) y elige “Guardar como PDF”. Verás exactamente las páginas que saldrían.
  • DevTools: en Chrome, abre el menú de tres puntos de las herramientas, “More tools” y “Rendering”, y en “Emulate CSS media type” elige print. La página se ve con los estilos de impresión y puedes inspeccionarlos como siempre. Firefox tiene un botón equivalente en el panel de estilos.

Qué quitar: navegación, botones y adornos

En papel no se puede hacer clic. Todo lo que sirve para navegar o interactuar sobra:

@media print {
  nav,
  .menu-movil,
  .buscador,
  .boton-compartir,
  .banner-cookies,
  footer,
  video,
  iframe {
    display: none;
  }
}

Una práctica cómoda es tener una clase de utilidad para marcar cualquier cosa desde el HTML:

@media print {
  .no-imprimir {
    display: none !important;
  }
}
<button class="no-imprimir" type="button">Añadir al carrito</button>

El !important aquí está justificado: es una utilidad que debe ganar siempre, aunque otra regla más específica le ponga display: flex.

También conviene quitar lo decorativo que gasta tinta y no aporta: sombras, fondos de color, degradados, bordes redondeados muy marcados.

@media print {
  * {
    box-shadow: none !important;
    text-shadow: none !important;
  }

  body {
    background: white;
    color: black;
  }
}

Adaptar el contenido al papel

Que ocupe todo el ancho

En pantalla es habitual limitar el contenido a un ancho máximo y centrarlo, o tener una barra lateral. En la hoja eso deja márgenes enormes. Deja que el contenido principal ocupe todo:

@media print {
  .contenedor {
    max-width: none;
    margin: 0;
    padding: 0;
  }

  .layout {
    display: block;   /* adiós a la rejilla con barra lateral */
  }

  aside {
    display: none;
  }
}

Tamaños en pt

En pantalla mides en px y rem. En papel tienen sentido las unidades físicas: pt (punto, 1/72 de pulgada), cm y mm. Un texto de 11 o 12 pt es lo normal en un documento impreso.

@media print {
  body { font-size: 12pt; line-height: 1.4; }
  h1   { font-size: 20pt; }
  h2   { font-size: 15pt; }
}

Las unidades las tienes todas en unidades. En pantalla, cm no mide un centímetro real; en impresión, sí.

Imágenes que no se salgan

@media print {
  img {
    max-width: 100% !important;
  }
}

Mostrar la URL de los enlaces

En pantalla, un enlace que dice “consulta las tarifas” funciona. En papel, el lector no sabe adónde lleva. La solución clásica es escribir la dirección detrás del texto con el pseudoelemento ::after y la función attr(), que lee el valor de un atributo:

@media print {
  a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 0.85em;
    word-break: break-all;   /* que una URL larga no se salga de la hoja */
  }
}

Con este HTML:

<p>Consulta las <a href="https://example.com/tarifas">tarifas de 2026</a>.</p>

En papel se lee:

Consulta las tarifas de 2026 (https://example.com/tarifas).

Fíjate en el selector: a[href^="http"] elige solo los enlaces cuyo href empieza por http. Así no se añaden direcciones a los enlaces internos de la misma página (href="#ingredientes"), que en papel no significan nada, ni a los mailto:. Los selectores de atributo los tienes en selectores, y ::after, en pseudoclases a fondo.

Si tu web usa rutas relativas (href="/tarifas/"), el texto mostraría solo /tarifas/. Puedes añadir el dominio a mano:

@media print {
  a[href^="/"]::after {
    content: " (https://example.com" attr(href) ")";
  }
}

La misma técnica sirve para mostrar el significado de las abreviaturas:

@media print {
  abbr[title]::after {
    content: " (" attr(title) ")";
  }
}

Y no olvides que, sin color, un enlace se confunde con el texto normal. Déjalo subrayado.

Configurar la hoja: @page

La regla @page controla la hoja de papel en sí: su tamaño, su orientación y sus márgenes. No va dentro de @media print porque solo tiene sentido al imprimir.

@page {
  size: A4;
  margin: 2cm 1.5cm;
}
  • size: A4, A5, letter… y la orientación: A4 landscape (apaisado) o A4 portrait (vertical). Si no lo indicas, el usuario elige en el cuadro de impresión. Fíjalo solo cuando el documento lo necesite, como una tabla muy ancha que solo cabe en apaisado.
  • margin: los márgenes de la hoja, con la misma sintaxis que el margin de siempre. Al darlos aquí, el body puede tener margin: 0.

Puedes dar estilos distintos a ciertas páginas con pseudoclases de página:

/* La primera hoja, con más espacio arriba para el logo */
@page :first {
  margin-top: 4cm;
}

/* En un documento a doble cara, margen interior más ancho para encuadernar */
@page :left  { margin-left: 2.5cm; margin-right: 1.5cm; }
@page :right { margin-left: 1.5cm; margin-right: 2.5cm; }

Numerar las páginas

Dentro de @page existen las cajas de margen, zonas como @top-center o @bottom-right, donde se puede escribir texto y el número de página:

@page {
  @bottom-right {
    content: "Página " counter(page) " de " counter(pages);
    font-size: 9pt;
  }
}

Nota: las cajas de margen funcionan en los navegadores basados en Chrome recientes, pero no en todos. Además, el navegador añade su propia cabecera y pie (fecha, título, URL) que el usuario puede quitar en el cuadro de impresión. Si numerar es imprescindible (facturas, informes), genera el PDF en el servidor.

Saltos de página

El navegador corta las páginas donde se acaba el espacio, sin pensar. Puede dejar un título solo al final de una hoja y su texto en la siguiente, o partir una tarjeta por la mitad. Tienes tres propiedades para guiarle:

PropiedadSe pone enValores útiles
break-beforeEl elemento antes del cual quieres el saltopage (forzar), avoid (evitar)
break-afterEl elemento después del cual quieres el saltopage, avoid
break-insideEl elemento que no quieres partiravoid

Forzar un salto

Cada capítulo de unos apuntes, o cada factura de una lista, empieza en una hoja nueva:

@media print {
  .capitulo {
    break-before: page;
  }

  .capitulo:first-child {
    break-before: auto;   /* el primero no: evita una hoja en blanco al principio */
  }
}

Evitar cortes feos

@media print {
  /* Un título nunca se queda solo al pie de la hoja */
  h1, h2, h3 {
    break-after: avoid;
  }

  /* Estas cajas no se parten por la mitad */
  figure,
  table,
  .tarjeta,
  blockquote {
    break-inside: avoid;
  }
}

avoid es una petición, no una orden. Si un elemento mide más que una hoja, el navegador no tiene más remedio que partirlo. Por eso no pongas break-inside: avoid en contenedores muy grandes como main o article.

Dos propiedades más afinan los párrafos: orphans (huérfanas, el mínimo de líneas de un párrafo que pueden quedar al final de una hoja) y widows (viudas, el mínimo de líneas que pueden pasar a la siguiente). Su valor por defecto es 2. No todos los navegadores las respetan, pero no hacen daño:

@media print {
  p {
    orphans: 3;
    widows: 3;
  }
}

Nota: verás en código antiguo page-break-before, page-break-after y page-break-inside. Son las versiones viejas de estas propiedades y siguen funcionando, pero usa las nuevas break-*.

Tablas largas

Si una tabla ocupa varias hojas, el navegador repite su <thead> en cada una, siempre que la hayas escrito con <thead>. Es otro motivo para marcar bien las tablas. Evita en cambio que las filas se partan:

@media print {
  tr {
    break-inside: avoid;
  }
}

Colores y fondos: print-color-adjust

Por defecto, para ahorrar tinta, los navegadores no imprimen los colores ni las imágenes de fondo, salvo que el usuario marque la opción “Gráficos de fondo”. Eso tiene dos consecuencias:

  1. Un texto blanco sobre un fondo oscuro puede quedar invisible: blanco sobre papel blanco. El navegador suele oscurecer el texto en ese caso, pero no siempre acierta. Mejor pon tú color: black en los elementos con fondo oscuro.
  2. Si el color transmite información (una leyenda de un gráfico, el estado de un pedido en verde o rojo, un código de colores en un horario), perderla es un problema.

Para el segundo caso existe print-color-adjust:

.leyenda-color,
.estado-pedido {
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}
ValorSignificado
economy (por defecto)El navegador puede quitar fondos y ajustar colores para ahorrar tinta
exactImprime los colores y fondos tal como están

Escribe las dos líneas: la versión con -webkit- la necesitan algunas versiones de Chrome y Safari. Úsalo solo en elementos concretos, nunca en todo el body: quien imprime en casa no quiere gastar un cartucho entero en tu cabecera.

Consejo: no confíes solo en el color, ni en pantalla ni en papel. Muchas impresoras son en blanco y negro. Añade siempre un texto o un icono: “Pagado”, “Pendiente”. Lo tienes explicado en CSS accesible.

Un botón “Imprimir” y los eventos de impresión

Desde JavaScript puedes abrir el cuadro de impresión con window.print():

const botonImprimir = document.querySelector('#imprimir');

botonImprimir.addEventListener('click', () => {
  window.print();
});

El navegador también avisa antes y después de imprimir con los eventos beforeprint y afterprint. Un uso práctico: los acordeones de <details> cerrados se imprimen cerrados, y el contenido se pierde. Puedes abrirlos todos antes de imprimir:

window.addEventListener('beforeprint', () => {
  document.querySelectorAll('details').forEach((detalle) => {
    detalle.open = true;
  });
});

Una hoja de impresión completa

Juntando todo, este es un bloque de partida razonable para cualquier web:

@page {
  margin: 2cm;
}

@media print {
  nav, footer, aside, video, iframe, .no-imprimir {
    display: none !important;
  }

  * {
    box-shadow: none !important;
    text-shadow: none !important;
  }

  body {
    margin: 0;
    background: white;
    color: black;
    font: 12pt/1.4 Georgia, serif;
  }

  .contenedor {
    max-width: none;
    padding: 0;
  }

  a {
    color: black;
    text-decoration: underline;
  }

  a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 0.85em;
    word-break: break-all;
  }

  h1, h2, h3 { break-after: avoid; }
  figure, table, .tarjeta { break-inside: avoid; }
  img { max-width: 100% !important; }
  p { orphans: 3; widows: 3; }
}

Errores frecuentes

  • No probarlo nunca. Abre la vista previa de impresión (o emula print en DevTools) de tus páginas importantes antes de publicarlas.
  • Dar la información solo con imágenes de fondo. Un icono puesto con background-image no se imprime por defecto. Si es contenido, usa <img> con alt.
  • Texto blanco sobre fondo oscuro. Sin gráficos de fondo, el texto desaparece. Pon color: black al imprimir.
  • print-color-adjust: exact en todo. Gasta tinta sin motivo. Úsalo solo donde el color informa.
  • Mostrar la URL de todos los enlaces. Los #ancla, mailto: y javascript: ensucian el texto. Filtra con a[href^="http"].
  • break-inside: avoid en contenedores enormes. Si el elemento no cabe en una hoja, se ignora o deja huecos en blanco. Úsalo en piezas pequeñas.
  • Usar las propiedades page-break-* en código nuevo. Funcionan, pero las actuales son break-before, break-after y break-inside.
  • Esconder el contenido principal por error. Un display: none en un selector demasiado general (header) puede quitar también el título del artículo. Usa clases concretas.

Resumen

HerramientaPara quéEjemplo
@media printEstilos solo al imprimir@media print { nav { display: none; } }
media="print"Hoja de estilos aparte para imprimir<link ... media="print">
@pageTamaño y márgenes de la hoja@page { size: A4; margin: 2cm; }
@page :firstEstilos de la primera hojamargin-top: 4cm
break-before: pageForzar salto antes de un elementoCada capítulo en hoja nueva
break-after: avoidEvitar salto despuésTítulos
break-inside: avoidNo partir un elementoTablas, figuras, tarjetas
orphans / widowsLíneas mínimas al cortar un párrafoorphans: 3
attr(href) en ::afterMostrar la URL de los enlacesa[href^="http"]::after
print-color-adjust: exactImprimir colores y fondosLeyendas de color
window.print()Abrir el cuadro de impresiónBotón “Imprimir”

Ya sabes adaptar tus páginas a pantalla y papel. En la siguiente lección construirás las piezas que se repiten en todas las webs: componentes en CSS.

Pruébalo tú

Cambia el código y pulsa Ejecutar (o Ctrl + Enter).

css-impresion.html
Resultado

Pon a prueba lo que has aprendido

[CSS] Al imprimir, ¿qué se lee después del enlace?
@media print {
  a[href^="http"]::after {
    content: " (" attr(href) ")";
  }
}

<a href="#horarios">Ver horarios</a>

[CSS] Quieres que cada capítulo de unos apuntes empiece en una hoja nueva al imprimir. ¿Qué regla usas?

[CSS] La leyenda de colores de un horario sale en blanco al imprimir, aunque en pantalla se ve bien. ¿Qué propiedad lo arregla?
.leyenda span {
  background: #16a34a;
}

[CSS] ¿Para qué sirve esta regla?
@page {
  size: A4 landscape;
  margin: 2cm;
}

[CSS] Has puesto break-inside: avoid en el <main> de un artículo de cinco páginas. ¿Qué pasa al imprimir?

¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.