Inserte puntos suspensivos (...) en la etiqueta HTML si el contenido es demasiado ancho

Resuelto BlaM asked hace 15 años • 24 respuestas

Tengo una página web con un diseño elástico que cambia su ancho si se cambia el tamaño de la ventana del navegador.

En este diseño hay titulares ( h2) que tendrán una longitud variable (en realidad son titulares de publicaciones de blog sobre las que no tengo control). Actualmente, si son más anchos que la ventana, están divididos en dos líneas.

¿Existe una solución elegante y probada (para varios navegadores), por ejemplo con jQuery, que acorte el HTML interno de esa etiqueta de título y agregue "..." si el texto fuera demasiado ancho para caber en una línea en la pantalla actual? ancho del contenedor?

BlaM avatar Feb 11 '09 20:02 BlaM
Aceptado

La siguiente solución CSS únicamente para truncar texto en una sola línea funciona con todos los navegadores enumerados en http://www.caniuse.com al momento de escribir este artículo, con la excepción de Firefox 6.0. Tenga en cuenta que JavaScript es totalmente innecesario a menos que necesite admitir el ajuste de texto de varias líneas o versiones anteriores de Firefox.

.ellipsis {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    -o-text-overflow: ellipsis;
}

Si necesita soporte para versiones anteriores de Firefox, consulte mi respuesta a esta otra pregunta .

Simon Lieschke avatar Jul 09 '2009 03:07 Simon Lieschke

Tengo una solución que funciona en FF3, Safari e IE6+ con texto de una sola línea y de varias líneas.

.ellipsis {
    white-space: nowrap;
    overflow: hidden;
}

.ellipsis.multiline {
    white-space: normal;
}

<div class="ellipsis" style="width: 100px; border: 1px solid black;">Lorem ipsum dolor sit amet, consectetur adipisicing elit</div>
<div class="ellipsis multiline" style="width: 100px; height: 40px; border: 1px solid black; margin-bottom: 100px">Lorem ipsum dolor sit amet, consectetur adipisicing elit</div>

<script type="text/javascript" src="/js/jquery.ellipsis.js"></script>
<script type="text/javascript">
$(".ellipsis").ellipsis();
</script>

jquery.ellipsis.js

(function($) {
    $.fn.ellipsis = function()
    {
        return this.each(function()
        {
            var el = $(this);

            if(el.css("overflow") == "hidden")
            {
                var text = el.html();
                var multiline = el.hasClass('multiline');
                var t = $(this.cloneNode(true))
                    .hide()
                    .css('position', 'absolute')
                    .css('overflow', 'visible')
                    .width(multiline ? el.width() : 'auto')
                    .height(multiline ? 'auto' : el.height())
                    ;

                el.after(t);

                function height() { return t.height() > el.height(); };
                function width() { return t.width() > el.width(); };

                var func = multiline ? height : width;

                while (text.length > 0 && func())
                {
                    text = text.substr(0, text.length - 1);
                    t.html(text + "...");
                }

                el.html(t.html());
                t.remove();
            }
        });
    };
})(jQuery);
alex avatar Jun 20 '2009 22:06 alex

Construí este código usando otras publicaciones, con las siguientes mejoras:

  1. Utiliza una búsqueda binaria para encontrar la longitud del texto adecuada.
  2. Maneja casos en los que los elementos de puntos suspensivos están inicialmente ocultos mediante la configuración de un evento de presentación única que vuelve a ejecutar el código de puntos suspensivos cuando el elemento se muestra por primera vez. Esto es útil para vistas maestras y detalladas o vistas de árbol donde algunos elementos no se muestran inicialmente.
  3. Opcionalmente agrega un atributo de título con el texto original para un efecto de desplazamiento.
  4. Agregado display: blockal estilo, para que los tramos funcionen.
  5. Utiliza el carácter de elipsis en lugar de 3 puntos.
  6. Ejecuta automáticamente el script para cualquier cosa con la clase .ellipsis

CSS:

.ellipsis {
        white-space: nowrap;
        overflow: hidden;
        display: block;
}

.ellipsis.multiline {
        white-space: normal;
}

jquery.ellipsis.js

(function ($) {

    // this is a binary search that operates via a function
    // func should return < 0 if it should search smaller values
    // func should return > 0 if it should search larger values
    // func should return = 0 if the exact value is found
    // Note: this function handles multiple matches and will return the last match
    // this returns -1 if no match is found
    function binarySearch(length, func) {
        var low = 0;
        var high = length - 1;
        var best = -1;
        var mid;

        while (low <= high) {
            mid = ~ ~((low + high) / 2); //~~ is a fast way to convert something to an int
            var result = func(mid);
            if (result < 0) {
                high = mid - 1;
            } else if (result > 0) {
                low = mid + 1;
            } else {
                best = mid;
                low = mid + 1;
            }
        }

        return best;
    }

    // setup handlers for events for show/hide
    $.each(["show", "toggleClass", "addClass", "removeClass"], function () {

        //get the old function, e.g. $.fn.show   or $.fn.hide
        var oldFn = $.fn[this];
        $.fn[this] = function () {

            // get the items that are currently hidden
            var hidden = this.find(":hidden").add(this.filter(":hidden"));

            // run the original function
            var result = oldFn.apply(this, arguments);

            // for all of the hidden elements that are now visible
            hidden.filter(":visible").each(function () {
                // trigger the show msg
                $(this).triggerHandler("show");
            });

            return result;
        };
    });

    // create the ellipsis function
    // when addTooltip = true, add a title attribute with the original text
    $.fn.ellipsis = function (addTooltip) {

        return this.each(function () {
            var el = $(this);

            if (el.is(":visible")) {

                if (el.css("overflow") === "hidden") {
                    var content = el.html();
                    var multiline = el.hasClass('multiline');
                    var tempElement = $(this.cloneNode(true))
                        .hide()
                        .css('position', 'absolute')
                        .css('overflow', 'visible')
                        .width(multiline ? el.width() : 'auto')
                        .height(multiline ? 'auto' : el.height())
                    ;

                    el.after(tempElement);

                    var tooTallFunc = function () {
                        return tempElement.height() > el.height();
                    };

                    var tooWideFunc = function () {
                        return tempElement.width() > el.width();
                    };

                    var tooLongFunc = multiline ? tooTallFunc : tooWideFunc;

                    // if the element is too long...
                    if (tooLongFunc()) {

                        var tooltipText = null;
                        // if a tooltip was requested...
                        if (addTooltip) {
                            // trim leading/trailing whitespace
                            // and consolidate internal whitespace to a single space
                            tooltipText = $.trim(el.text()).replace(/\s\s+/g, ' ');
                        }

                        var originalContent = content;

                        var createContentFunc = function (i) {
                            content = originalContent.substr(0, i);
                            tempElement.html(content + "…");
                        };

                        var searchFunc = function (i) {
                            createContentFunc(i);
                            if (tooLongFunc()) {
                                return -1;
                            }
                            return 0;
                        };

                        var len = binarySearch(content.length - 1, searchFunc);

                        createContentFunc(len);

                        el.html(tempElement.html());

                        // add the tooltip if appropriate
                        if (tooltipText !== null) {
                            el.attr('title', tooltipText);
                        }
                    }

                    tempElement.remove();
                }
            }
            else {
                // if this isn't visible, then hook up the show event
                el.one('show', function () {
                    $(this).ellipsis(addTooltip);
                });
            }
        });
    };

    // ellipsification for items with an ellipsis
    $(document).ready(function () {
        $('.ellipsis').ellipsis(true);
    });

} (jQuery));
Adam Tegen avatar Jan 30 '2012 21:01 Adam Tegen