Calcular ancho de texto con JavaScript

467

Me gustaría usar JavaScript para calcular el ancho de una cadena. ¿Es esto posible sin tener que usar un tipo de letra monoespacio?

Si no está integrado, mi única idea es crear una tabla de anchos para cada carácter, pero esto no es razonable, especialmente para Unicode y diferentes tamaños de letra (y todos los navegadores).

Jacob
fuente
10
Tenga en cuenta que si usa fuentes externas, tendrá que usar las técnicas a continuación después de que se hayan cargado. Es posible que no se dé cuenta de esto si los tiene en caché o si tiene instaladas versiones locales.
Seth W. Klein

Respuestas:

355

Crea un DIV con los siguientes estilos. En su JavaScript, establezca el tamaño de fuente y los atributos que está tratando de medir, coloque su cadena en el DIV y luego lea el ancho y alto actuales del DIV. Se estirará para adaptarse al contenido y el tamaño estará dentro de unos pocos píxeles del tamaño de la cadena representada.

var fontSize = 12;
var test = document.getElementById("Test");
test.style.fontSize = fontSize;
var height = (test.clientHeight + 1) + "px";
var width = (test.clientWidth + 1) + "px"

console.log(height, width);
#Test
{
    position: absolute;
    visibility: hidden;
    height: auto;
    width: auto;
    white-space: nowrap; /* Thanks to Herb Caudill comment */
}
<div id="Test">
    abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
</div>

CMPalmer
fuente
8
Lo único que agregaría es que esto puede dar las dimensiones incorrectas dependiendo de qué estilos se usen. Recuerde que puede tener estilos como p {letter-spacing: 0.1em; } que un elemento DIV no reflejaría. Debe asegurarse de que los estilos en el lugar sean apropiados para el lugar donde usará el texto.
Jim
55
Comentario de Ditto Jim: verifique dos veces para asegurarse de que el contenedor, div en este caso, no tenga otros estilos aplicados a través de las reglas de selección de CSS que puede que no conozca en ese momento. Elimine todos los estilos relevantes del contenedor antes de aplicar los que le interesan antes de medir.
Jason Bunting
44
También debe poner en el espacio en blanco: nowrap si cree que el texto excederá el ancho del navegador.
Herb Caudill
55
@BBog todo ese pirateo es por eso que sugiero un enfoque diferente, menos hacky, abajo. Echa un vistazo aquí .
Domi
11
¿Solo tiene curiosidad por saber para qué +1sirve cada dimensión?
Kip
385

En HTML 5 , puede usar el método Canvas.measureText (más explicaciones aquí ).

Prueba este violín :

/**
 * Uses canvas.measureText to compute and return the width of the given text of given font in pixels.
 * 
 * @param {String} text The text to be rendered.
 * @param {String} font The css font descriptor that text is to be rendered with (e.g. "bold 14px verdana").
 * 
 * @see /programming/118241/calculate-text-width-with-javascript/21015393#21015393
 */
function getTextWidth(text, font) {
    // re-use canvas object for better performance
    var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
    var context = canvas.getContext("2d");
    context.font = font;
    var metrics = context.measureText(text);
    return metrics.width;
}

console.log(getTextWidth("hello there!", "bold 12pt arial"));  // close to 86

Este violín compara este método de Canvas con una variación del método basado en DOM de Bob Monteverde , para que pueda analizar y comparar la precisión de los resultados.

Este enfoque tiene varias ventajas, que incluyen:

NOTA: Cuando agregue el texto a su DOM, recuerde también tener en cuenta el relleno, el margen y el borde .

NOTA 2: en algunos navegadores, este método produce una precisión de subpíxel (el resultado es un número de coma flotante), en otros no (el resultado es solo un int). Es posible que desee ejecutar Math.floor(o Math.ceil) en el resultado, para evitar inconsistencias. Dado que el método basado en DOM nunca tiene una precisión de subpíxel, este método tiene una precisión aún mayor que los otros métodos aquí.

De acuerdo con este jsperf (gracias a los contribuyentes en los comentarios), el método Canvas y el método basado en DOM son casi igualmente rápidos, si se agrega el almacenamiento en caché al método basado en DOM y no está utilizando Firefox. En Firefox, por alguna razón, este método de Canvas es mucho más rápido que el método basado en DOM (a partir de septiembre de 2014).

Domi
fuente
77
Esta es una opción increíble, no lo sabía. ¿Alguna vez comparó el rendimiento de esto con el rendimiento de la medición en el DOM?
SimplGy 01 de
2
Agregué el almacenamiento en caché a ese punto de referencia jsperf. Ahora los dos métodos están más o menos a la par: jsperf.com/measure-text-width/4
Brandon Bloom
1
@ Martin, ¿eh? ¿Qué tiene que ver "muchos elementos HTML" con algo aquí? El objeto de lienzo en este ejemplo ni siquiera está adjunto al DOM. E incluso aparte de eso, cambiar la fuente en un contexto de dibujo de lienzo ni siquiera afecta el lienzo hasta que usted strokeText()o fillText(). ¿Quizás quisiste comentar una respuesta diferente?
Ajedi32
1
Buena solución He envuelto un par de otros métodos alrededor de la respuesta de Domi para poder: Obtener una cadena (potencialmente) truncada con puntos suspensivos (...) al final si no cabe en un espacio dado (la mayor parte de la cadena se utilizará lo más posible): pase un elemento JQuery que contenga la cadena (posiblemente truncada) y determine los atributos de fuente dinámicamente para que no tengan que estar codificados, permitiendo que los atributos de fuente CSS cambien sin romperse El diseño. JSFiddle Aquí: jsfiddle.net/brebey/1q94gLsu/6/embed
BRebey
2
¡Bien porque el usuario no lo ve!
clabe45
110

Aquí hay uno que batí sin ningún ejemplo. Parece que todos estamos en la misma página.

String.prototype.width = function(font) {
  var f = font || '12px arial',
      o = $('<div></div>')
            .text(this)
            .css({'position': 'absolute', 'float': 'left', 'white-space': 'nowrap', 'visibility': 'hidden', 'font': f})
            .appendTo($('body')),
      w = o.width();

  o.remove();

  return w;
}

Usarlo es simple: "a string".width()

** Agregado white-space: nowrappara que se puedan calcular cadenas con un ancho mayor que el ancho de la ventana.

Bob Monteverde
fuente
2
Gracias JordanC. Una cosa que agregaría es que si llama a esto muchas veces en la misma página y el rendimiento es un problema, podría persistir en el DIV y simplemente cambiar el contenido y verificar el ancho. Simplemente lo hice de esta manera, una vez que todo estuviera dicho y hecho, el DOM sería el mismo que cuando comenzaste
Bob Monteverde el
3
No agregaría este método Stringya que disminuye la separación de preocupaciones de su programa (código central separado frente a código UI). Imagine que quiere portar su código central a una plataforma con un marco de interfaz de usuario muy diferente ...
Domi
23
Este es un mal diseño , no solo combina su modelo con su vista, sino que también lo combina directamente con jQuery. Además de eso, esto es un infierno de reflujo, esto definitivamente no escalaría bien.
James
1
Si desea el valor flotante, puede usar o[0].getBoundingClientRect().widthcomo se sugiere aquí: stackoverflow.com/a/16072668/936397
Alexander Olsson
1
@virus dijo que más de 100 personas probablemente tampoco se preocupen por el rendimiento ... Sin embargo, no hace que lo que dije sea menos válido o verdadero.
James
30

jQuery:

(function($) {

 $.textMetrics = function(el) {

  var h = 0, w = 0;

  var div = document.createElement('div');
  document.body.appendChild(div);
  $(div).css({
   position: 'absolute',
   left: -1000,
   top: -1000,
   display: 'none'
  });

  $(div).html($(el).html());
  var styles = ['font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing'];
  $(styles).each(function() {
   var s = this.toString();
   $(div).css(s, $(el).css(s));
  });

  h = $(div).outerHeight();
  w = $(div).outerWidth();

  $(div).remove();

  var ret = {
   height: h,
   width: w
  };

  return ret;
 }

})(jQuery);
Deepak Nadar
fuente
27

Esto funciona para mi ...

// Handy JavaScript to measure the size taken to render the supplied text;
// you can supply additional style information too if you have it.

