Calcular a largura do texto com JavaScript

467

Eu gostaria de usar JavaScript para calcular a largura de uma string. Isso é possível sem a necessidade de usar um tipo de letra monoespaçada?

Se não estiver embutido, minha única idéia é criar uma tabela de larguras para cada caractere, mas isso não é razoável, especialmente para suportar Unicode e tamanhos de tipos diferentes (e todos os navegadores).

Jacob
fonte
10
Lembre-se de que, se você estiver usando fontes externas, precisará usar as técnicas abaixo após o carregamento. Você pode não perceber isso se os tiver em cache ou se tiver versões locais instaladas.
Seth W. Klein

Respostas:

355

Crie um DIV com os seguintes estilos. No seu JavaScript, defina o tamanho da fonte e os atributos que você está tentando medir, coloque sua string no DIV e leia a largura e a altura atuais do DIV. Ele se estenderá para caber no conteúdo e o tamanho estará a poucos pixels do tamanho renderizado da sequência.

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
fonte
8
A única coisa que eu acrescentaria é que isso pode dar as dimensões erradas, dependendo de quais estilos são usados. Lembre-se de que você pode ter estilos como p {espaçamento entre letras: 0.1em; } que um elemento DIV não refletiria. Você deve garantir que os estilos no local sejam apropriados para onde você usará o texto.
Jim
5
O mesmo comentário de Jim - verifique duas vezes para garantir que o contêiner, div neste caso, não tenha outros estilos aplicados a ele por meio de regras de seleção de css que você talvez não conheça no momento. Retire todos os estilos relevantes do contêiner antes de aplicar os que mais lhe interessam antes de medir.
Jason Bunting
44
Você também deve colocar espaço em branco: nowrap se achar que o texto excederá a largura do navegador.
Herb Caudill
5
@BBog tudo o que hackear é por isso que sugiro uma abordagem diferente, menos hacky, no andar de baixo. Dê uma olhada aqui .
Domi
11
Apenas curioso para que +1serve cada dimensão?
Kip
385

No HTML 5 , você pode apenas usar o método Canvas.measureText (mais explicações aqui ).

Experimente este violino :

