Line Clampin’ (truncamiento de texto de varias líneas) | Programar Plus

Quieres X líneas de texto. Cualquier cosa después de eso: cortado con gracia. Eso es “sujeción de línea” y es un deseo perfectamente legítimo. Cuando puede contar con que el texto tenga un cierto número de líneas, puede crear cuadrículas más sólidas y confiables a partir de los elementos que contienen ese texto, así como lograr cierta armonía estética simétrica.

Hay un par de formas de hacerlo, ninguna de ellas espectacular.

En caso de que la explicación no haya sido clara, imagina que tienes un código HTML como este:

<div class="module">
  <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>
</div>

Y desea limitarlo a exactamente tres líneas en un contenedor. Como esto:

En todos estos ejemplos, supongamos que tenemos un “módulo”.

.module {
  width: 250px;
  overflow: hidden;
}

La forma estandarizada

Solía ​​​​llamar a esto “la forma extraña de WebKit flexbox”, pero en un giro extra extraño, la especificación ahora incluye esto como parte del módulo de desbordamiento, el antiguo flexbox y todo. Y, Firefox lo implementó así. Y con Edge-gone-Chromium, esta extraña técnica se ha vuelto mucho más útil en lugar de menos.

.line-clamp {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;  
}

A pesar de la extraña sintaxis, esto es increíble y es exactamente lo que necesitamos. Aquí hay un patio de recreo para jugar con él:

Para ser justos, es realmente raro. ¿Por qué tiene que ser una cosa de flexbox (la versión anterior)? No funciona sin eso. Y es extremadamente frágil. Digamos que desea que el módulo (o el párrafo) tenga algo de relleno. No puede porque el relleno expondrá líneas adicionales. Eso es lo que obtenemos con las propiedades originalmente no estandarizadas a medias.

El camino del desvanecimiento

La raíz de esta técnica es establecer la altura del módulo de forma predecible. Digamos que usted establece el line-height a 1.2em. Si queremos exponer tres líneas de texto, podemos hacer que la altura del contenedor 3.6em (1,2 em × 3). El desbordamiento oculto ocultará el resto.

Pero puede ser un poco incómodo cortar el texto así. Idealmente, agregaríamos puntos suspensivos, pero no podemos posicionarlos de manera confiable. Entonces, en su lugar, desvaneceremos el texto logrando el mismo tipo de comunicación (“hay más…”).

Para desvanecer la última línea, creamos un cuadro (un pseudoelemento funcionará muy bien) y superponemos un degradado de color transparente a color de fondo en la parte superior. Hacerlo casi tan ancho como el contenedor es mejor en caso de que la última línea sea corta. porque conocemos la line-height, podemos hacer que el cuadro del pseudoelemento tenga exactamente una línea de alto.

.fade {
  position: relative;
  height: 3.6em; /* exactly three lines */
}
.fade::after {
  content: "";
  text-align: right;
  position: absolute;
  bottom: 0;
  right: 0;
  width: 70%;
  height: 1.2em;
  background: linear-gradient(to right, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1) 50%);
}

El camino del desbordamiento de la ópera

Opera, como su propio motor de renderizado, ya no existe. Solo dejo esto por razones históricas.

Al igual que WebKit, Opera tiene su propia forma de manejar esto. Aplican puntos suspensivos en la línea que desee. Por supuesto, el tiempo corre para Presto (el motor de renderizado de Opera antes de Blink), por lo que esto no es particularmente útil. Sin embargo, tal vez aún pueda informar una implementación futura.

.last-line {
  height: 3.6em; /* exactly three lines */
  text-overflow: -o-ellipsis-lastline;
}

El estilo de Clamp.js

Donde hay voluntad hay un camino (con JavaScript). Creo que eso es un dicho. Joseph J. Schmitt tiene una excelente cosa de JavaScript sin biblioteca llamada Clamp.js para hacer que esto suceda en una forma de navegador cruzado.

var module = document.getElementById("clamp-this-module");

$clamp(module, {clamp: 3});

Asegúrese de orientar el elemento con el texto directamente dentro de él. Originalmente intenté poner la ID en el módulo, que funcionó en Chrome/Safari, pero falló en Firefox. Poniéndolo en el <p> lo hizo funcionar en ambos (Thx Merri).

Ocultar desbordamiento y colocar puntos suspensivos al estilo CSS puro

El truco es establecer un max-height igual al número máximo de líneas multiplicado por el line-height.

html {
  --lh: 1.4rem;
  line-height: var(--lh);
}

.truncate-overflow {
  --max-lines: 3;
  position: relative;
  max-height: calc(var(--lh) * var(--max-lines));
  overflow: hidden;
  padding-right: 1rem; /* space for ellipsis */
}
.truncate-overflow::before {
  position: absolute;
  content: "...";
  inset-block-end: 0; /* "bottom" */
  inset-inline-end: 0; /* "right" */
}
.truncate-overflow::after {
  content: "";
  position: absolute;
  inset-inline-end: 0; /* "right" */
  width: 1rem;
  height: 1rem;
  background: white;
}

El resto de eso es colocar puntos suspensivos “…” al final de las líneas, pero solo si el texto excede el número máximo de líneas.

Las demostraciones

Actualización: ¡Más buenas maneras!

  • Hay una forma excepcionalmente inteligente de CSS para hacer esto publicada en el blog de Mobify Actualizar: enlace eliminado, blog muerto, agregado en la técnica aquí.
  • Vesa Piittinen creó un método alternativo a Clamp.js.
    “A diferencia de Clamp.js, retiene todo el texto dentro del elemento sujeto y usa text-overflow para hacer la magia.
  • FT Labs también ha creado un complemento de JavaScript para hacer el trabajo. Es bueno que no tengas que especificar el número de líneas, simplemente sucede cuando el texto desborda el contenedor, por lo que la decisión de diseño permanece en el CSS.
  • Sucinto: “Un pequeño complemento de jQuery para truncar varias líneas de texto”.

Estos ejemplos se han añadido al Pen principal.

También está Shave de DollarShaveClub: