Как определить ширину текстовой строки в JS
Измерение ширины текста с помощью Canvas API
Как измерить ширину текста без добавления элементов в DOM?
Canvas предоставляет метод measureText, который возвращает объект с шириной в пикселях. Это быстрый и точный способ, не требующий изменении вёрстки.
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.font = '16px Arial';
const width = ctx.measureText('Пример текста').width;
console.log(width);
Js text width (измерение ширины текста в javascript)
Перед измерением необходимо установить шрифт и его размер, иначе результат будет для шрифта по умолчанию. Также следует учитывать загрузку веб-шрифтов.
Проблема: при использовании веб-шрифтов, если шрифт ещё не загружен, измерение будет неверным. Решение: дождаться события document.fonts.ready или использовать шрифты, уже загруженные на странице.
Как измерить ширину текста с учётом стилей элемента?
Если текст должен отображаться с определёнными стилями (жирность, межбуквенное расстояние и т.д.), можно создать временный элемент, применить стили и измерить его ширину после добавления в DOM.
const span = document.createElement('span');
span.textContent = 'Текст с нестандартными стилями';
span.style.font = 'bold 18px Times New Roman';
span.style.letterSpacing = '2px';
span.style.position = 'absolute';
span.style.visibility = 'hidden';
document.body.appendChild(span);
const width = span.getBoundingClientRect().width;
document.body.removeChild(span);
console.log(width);
Border width js (стиль border-width в javascript)
Проблема: offsetWidth включает padding, border, scrollbar, если они есть. Лучше использовать getBoundingClientRect().width, который возвращает ширину содержимого с учётом паддингов, но без margin. Также добавление элемента влияет на layout; использование position:absolute и visibility:hidden минимизирует это влияние.
Как измерить ширину текста в уже существующем элементе?
Если элемент уже есть на странице и содержит текст, можно напрямую получить его ширину через offsetWidth или getBoundingClientRect.
const element = document.getElementById('myText');
const width = element.offsetWidth;
console.log(width);
Js style width (стиль width в javascript)
Этот способ не подходит, если текст ещё не отрендерен.
Как измерить ширину текста с помощью Range?
Объект Range позволяет измерять ширину выделенного фрагмента текста. Это может быть полезно для динамических текстов.
const range = document.createRange();
const textNode = document.createTextNode('Измеряемый текст');
range.selectNodeContents(textNode); // нужно сначала добавить textNode в DOM
// для измерения без DOM можно создать временный элемент как выше
Js width height (ширина и высота в javascript)
Range измеряет ширину в координатах документа, но требует, чтобы текст был в DOM.
Как измерить ширину текста в SVG?
Элемент SVG text имеет метод getComputedTextLength, возвращающий длину текста в пользовательских единицах.
const svgNS = 'http://www.w3.org/2000/svg';
const text = document.createElementNS(svgNS, 'text');
text.textContent = 'SVG текст';
text.setAttribute('font-size', '20');
document.getElementById('svgContainer').appendChild(text);
const length = text.getComputedTextLength();
console.log(length);
Js device width (ширина экрана устройства в javascript)
Как выполнить приблизительное измерение без точного шрифта?
Если точность не критична, можно использовать среднюю ширину символа (например, 0.6 от font-size) и умножить на длину строки.
const fontsize = 16;
const approximateWidth = text.length * fontsize * 0.6;
Этот метод даёт лишь грубую оценку и не учитывает кернинг, разные шрифты и специфические символы.
Расширенные примеры измерения ширины текста
Измерение многострочного текста
Для текста, занимающего несколько строк, ширина обычно определяется самой длинной строкой. Можно разбить текст на строки и измерить каждую.
const multiline = 'Первая строка\nВторая, более длинная строка\nТретья';
const lines = multiline.split('\n');
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.font = '14px Arial';
const widths = lines.map(line => ctx.measureText(line).width);
const maxWidth = Math.max(...widths);
console.log('Максимальная ширина:', maxWidth);
Максимальная ширина: 156.5
Измерение текста с разными шрифтами
Необходимо учитывать, что шрифт может быть разным для разных частей текста. В таком случае измерение проводится для каждого фрагмента отдельно.
const parts = [
{ text: 'Жирный', font: 'bold 16px Arial' },
{ text: ' Курсив', font: 'italic 16px Times' }
];
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
let totalWidth = 0;
parts.forEach(part => {
ctx.font = part.font;
totalWidth += ctx.measureText(part.text).width;
});
console.log('Общая ширина:', totalWidth);
Общая ширина: 87.2
Кэширование измерений для повышения производительности
Если требуется многократно измерять один и тот же текст, результат можно сохранять в переменной или Map.
const cache = new Map();
function getTextWidth(text, font) {
const key = text + '|' + font;
if (cache.has(key)) return cache.get(key);
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.font = font;
const width = ctx.measureText(text).width;
cache.set(key, width);
return width;
}
console.log(getTextWidth('Привет', '14px Arial'));
console.log(getTextWidth('Привет', '14px Arial')); // из кэша
35.2 (дважды выведется одно и то же)
Измерение с учётом letter-spacing и word-spacing
Canvas API не учитывает CSS-свойства letter-spacing и word-spacing, поэтому при необходимости их нужно добавлять вручную.
function measureTextWithSpacing(text, font, letterSpacing = 0, wordSpacing = 0) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.font = font;
let width = 0;
for (let i = 0; i < text.length; i++) {
width += ctx.measureText(text[i]).width;
if (text[i] === ' ') width += wordSpacing;
if (i < text.length - 1) width += letterSpacing;
}
return width;
}
console.log(measureTextWithSpacing('Hello World', '16px Arial', 1, 4));
95.2
Сравнение точности canvas и DOM-элемента
Оба метода дают близкие результаты, но canvas может отличаться из-за округления. Проверка:
const text = 'Тест';
const font = '20px Arial';
// Canvas
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.font = font;
const cWidth = ctx.measureText(text).width;
// DOM
const span = document.createElement('span');
span.textContent = text;
span.style.font = font;
span.style.position = 'absolute';
span.style.visibility = 'hidden';
document.body.appendChild(span);
const dWidth = span.getBoundingClientRect().width;
document.body.removeChild(span);
console.log('Canvas:', cWidth, 'DOM:', dWidth);
Canvas: 36.3 DOM: 36.3 (обычно совпадают)
Измерение ширины текста до его рендеринга в браузере
Это полезно для адаптивной верстки, когда нужно определить, поместится ли текст в контейнер.
function canFit(text, maxWidth, font) {
const width = getTextWidth(text, font); // функция из предыдущих примеров
return width <= maxWidth;
}
console.log(canFit('Длинный текст, который не поместится', 100, '12px Arial'));
false