Escribí un script CSS para colocar texto truncado de varias líneas con un botón «Leer más».

Me preguntaba si CSS permite formatear correctamente el texto truncado para que incluya varias líneas y, al presionar el botón «Mostrar más«, mostrar el texto completo.

La propiedad text-overflow: ellipsis no admite varias líneas. Pero recordé la propiedad line-clamp, que permite truncar texto de varias líneas.

Más detalles sobre el botón «Mostrar más»

Para crear el botón «Mostrar más«, no pude usar la etiqueta <button> o <a>. Para esto se necesita una etiqueta <label> y un checkbox. Esto es lo que resultó:

<div class="box">
  <input type="checkbox" id="expanded">
  <p>Hey, no me cortes así. Quiero expresar mi opinión y no me gusta que me pongan en una caja.</p>
  <!-- Nota: no encontré la manera de colocar un botón/etiqueta adicional en la línea dentro del párrafo después o antes del truncamiento. -->
  <label for="expanded" role="button">leer más</label>
</div>

Coloqué el checkbox justo antes del párrafo, por lo que puedo usar el pseudo-clase :checked para activar el truncamiento del texto:

input:checked + p {
  -webkit-line-clamp: unset;
}

Presiona el botón y en el párrafo se mostrará una versión recortada del texto.

¿Qué pasa con la accesibilidad?

El truco con el checkbox no solo es semánticamente incorrecto, sino que también limita las posibilidades de acceso a la funcionalidad para personas con discapacidad visual.

Además, se le asigna al checkbox la propiedad display: none. Esto interrumpe la navegación con el teclado. No se puede usar un checkbox oculto, y usar una etiqueta no ayuda. El evento de presionar la barra espaciadora/intro no redirige el evento al checkbox.

Para solucionar este problema, hice que el checkbox fuera enfocable, aunque todavía invisible:

input {
  opacity: 0;
  position: absolute;
  pointer-events: none;
}

Ahora se puede seleccionar el checkbox, pero sin un lector de pantalla no se puede saber si está activado o no, ya que es invisible. Para solucionar este problema, hice que la etiqueta herede el estilo de enfoque predeterminado del navegador cuando el checkbox está seleccionado:

input:focus ~ label {
  outline: -webkit-focus-ring-color auto 5px;
}

A continuación se muestra una versión demo combinada. Intenta presionar el botón con el ratón y luego usando la barra espaciadora.

See the Pen Texto Truncado CSS by Alex (@htmldesdecero) on CodePen.

¿Cómo mostrar el botón dinámicamente?

Pero, ¿cómo mostrar el botón dinámicamente cuando el texto del párrafo es demasiado largo para caber en el contenedor? Esta es la única función que no pude implementar con CSS. Porque requiere el uso del selector :truncated:

.read-more { display: none; }
p:truncated + .read-more { display: block; }

Por lo tanto, esto solo se puede implementar con JavaScript. Por ejemplo:

const ps = document.querySelectorAll('p');
const observer = new ResizeObserver(entries => {
  for (let entry of entries) {
    entry.target.classList[entry.target.scrollHeight > entry.contentRect.height ? 'add' : 'remove']('truncated');
  }
});

ps.forEach(p => {
  observer.observe(p);
});

Aquí hay una versión demo extendida:

See the Pen Texto Truncado CSS-JS by Alex (@htmldesdecero) on CodePen.

Categorizado en:

CSS,