function measureText(pText, pFontSize, pStyle) {
    var lDiv = document.createElement('div');

    document.body.appendChild(lDiv);

    if (pStyle != null) {
        lDiv.style = pStyle;
    }
    lDiv.style.fontSize = "" + pFontSize + "px";
    lDiv.style.position = "absolute";
    lDiv.style.left = -1000;
    lDiv.style.top = -1000;

    lDiv.innerHTML = pText;

    var lResult = {
        width: lDiv.clientWidth,
        height: lDiv.clientHeight
    };

    document.body.removeChild(lDiv);
    lDiv = null;

    return lResult;
}
Pete
fuente
Hola, su respuesta es realmente útil, pero use .cssText en lugar de .style para admitir IE 8 y versiones inferiores.
Dilip Rajkumar
Esta respuesta es excelente, pero cuando genero un gran texto, se vuelve inexacto unos pocos píxeles. ¿Es porque el ancho no es un entero?
Bobtroopo
20

La biblioteca de JavaScript ExtJS tiene una gran clase llamada Ext.util.TextMetrics que "proporciona mediciones precisas de píxeles para bloques de texto para que pueda determinar exactamente qué tan alto y ancho, en píxeles, será un bloque de texto dado". Puede usarlo directamente o ver su código fuente para ver cómo se hace.

http://docs.sencha.com/extjs/6.5.3/modern/Ext.util.TextMetrics.html

gran lep
fuente
1
ExtJS tiene una licencia extraña. O le paga a los mantenedores actuales, a la Compañía Sencha para que lo use, o debe abrir el código fuente completo en su aplicación. Este es un espectáculo para la mayoría de las empresas. jQuery, por otro lado, usa la licencia MIT altamente permisiva.
devdanke
1
¿JavaScript no cumple automáticamente con los requisitos de código abierto? Sirve la fuente a cualquiera que vea la página.
PatrickO
10
Hay una diferencia entre poder ver el código fuente y el código abierto, que se define mediante licencia.
Parker Ault
Gracias de aquellos de nosotros que todavía usamos ExtJS :-)
Monarch Wadia
1
deberías haber dejado que el ExtJS descanse en paz
canbax
19

¡Me gusta tu "única idea" de hacer un mapa de ancho de caracteres estático! En realidad funciona bien para mis propósitos. A veces, por razones de rendimiento o porque no tiene fácil acceso a un DOM, es posible que solo desee una calculadora independiente rápida y hacky calibrada para una sola fuente. Así que aquí hay uno calibrado para Helvetica; pasar una cadena y (opcionalmente) un tamaño de fuente:

function measureText(str, fontSize = 10) {
  const widths = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2796875,0.2765625,0.3546875,0.5546875,0.5546875,0.8890625,0.665625,0.190625,0.3328125,0.3328125,0.3890625,0.5828125,0.2765625,0.3328125,0.2765625,0.3015625,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.2765625,0.2765625,0.584375,0.5828125,0.584375,0.5546875,1.0140625,0.665625,0.665625,0.721875,0.721875,0.665625,0.609375,0.7765625,0.721875,0.2765625,0.5,0.665625,0.5546875,0.8328125,0.721875,0.7765625,0.665625,0.7765625,0.721875,0.665625,0.609375,0.721875,0.665625,0.94375,0.665625,0.665625,0.609375,0.2765625,0.3546875,0.2765625,0.4765625,0.5546875,0.3328125,0.5546875,0.5546875,0.5,0.5546875,0.5546875,0.2765625,0.5546875,0.5546875,0.221875,0.240625,0.5,0.221875,0.8328125,0.5546875,0.5546875,0.5546875,0.5546875,0.3328125,0.5,0.2765625,0.5546875,0.5,0.721875,0.5,0.5,0.5,0.3546875,0.259375,0.353125,0.5890625]
  const avg = 0.5279276315789471
  return str
    .split('')
    .map(c => c.charCodeAt(0) < widths.length ? widths[c.charCodeAt(0)] : avg)
    .reduce((cur, acc) => acc + cur) * fontSize
}

Esa matriz fea gigante tiene anchos de caracteres ASCII indexados por código de caracteres. Por lo tanto, esto solo es compatible con ASCII (de lo contrario, supone un ancho de caracteres promedio). Afortunadamente, el ancho básicamente se escala linealmente con el tamaño de fuente, por lo que funciona bastante bien en cualquier tamaño de fuente. Es notablemente carente de conocimiento de kerning o ligaduras o lo que sea.

Para "calibrar" acabo de representar cada carácter hasta el código 126 (la poderosa tilde) en un svg y obtuve el cuadro delimitador y lo guardé en esta matriz; Más código y explicación y demostración aquí .