/**
 * 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

Esse violão compara esse método do Canvas com uma variação do método baseado em DOM de Bob Monteverde , para que você possa analisar e comparar a precisão dos resultados.

Existem várias vantagens nessa abordagem, incluindo:

NOTA: Ao adicionar o texto ao seu DOM, lembre-se de levar em consideração o preenchimento, a margem e a borda .

NOTA 2: Em alguns navegadores, esse método gera precisão de sub-pixel (resultado é um número de ponto flutuante); em outros, não (resultado é apenas um int). Você pode querer executar Math.floor(ou Math.ceil) o resultado, para evitar inconsistências. Como o método baseado no DOM nunca é preciso com sub-pixels, esse método tem uma precisão ainda maior do que os outros métodos aqui.

De acordo com este jsperf (graças aos colaboradores nos comentários), o método Canvas e o método baseado em DOM são igualmente rápidos, se o cache for adicionado ao método baseado em DOM e você não estiver usando o Firefox. No Firefox, por algum motivo, esse método Canvas é muito mais rápido que o método baseado em DOM (em setembro de 2014).

Domi
fonte
7
Esta é uma opção incrível, eu não sabia disso. Já comparou o desempenho disso ao desempenho da medição no DOM?
SimplGy
2
Eu adicionei o cache ao benchmark jsperf. Agora os dois métodos estão praticamente no mesmo nível: jsperf.com/measure-text-width/4
Brandon Bloom
1
@Martin Huh? O que "muitos elementos HTML" têm a ver com algo aqui? O objeto de tela neste exemplo nem está anexado ao DOM. Além disso, alterar a fonte em um contexto de desenho de tela nem sequer afeta a tela até você strokeText()ou fillText(). Talvez você quisesse comentar uma resposta diferente?
precisa saber é o seguinte
1
Ótima solução. Eu envolvi alguns outros métodos em torno da resposta da Domi para que eu possa - Pegue uma sequência (potencialmente) truncada com reticências (...) no final, se não couber em um determinado espaço (a maior parte da sequência) quanto possível, será usado) - Passe um elemento JQuery que deve conter a sequência (possivelmente truncada) e determine os atributos de fonte dinamicamente para que eles não precisem ser codificados, permitindo que os atributos de fonte CSS sejam alterados sem interromper o layout. JsFiddle aqui: jsfiddle.net/brebey/1q94gLsu/6/embed
BRebey
2
Bom porque o usuário não vê!
Clone45
110

Aqui está um que eu juntei sem exemplo. Parece que estamos todos na mesma 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;
}

Usá-lo é simples: "a string".width()

** Adicionado white-space: nowrappara que strings com largura maior que a largura da janela possam ser calculadas.

Bob Monteverde
fonte
2
Obrigado JordanC. Uma coisa que gostaria de acrescentar é que, se você está chamando isso várias vezes na mesma página, e o desempenho é um problema, você pode persistir no DIV e alterar o conteúdo e verificar a largura. Eu fiz dessa maneira, assim que tudo estivesse dito e feito, o DOM seria o mesmo de quando você começou.
Bob Monteverde
3
Eu não adicionaria esse método, Stringpois diminui a separação de preocupações do seu programa (código principal separado x código da interface do usuário). Imagine que você deseja portar seu código do núcleo de uma plataforma com um quadro UI muito diferente ...
Domi
23
Esse design é ruim , além de associar seu modelo à sua visualização, mas também diretamente ao jQuery. Além disso, isso é um inferno de refluxo, isso definitivamente não seria bem dimensionado.
James
1
Se você deseja que o valor float, você poderia usar o[0].getBoundingClientRect().widthcomo sugerido aqui: stackoverflow.com/a/16072668/936397
Alexander Olsson
1
O @virus disse que mais de 100 pessoas provavelmente também não se importam com o desempenho ... No entanto, isso não torna o que eu disse menos válido ou verdadeiro.
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
fonte
27

Isso funciona para mim ...

// 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
fonte
Oi a sua resposta é realmente útil no entanto usar .cssText vez de .Style para apoiar IE 8 e diminuir ..
Dilip Rajkumar
Essa resposta é ótima, mas quando eu gero um grande pedaço de texto, ele fica impreciso em alguns pixels. É porque a largura não é um número inteiro?
Bobtroopo 22/03
20

A biblioteca javascript ExtJS possui uma excelente classe chamada Ext.util.TextMetrics que "fornece medições precisas de pixel para blocos de texto, para que você possa determinar exatamente quão alto e amplo, em pixels, um determinado bloco de texto será". Você pode usá-lo diretamente ou visualizar sua origem no código para ver como isso é feito.

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

grande lep
fonte
1
ExtJS tem uma licença ímpar. Você paga os mantenedores atuais, a Sencha Company para usá-lo, ou você deve abrir todos os códigos relacionados em seu aplicativo. Esta é uma rolha de exibição para a maioria das empresas. O jQuery, por outro lado, usa a licença MIT altamente permissiva.
Devdanke
1
O javascript não atende automaticamente aos requisitos de código aberto? Você serve a fonte para qualquer pessoa que esteja visualizando a página.
PatrickO
10
Há uma diferença entre poder visualizar o código fonte e o código aberto, definidos pelo licenciamento.
Parker Ault
Graças daqueles de nós ainda usando ExtJS :-)
Monarch Wadia
1
você deveria ter deixado o ExtJS descansar em paz
canbax
19

Eu gosto da sua "única idéia" de apenas fazer um mapa estático de largura de caracteres! Na verdade, funciona bem para os meus propósitos. Às vezes, por razões de desempenho ou porque você não tem acesso fácil a um DOM, você pode apenas querer uma calculadora rápida e autônoma, calibrada para uma única fonte. Então aqui está um calibrado para Helvetica; passe uma string e (opcionalmente) um tamanho de fonte:

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
}

Essa matriz feia gigante tem larguras de caracteres ASCII indexadas pelo código de caracteres. Portanto, isso apenas suporta ASCII (caso contrário, assume uma largura média de caracteres). Felizmente, a largura é dimensionada basicamente linearmente com o tamanho da fonte, portanto funciona muito bem em qualquer tamanho de fonte. Está visivelmente sem qualquer conhecimento de kerning ou ligaduras ou o que seja.

Para "calibrar", renderizei todos os caracteres até o charCode 126 (o poderoso til) em um svg e peguei a caixa delimitadora e salvei-a nessa matriz; mais código, explicação e demonstração aqui .

Toph
fonte
1
essa é uma solução inteligente, ótima :) estou sempre usando a mesma fonte / tamanho, por isso me convém. Eu achei o desempenho das soluções DOM / Canvas um problema real, isso é realmente limpo, felicidades!
mikeapr4
1
remove a necessidade de tela +1
frage 27/01
Você pode se livrar do * fontSizee apenas usá-los
Matt Fletcher
Que resposta incrível!
almosnow
11

Eu escrevi uma pequena ferramenta para isso. Talvez seja útil para alguém. Funciona sem jQuery .

https://github.com/schickling/calculate-size

Uso:

var size = calculateSize("Hello world!", {
   font: 'Arial',
   fontSize: '12px'
});

console.log(size.width); // 65
console.log(size.height); // 14

Fiddle: http://jsfiddle.net/PEvL8/

debochado
fonte
7

Você pode usar a tela para não precisar lidar muito com as propriedades do 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
fonte
Isso não é muito mais pesado (com a obtenção do contexto 2D etc.) do que criar um elemento DOM e especificar propriedades css para ele?
precisa saber é o seguinte
1
Essa é uma abordagem limpa se você já estiver usando a tela para alguma coisa. Mas muito lento. Somente a chamada measureText leva cerca de 8 a 10 ms (usando o Chrome).
Rui Marques
6
<span id="text">Text</span>

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

Isso deve funcionar desde que a tag <span> não tenha outros estilos aplicados a ela. offsetWidth incluirá a largura de todas as bordas, preenchimento horizontal, largura da barra de rolagem vertical etc.

Bryan Friedman
fonte
Isso é mais ou menos o que cria soluções superiores, mas como seu texto pode ser dividido em várias linhas, eles adicionam alguns estilos CSS ao texto para obter a largura real do texto.
Adrian Maire
2

O trecho de código abaixo, "calcula" a largura da tag de extensão, anexa "..." a ela se for muito longo e reduz o comprimento do texto, até que caiba no pai (ou até que tente mais do que isso) mil vezes)

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 (com 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
fonte
2
Tente uma pesquisa binária em vez de fazer um loop de um caractere de cada vez: veja meu comentário na resposta de Alex para stackoverflow.com/questions/536814/…
StanleyH
@ StanleyH: Boa ideia - implementarei sua sugestão o mais rápido possível.
Techek
2

O melhor é detectar se o texto se ajusta logo antes da exibição do elemento. Então você pode usar esta função que não requer que o elemento esteja na tela.

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
fonte
2

Caso alguém mais chegue aqui procurando uma maneira de medir a largura de uma string e uma maneira de saber qual é o maior tamanho de fonte que caberá em uma largura específica, aqui está uma função que se baseia na solução @ Domi com uma pesquisa binária :

/**
 * 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
fonte
Isso funciona surpreendentemente (juntamente com o código da resposta da Domi)
r3wt
1

Tente 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
fonte
1

A largura e a altura de um texto podem ser obtidas com clientWidtheclientHeight

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

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

verifique se a propriedade de posição do estilo está definida como absoluta

element.style.position = "absolute";

não é necessário estar dentro de um div, pode estar dentro de um pou umspan

Gjaa
fonte
1

Partindo da resposta de Deepak Nadar , alterei os parâmetros de funções para aceitar estilos de texto e fonte. Você não precisa fazer referência a um elemento. Além disso, eles fontOptionstêm padrões, para que você não precise fornecer todos eles.

(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
fonte
0

Eu acho que isso é muito parecido com a entrada de Depak, mas é baseado no trabalho de Louis Lazaris publicado em um artigo na página impressionante das redes

(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);

O evento de ajuste é usado para executar a chamada de função imediatamente após a função ser associada ao controle.

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

Mauricio
fonte
0

Sem 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
fonte
quando você define um número não funciona, porque não há um espaço necessário; se você o remover, ele funcionará bem: fontSize + "px arial" -> fontSize + "px arial", apenas isso.
Alberto Acuña
0

Violino do exemplo de trabalho: 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
fonte
0

O Element.getClientRects()método retorna uma coleção de DOMRectobjetos que indicam os retângulos delimitadores para cada caixa de borda CSS em um cliente. O valor retornado é uma coleção de DOMRectobjetos, um para cada caixa de borda CSS associada ao elemento. Cada DOMRectobjecto contém só de leitura left, top, righte bottompropriedades que descrevem a caixa de fronteira, em pixels, com a parte superior esquerda em relao ao canto superior esquerdo da janela de visualização.

Element.getClientRects () da Mozilla Contribuintes está licenciado sob CC-BY-SA 2.5 .

A soma de todas as larguras de retângulo retornadas gera a largura total do texto em pixels.

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
fonte
0

Eu fiz um pequeno 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});

O legal é que você pode notar - ele permite levar em consideração quaisquer atributos CSS, mesmo os preenchimentos!

Roman86
fonte
0

Você também pode fazer isso com createRange, que é mais preciso, do que a técnica de clonagem 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
fonte
-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
fonte