Рассчитать ширину текста с помощью JavaScript

467

Я хотел бы использовать JavaScript для расчета ширины строки. Возможно ли это без использования моноширинного шрифта?

Если он не встроенный, моя единственная идея - создать таблицу ширины для каждого символа, но это довольно неразумно, особенно с поддержкой Unicode и разных размеров шрифта (и всех браузеров в этом отношении).

Иаков
источник
10
Помните, что если вы используете внешние шрифты, вам придется использовать методы, приведенные ниже, после их загрузки. Возможно, вы этого не поймете, если вы их кэшировали или если у вас установлены локальные версии.
Сет В. Кляйн

Ответы:

355

Создайте DIV со следующими стилями. В вашем JavaScript установите размер шрифта и атрибуты, которые вы пытаетесь измерить, поместите вашу строку в DIV, затем прочитайте текущую ширину и высоту DIV. Он растянется, чтобы соответствовать содержимому, и размер будет в пределах нескольких пикселей от размера отображаемой строки.

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
источник
8
Единственное, что я хотел бы добавить, это то, что это может дать неправильные размеры в зависимости от того, какие стили используются. Помните, что у вас могут быть такие стили, как p {letter-spacing: 0.1em; } что элемент DIV не будет отражать. Вы должны убедиться, что стили на месте соответствуют тому, где вы будете использовать текст.
Джим
5
Ditto Jim's comment - перепроверьте, чтобы убедиться, что к контейнеру, div в этом случае, не применяются какие-либо другие стили, применяемые к нему через правила выбора css, о которых вы, возможно, не знали в то время. Удалите все соответствующие стили из контейнера, прежде чем применять те, которые вам нужны, перед измерением.
Джейсон Бантинг
44
Вы также должны поставить пробел: nowrap, если вы думаете, что текст будет превышать ширину браузера.
Herb Caudill
5
@BBog все эти взломы, поэтому я предлагаю другой, менее хакерский подход внизу. Посмотрите на это здесь .
Доми
11
Просто любопытно, что +1для каждого измерения?
Кип
385

В HTML 5 вы можете просто использовать метод Canvas.measureText (дальнейшее объяснение здесь ).

Попробуйте эту скрипку :

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

Эта скрипка сравнивает этот метод Canvas с вариацией метода , основанного на DOM Боба Монтеверде , так что вы можете анализировать и сравнивать точность результатов.

У этого подхода есть несколько преимуществ, в том числе:

ПРИМЕЧАНИЕ. При добавлении текста в DOM не забывайте также учитывать отступы, поля и границы .

ПРИМЕЧАНИЕ 2: В некоторых браузерах этот метод дает субпиксельную точность (результат - число с плавающей запятой), в других - нет (результат - только целое число). Возможно, вы захотите запустить Math.floor(или Math.ceil) результат, чтобы избежать несоответствий. Поскольку метод на основе DOM никогда не является субпиксельным с точностью, этот метод имеет даже более высокую точность, чем другие методы здесь.

Согласно этому jsperf (спасибо авторам в комментариях), метод Canvas и метод на основе DOM работают примерно одинаково, если к методу на основе DOM добавлено кэширование, а вы не используете Firefox. В Firefox по какой-то причине этот метод Canvas намного быстрее, чем метод на основе DOM (по состоянию на сентябрь 2014 года).

Доми
источник
7
Это отличный вариант, я не знал об этом. Когда-нибудь сравнивать производительность этого с производительностью измерения в DOM?
SimplGy
2
Я добавил кеширование в этот тест jsperf. Теперь эти два метода в значительной степени совпадают
Брэндон Блум,
1
@ Мартин А? При чем здесь «много элементов HTML»? Объект canvas в этом примере даже не прикреплен к DOM. И даже помимо этого, изменение шрифта в контексте рисования холста даже не влияет на холст, пока вы strokeText()или fillText(). Возможно, вы хотели прокомментировать другой ответ?
Ajedi32
1
Хорошее решение. Я обернул несколько других методов вокруг ответа Domi, чтобы я мог: - Получить (потенциально) усеченную строку с многоточием (...) в конце, если она не помещается в заданное пространство (столько же в строке будет использоваться, насколько это возможно) - передать элемент JQuery, который должен содержать (возможно, усеченную) строку, и динамически определять атрибуты Font, чтобы их не нужно было жестко кодировать, позволяя атрибутам шрифта CSS изменяться без прерывания расположение. JSFiddle Здесь: jsfiddle.net/brebey/1q94gLsu/6/embed
BRebey
2
Хорошо, потому что пользователь этого не видит!
clabe45
110

Вот тот, который я взбил без примера. Похоже, мы все на одной странице.

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;
}