Toph
fuente
1
esa es una solución inteligente, buena :) Siempre estoy usando la misma fuente / tamaño, así que me queda bien. El rendimiento de las soluciones DOM / Canvas me pareció un problema real, esto es realmente limpio, ¡salud!
mikeapr4
1
elimina la necesidad de lienzo +1
frage
Puede deshacerse de él * fontSizey simplemente usarlos
Matt Fletcher
¡Qué respuesta tan asombrosa!
casi
7

Puede usar el lienzo para no tener que lidiar tanto con las propiedades css:

var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
ctx.font = "20pt Arial";  // This can be set programmaticly from the element's font-style if desired
var textWidth = ctx.measureText($("#myElement").text()).width;
rysama
fuente
¿No es mucho más pesado (obtener el contexto 2D, etc.) que crear un elemento DOM y especificar las propiedades CSS para él?
Pharao2k
1
Este es un enfoque limpio si ya está utilizando el lienzo para algo. Pero MUY LENTO. La llamada a measureText solo tarda entre 8 y 10 ms (con Chrome).
Rui Marques
6
<span id="text">Text</span>

<script>
var textWidth = document.getElementById("text").offsetWidth;
</script>

Esto debería funcionar siempre que la etiqueta <span> no tenga otros estilos aplicados. offsetWidth incluirá el ancho de cualquier borde, relleno horizontal, ancho de la barra de desplazamiento vertical, etc.

Bryan Friedman
fuente
Eso es más o menos lo que hace que las soluciones superiores, pero como su texto puede dividirse en varias líneas, agregan algunos estilos CSS al texto para obtener el ancho real del texto completo.
Adrian Maire
2

Los recortes de código a continuación, "calculan" el ancho de la etiqueta span, le agrega "..." si es demasiado largo y reduce la longitud del texto, hasta que encaje en su padre (o hasta que haya intentado más de mil veces)

CSS

div.places {
  width : 100px;
}
div.places span {
  white-space:nowrap;
  overflow:hidden;
}

HTML

<div class="places">
  <span>This is my house</span>
</div>
<div class="places">
  <span>And my house are your house</span>
</div>
<div class="places">
  <span>This placename is most certainly too wide to fit</span>
</div>

JavaScript (con jQuery)

// loops elements classed "places" and checks if their child "span" is too long to fit
$(".places").each(function (index, item) {
    var obj = $(item).find("span");
    if (obj.length) {
        var placename = $(obj).text();
        if ($(obj).width() > $(item).width() && placename.trim().length > 0) {
            var limit = 0;
            do {
                limit++;
                                    placename = placename.substring(0, placename.length - 1);
                                    $(obj).text(placename + "...");
            } while ($(obj).width() > $(item).width() && limit < 1000)
        }
    }
});
Techek
fuente
2
Intente una búsqueda binaria en lugar de recorrer 1 carácter a la vez: vea mi comentario sobre la respuesta de Alex a stackoverflow.com/questions/536814/…
StanleyH
@StanleyH: Buena idea: implementaré su sugerencia lo antes posible.
Techek
2

Lo mejor es detectar si el texto encaja justo antes de mostrar el elemento. Entonces puede usar esta función que no requiere que el elemento esté en la pantalla.

function textWidth(text, fontProp) {
    var tag = document.createElement("div");
    tag.style.position = "absolute";
    tag.style.left = "-999em";
    tag.style.whiteSpace = "nowrap";
    tag.style.font = fontProp;
    tag.innerHTML = text;

    document.body.appendChild(tag);

    var result = tag.clientWidth;

    document.body.removeChild(tag);

    return result;
}

Uso:

if ( textWidth("Text", "bold 13px Verdana") > elementWidth) {
    ...
}
artnikpro
fuente
2

En caso de que alguien más haya llegado aquí buscando una forma de medir el ancho de una cadena y una forma de saber cuál es el tamaño de fuente más grande que se ajustará a un ancho particular, aquí hay una función que se basa en la solución de @ Domi con una búsqueda binaria :

