jueves, 30 de mayo de 2013

Simular "text-overflow:ellipsis" para textos largos ( multilínea )

En CSS, si utilizamos las siguientes propiedades:
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
Podemos conseguir que un texto se corte a la anchura que queramos y se inserten automáticamente unos puntos suspensivos al final.



El problema es que sólo funciona para una única línea. El texto se corta cuando la línea sobrepasa la anchura del contenedor. Necesitamos incluir white-space: nowrap para evitar que el texto que no cabe se desplace a la línea siguiente.
Sería muy util poder hacer también algo como esto:



Es decir, tenemos un texto largo, de varias líneas ( sin white-space: nowrap ), y queremos que se corte mostrando "..." cuando supera la altura del contenedor.

Ellipsis multilínea con JavaScript

Sólo son necesarias unas líneas de JavaScript para conseguirlo. Supongamos que tenemos un texto largo en un div contenedor con una altura limitada:
<div id="container">
  <p>
  Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </p>
</div>

Tenemos el siguiente CSS para limitar la altura y anchura del contenedor y ocultar el texto que no cabe:
#container {
  width: 300px;
  height: 95px;
  overflow: hidden;
}
El texto quedaría cortado pero no tenemos ninguna indicación de ello:



Podemos solucionar el problema con unas lineas de JavaScript (y JQuery):
var containerHeight = $("#container").height();
var $text = $("#container p");

while ( $text.outerHeight() > containerHeight ) {
        $text.text(function (index, text) {
            return text.replace(/\W*\s(\S)*$/, '...');
       });
}
El resultado es:



Lo que hace este pequeño script es ir recortando palabras del final del texto hasta que la altura del texto es igual a la altura del contenedor.Toda la magia se realiza con la expresión regular:
text.replace(/\W*\s(\S)*$/, '...');
Básicamente esta instrucción sustituye la última palabra, junto con cualquier espacio en blanco que tenga delante, por "...". Esto se va repitiendo hasta que el texto encaja dentro del contenedor.

Creando una función genérica

Podemos hacerlo más flexible creando una función que incluya los "..." en cualquier texto largo que sobrepase el contenedor. Pasaremos como parámetro el id del div que contiene el texto.
La siguiente función es válida siempre que el marcado HTML sea como en el ejemplo anterior,el texto debe estar englobado en un <p></p> que está dentro del elemento que se pasa como parámetro. No es dificil cambiar la función para otra estructura.
function createEllipsis ( containerId ) {
    $container = $("#" + containerId);
    var containerHeight = $container.height();
    var $text = $container.find("p");

    while ( $text.outerHeight() > containerHeight ) {
        $text.text(function (index, text) {
            return text.replace(/\W*\s(\S)*$/, '...');
        });
    }
  }

Se utilizaría:
createEllipsis("container");

Hay tambien una solución para hacer algo parecido con CSS descrita en el post Multiline ellipsis in pure css pero tiene varios problemas. Necesita algún marcado extra en el HTML y, la más grave, si la línea en la que cortamos es corta (un punto y aparte), los puntos suspensivos quedan siempre pegados a la derecha y queda un hueco en blanco.

7 comentarios:

  1. Buen artículo, buscando snippets que hicieran una función algo más compleja he encontrado esto.
    Sencillo, básico y funcional, algo que muchas veces pasamos por alto, o nuestra "vagancia" o "productividad" buscamos la solución sencilla cuándo la tenemos en apenas 5 líneas.

    Gracias por hacerme sonreír hoy y darle un aviso a mi vagancia! Un saludo.

    ResponderEliminar
  2. No funciona, ya que, el css tiene un overflow hidden que esta sobrando.

    Link que el código funcionando:
    https://jsfiddle.net/xeneize100/cct4xy2L/2/

    ResponderEliminar
  3. Excelente!!!!!!!!!!!!!!!!!!!!!!!!! siga así salvando vidas!

    ResponderEliminar
  4. Gracias, una solución simple y clara.

    No te imaginas cuanto busque, tu ejemplo con outerHeight y outerWidth es justo lo que estoy buscando para dividir un extenso párrafo en líneas con un ancho máximo, luego la conversión a PDF es perfecta.

    ResponderEliminar
  5. Justo lo que buscaba!!! Graciasssss

    ResponderEliminar