Используя это просто: "a string".width()

** Добавлено, white-space: nowrapчтобы можно было рассчитать строки с шириной, превышающей ширину окна.

Боб Монтеверде
источник
2
Спасибо Джордан. Я бы добавил, что если вы вызываете это много раз на одной и той же странице, и производительность является проблемой, вы можете сохранить DIV и просто изменить содержимое и проверить ширину. Я просто сделал это таким образом, чтобы после того, как все было сказано и сделано, DOM был бы таким же, как когда вы начинали
Боб Монтеверде
3
Я бы не стал прибегать к этому методу, Stringпоскольку он уменьшает разделение интересов вашей программы (отдельный код ядра и код пользовательского интерфейса). Представьте, что вы хотите портировать свой основной код на платформу с совершенно другой структурой пользовательского интерфейса ...
Domi
23
Это плохой дизайн , он не только соединяет вашу модель с вашим представлением, но также соединяет ее напрямую с jQuery. Кроме того, это адский рефлоу, это определенно не будет хорошо масштабироваться.
Джеймс
1
Если вы хотите использовать значение с плавающей запятой, вы можете использовать его o[0].getBoundingClientRect().widthв соответствии с предложением здесь: stackoverflow.com/a/16072668/936397
Александр Олссон,
1
@virus хорошо сказал, что 100+ людей, вероятно, тоже не заботятся о производительности ... Тем не менее, не делает то, что я сказал, менее достоверным или правдивым.
Джеймс
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);
Дипак Надар
источник
27

Это работает для меня ...

// 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;
}
Пит
источник
Привет, ваш ответ действительно полезен, однако используйте .cssText вместо .style для поддержки IE 8 и ниже.
Дилип Раджкумар
Этот ответ хорош, но когда я генерирую большой фрагмент текста, он становится неточным на несколько пикселей. Это потому, что ширина не является целым числом?
Bobtroopo
20

В библиотеке ExtJS javascript есть отличный класс Ext.util.TextMetrics, который «обеспечивает точные измерения пикселей для блоков текста, чтобы вы могли точно определить, насколько высокими и широкими в пикселях будет данный блок текста». Вы можете использовать его напрямую или просмотреть его исходный код, чтобы увидеть, как это делается.

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

большой леп
источник
1
ExtJS имеет нечетную лицензию. Либо вы платите текущим сопровождающим, либо компании Sencha за их использование, или вы должны открыть исходный код всего связанного кода в вашем приложении. Это шоу-стоппер для большинства компаний. С другой стороны, jQuery использует лицензию MIT с высокой разрешающей способностью.
Девданке
1
Разве javascript автоматически не отвечает требованиям открытого исходного кода? Вы предоставляете источник любому, кто просматривает страницу.
PatrickO
10
Существует разница между возможностью просмотра исходного кода и открытого исходного кода, что определяется лицензированием.
Паркер Олт
Спасибо от тех, кто все еще использует ExtJS :-)
Monarch Wadia
1
ты должен был позволить ExtJS покоиться с миром
canbax
19

Мне нравится ваша "единственная идея" просто сделать статическую карту ширины символов! Это на самом деле хорошо работает для моих целей. Иногда по соображениям производительности или из-за того, что у вас нет простого доступа к DOM, вам может понадобиться быстрый взломанный автономный калькулятор, откалиброванный для одного шрифта. Итак, вот один, откалиброванный для Helvetica; передать строку и (необязательно) размер шрифта:

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
}

Этот гигантский уродливый массив имеет ширину символов ASCII, проиндексированную кодом символов. Так что это просто поддерживает ASCII (в противном случае предполагается средняя ширина символа). К счастью, ширина в основном линейно масштабируется в зависимости от размера шрифта, поэтому она отлично работает при любом размере шрифта. Ему явно не хватает понимания кернинга, лигатур или чего-то еще.

Чтобы «откалибровать», я просто визуализировал каждый символ до charCode 126 (могущественная тильда) в SVG, получил ограничивающий прямоугольник и сохранил его в этом массиве; больше кода и объяснений и демо здесь .

Тоф
источник
1
это умное решение, хорошо :) Я всегда использую один и тот же шрифт / размер, так что он мне подходит. Я считаю, что производительность решений DOM / Canvas - настоящая проблема, это действительно чисто, ура!
mikeapr4
1
устраняет необходимость в холсте +1
фрейм
Вы можете избавиться от * fontSizeи просто использовать их
Мэтт Флетчер
Какой удивительный ответ!
almosnow
11

Я написал небольшой инструмент для этого. Возможно, это кому-нибудь пригодится. Работает без jQuery .

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

Применение:

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

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