/**
 * Find the largest font size (in pixels) that allows the string to fit in the given width.
 * 
 * @param {String} text The text to be rendered.
 * @param {String} font The css font descriptor that text is to be rendered with (e.g. "bold ?px verdana") -- note the use of ? in place of the font size.
 * @param {width} the width in pixels the string must fit in
 * @param {minFontPx} the smallest acceptable font size in pixels
 * @param {maxFontPx} the largest acceptable font size in pixels
**/
function GetTextSizeForWidth( text, font, width, minFontPx, maxFontPx )
{
    for ( ; ; )
    {
        var s = font.replace( "?", maxFontPx );
        var w = GetTextWidth( text, s );
        if ( w <= width )
        {
            return maxFontPx;
        }

        var g = ( minFontPx + maxFontPx ) / 2;

        if ( Math.round( g ) == Math.round( minFontPx ) || Math.round( g ) == Math.round( maxFontPx ) )
        {
            return g;
        }

        s = font.replace( "?", g );
        w = GetTextWidth( text, s );
        if ( w >= width )
        {
            maxFontPx = g;
        }
        else
        {
            minFontPx = g;
        }
    }
}
M Katz
fuente
Esto funciona de manera sorprendente (junto con el código de la respuesta de Domi)
r3wt
1

Prueba este código:

function GetTextRectToPixels(obj)
{
var tmpRect = obj.getBoundingClientRect();
obj.style.width = "auto"; 
obj.style.height = "auto"; 
var Ret = obj.getBoundingClientRect(); 
obj.style.width = (tmpRect.right - tmpRect.left).toString() + "px";
obj.style.height = (tmpRect.bottom - tmpRect.top).toString() + "px"; 
return Ret;
}
Jason Bracey
fuente
1

El ancho y la altura de un texto se pueden obtener con clientWidthyclientHeight

var element = document.getElementById ("mytext");

var width = element.clientWidth;
var height = element.clientHeight;

asegúrese de que la propiedad de posición de estilo esté establecida en absoluta

element.style.position = "absolute";

no se requiere estar dentro de a div, puede estar dentro de a po aspan

Gjaa
fuente
1

Partiendo de la respuesta de Deepak Nadar , cambié los parámetros de las funciones para aceptar estilos de texto y fuente. No necesita hacer referencia a un elemento. Además, fontOptionstienen valores predeterminados, por lo que no necesita suministrarlos todos.

(function($) {
  $.format = function(format) {
    return (function(format, args) {
      return format.replace(/{(\d+)}/g, function(val, pos) {
        return typeof args[pos] !== 'undefined' ? args[pos] : val;
      });
    }(format, [].slice.call(arguments, 1)));
  };
  $.measureText = function(html, fontOptions) {
    fontOptions = $.extend({
      fontSize: '1em',
      fontStyle: 'normal',
      fontWeight: 'normal',
      fontFamily: 'arial'
    }, fontOptions);
    var $el = $('<div>', {
      html: html,
      css: {
        position: 'absolute',
        left: -1000,
        top: -1000,
        display: 'none'
      }
    }).appendTo('body');
    $(fontOptions).each(function(index, option) {
      $el.css(option, fontOptions[option]);
    });
    var h = $el.outerHeight(), w = $el.outerWidth();
    $el.remove();
    return { height: h, width: w };
  };
}(jQuery));

var dimensions = $.measureText("Hello World!", { fontWeight: 'bold', fontFamily: 'arial' });

// Font Dimensions: 94px x 18px
$('body').append('<p>').text($.format('Font Dimensions: {0}px x {1}px', dimensions.width, dimensions.height));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Mr. Polywhirl
fuente
0

Supongo que esto es bastante similar a la entrada de Depak, pero se basa en el trabajo de Louis Lazaris publicado en un artículo en una impresionante página web

(function($){

        $.fn.autofit = function() {             

            var hiddenDiv = $(document.createElement('div')),
            content = null;

            hiddenDiv.css('display','none');

            $('body').append(hiddenDiv);

            $(this).bind('fit keyup keydown blur update focus',function () {
                content = $(this).val();

                content = content.replace(/\n/g, '<br>');
                hiddenDiv.html(content);

                $(this).css('width', hiddenDiv.width());

            });

            return this;

        };
    })(jQuery);

El evento fit se usa para ejecutar la llamada a la función inmediatamente después de que la función esté asociada al control.

por ejemplo: $ ('input'). autofit (). trigger ("fit");

Mauricio
fuente
0

Sin jQuery:

String.prototype.width = function (fontSize) {
    var el,
        f = fontSize + " px arial" || '12px arial';
    el = document.createElement('div');
    el.style.position = 'absolute';
    el.style.float = "left";
    el.style.whiteSpace = 'nowrap';
    el.style.visibility = 'hidden';
    el.style.font = f;
    el.innerHTML = this;
    el = document.body.appendChild(el);
    w = el.offsetWidth;
    el.parentNode.removeChild(el);
    return w;
}

// Usage
"MyString".width(12);
v1r00z
fuente
cuando establece un número no funciona, porque no es necesario un espacio, si lo elimina, funcionará bien: fontSize + "px arial" -> fontSize + "px arial", solo eso.
Alberto Acuña
0

Violín de ejemplo de trabajo: http://jsfiddle.net/tdpLdqpo/1/

HTML:

<h1 id="test1">
    How wide is this text?
</h1>
<div id="result1"></div>
<hr/>
<p id="test2">
    How wide is this text?
</p>
<div id="result2"></div>
<hr/>
<p id="test3">
    How wide is this text?<br/><br/>
    f sdfj f sdlfj lfj lsdk jflsjd fljsd flj sflj sldfj lsdfjlsdjkf sfjoifoewj flsdjfl jofjlgjdlsfjsdofjisdojfsdmfnnfoisjfoi  ojfo dsjfo jdsofjsodnfo sjfoj ifjjfoewj fofew jfos fojo foew jofj s f j
</p>
<div id="result3"></div>

Código JavaScript:

function getTextWidth(text, font) {
    var canvas = getTextWidth.canvas ||
        (getTextWidth.canvas = document.createElement("canvas"));
    var context = canvas.getContext("2d");
    context.font = font;
    var metrics = context.measureText(text);
    return metrics.width;
};

$("#result1")
.text("answer: " +
    getTextWidth(
             $("#test1").text(),
             $("#test1").css("font")) + " px");

$("#result2")
    .text("answer: " +
        getTextWidth(
             $("#test2").text(),
             $("#test2").css("font")) + " px");

$("#result3")
    .text("answer: " +
        getTextWidth(
             $("#test3").text(),
             $("#test3").css("font")) + " px");
Jason Williams
fuente
0

El Element.getClientRects()método devuelve una colección de DOMRectobjetos que indican los rectángulos delimitadores para cada cuadro de borde CSS en un cliente. El valor devuelto es una colección de DOMRectobjetos, uno para cada cuadro de borde CSS asociado con el elemento. Cada DOMRectobjeto contiene de sólo lectura left, top, righty bottomlas propiedades que describen el cuadro de frontera, en píxeles, con el pariente superior izquierda a la parte superior izquierda de la ventana gráfica.

Element.getClientRects () de Mozilla Contributors está licenciado bajo CC-BY-SA 2.5 .

Al resumir todos los anchos de rectángulo devueltos se obtiene el ancho total del texto en píxeles.

document.getElementById('in').addEventListener('input', function (event) {
    var span = document.getElementById('text-render')
    span.innerText = event.target.value
    var rects = span.getClientRects()
    var widthSum = 0
    for (var i = 0; i < rects.length; i++) {
        widthSum += rects[i].right - rects[i].left
    }
    document.getElementById('width-sum').value = widthSum
})
<p><textarea id='in'></textarea></p>
<p><span id='text-render'></span></p>
<p>Sum of all widths: <output id='width-sum'>0</output>px</p>

transistor09
fuente
0

Hice un pequeño módulo ES6 (usa jQuery):

import $ from 'jquery';

const $span=$('<span>');
$span.css({
    position: 'absolute',
    display: 'none'
}).appendTo('body');

export default function(str, css){
    $span[0].style = ''; // resetting the styles being previously set
    $span.text(str).css(css || {});
    return $span.innerWidth();
}

Fácil de usar:

import stringWidth from './string_width';
const w = stringWidth('1-3', {fontSize: 12, padding: 5});

Lo bueno que puedes notar es que permite tener en cuenta los atributos CSS, ¡incluso los rellenos!

Roman86
fuente
0

También puede hacer esto con createRange, que es más preciso, que la técnica de clonación de texto:

function getNodeTextWidth(nodeWithText) {
    var textNode = $(nodeWithText).contents().filter(function () {
        return this.nodeType == Node.TEXT_NODE;
    })[0];
    var range = document.createRange();
    range.selectNode(textNode);
    return range.getBoundingClientRect().width;
}
Inc33
fuente
-1
var textWidth = (function (el) {
    el.style.position = 'absolute';
    el.style.top = '-1000px';
    document.body.appendChild(el);

    return function (text) {
        el.innerHTML = text;
        return el.clientWidth;
    };
})(document.createElement('div'));
kavun
fuente