Скрипка: http://jsfiddle.net/PEvL8/

schickling
источник
7

Вы можете использовать холст, чтобы вам не приходилось иметь дело со свойствами 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
источник
Разве это не намного тяжелее (с получением 2d-контекста и т. Д.), Чем создание элемента DOM и указание для него свойств CSS?
Pharao2k
1
Это чистый подход, если вы уже используете canvas для чего-то. Но ОЧЕНЬ МЕДЛЕННО. Один только вызов measureText занимает около 8-10 мс (с использованием Chrome).
Руи Маркес
6
<span id="text">Text</span>

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

Это должно работать, пока к тегу <span> не применяются другие стили. offsetWidth будет включать в себя ширину любых границ, горизонтальное заполнение, ширину вертикальной полосы прокрутки и т. д.

Брайан Фридман
источник
Это более или менее то, что делает верхние решения, но так как ваш текст может быть разбит на несколько строк, они добавляют несколько стилей CSS к тексту, чтобы получить реальную полную ширину текста.
Адриан Мэйр
2

Приведенный ниже фрагмент кода «вычисляет» ширину тега span, добавляет к нему «...», если он слишком длинный, и сокращает длину текста до тех пор, пока он не уместится в родительском элементе (или пока он не попытается выполнить более тысячи раз)

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 (с помощью 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
источник
2
Попробуйте выполнить бинарный поиск вместо зацикливания 1 символа за раз: см. Мой комментарий к ответу Алекса на stackoverflow.com/questions/536814/…
StanleyH
@StanleyH: Хорошая идея - я выполню ваше предложение как можно скорее.
Течек
2

Лучше всего определить, подходит ли текст прямо перед отображением элемента. Таким образом, вы можете использовать эту функцию, которая не требует, чтобы элемент был на экране.

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;
}

Применение:

if ( textWidth("Text", "bold 13px Verdana") > elementWidth) {
    ...
}
artnikpro
источник
2

На тот случай, если кто-то еще ищет здесь способ измерения ширины строки и способ узнать, какой самый большой размер шрифта будет соответствовать конкретной ширине, вот функция, основанная на решении @ Domi с бинарным поиском. :

/**
 * 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;
        }
    }
}
М Кац
источник
Это работает удивительно (в сочетании с кодом из ответа Доми)
r3wt
1

Попробуйте этот код:

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;
}
Джейсон Брейси
источник
1

Ширина и высота текста могут быть получены с помощью clientWidthиclientHeight

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

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

убедитесь, что свойство стиля позиции установлено в абсолют

element.style.position = "absolute";

не обязательно должен быть внутри div, может быть внутри pилиspan

Gjaa
источник
1

Основываясь на ответе Дипака Надара , я изменил параметр функций, чтобы принимать стили текста и шрифта. Вам не нужно ссылаться на элемент. Кроме того, fontOptionsесть значения по умолчанию, поэтому вам не нужно поставлять все из них.

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

Мистер Поливирл
источник
0

Я думаю, что это похоже на запись Депака, но основано на работе Луи Лазариса, опубликованной в статье на странице впечатляющей сети

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

Событие fit используется для немедленного выполнения вызова функции после того, как функция связана с элементом управления.

Например: $ ('input'). autofit (). trigger ("fit");

Маурисио
источник
0

Без 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
источник
когда вы устанавливаете число, это не работает, потому что пробел не нужен, если вы удалите его, он будет работать нормально: fontSize + "px arial" -> fontSize + "px arial", только это.
Альберто Акунья
0

Скрипка рабочего примера: 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>

Код 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");
Джейсон Уильямс
источник
0

Element.getClientRects()Метод возвращает коллекцию DOMRectобъектов , которые указывают ограничивающие прямоугольники для каждого пограничного поле CSS в клиенте. Возвращаемое значение представляет собой коллекцию DOMRectобъектов, по одному для каждого поля границы CSS, связанного с элементом. Каждый DOMRectобъект содержит только для чтения left, top, rightи bottomсвойства , описывающие форму границы, в пикселях, с левого верхнего по отношению к верхней левой части окна просмотра.

Element.getClientRects () от Mozilla Contributors лицензируется в соответствии с CC-BY-SA 2.5 .

Суммирование всех возвращенных значений ширины прямоугольника дает общую ширину текста в пикселях.

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
источник
0

Я сделал крошечный модуль ES6 (использует 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();
}

Легко использовать:

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

Крутая вещь, которую вы можете заметить - она ​​позволяет учитывать любые атрибуты CSS, даже отступы!

Roman86
источник
0

Вы также можете сделать это с помощью createRange, который является более точным, чем метод клонирования текста:

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;
}
работе 33
источник
-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'));
Кавун
источник