Преобразование em в px в Javascript (и получение размера шрифта по умолчанию)

Существуют ситуации, когда бывает полезно получить точную ширину пикселяem измерение. Например, предположим, что у вас есть элемент со свойством CSS (например, border или padding), который измеряется в ems, и вам нужно получить точную ширину пикселя границы или отступа. Существует существующий вопрос, который затрагивает эту тему:

Как я могу получить размер шрифта по умолчанию в пикселях, используя JavaScript или JQuery?

Этот вопрос задает вопрос о получении размер шрифта по умолчанию - что необходимо для преобразования относительногоem значение до точногоpx ценность

Этот ответ @ есть довольно хорошее объяснение того, как получить размер шрифта элемента по умолчанию:

Так как ems измеряет ширину, вы всегда можете вычислить точный размер шрифта в пикселях, создав div, длина которого составляет 1000 ems, и разделив его свойство client-Width на 1000. Я помню, что ems усекаются до ближайшей тысячной, поэтому вам нужно 1000 ems чтобы избежать ошибочного усечения результата пикселя.

Итак, используя этот ответ в качестве руководства, я написал следующую функцию, чтобы получить размер шрифта по умолчанию:

<code>function getDefaultFontSize(parentElement)
{
    parentElement = parentElement || document.body;
    var div = document.createElement('div');
    div.style.width = "1000em";
    parentElement.appendChild(div);
    var pixels = div.offsetWidth / 1000;
    parentElement.removeChild(div);
    return pixels;
}
</code>

Как только у вас есть размер шрифта по умолчанию, вы можете конвертировать любойem ширина доpx width, просто умножив ems на размер шрифта элемента по умолчанию и округлив результат:

Math.round(ems * getDefaultFontSize(element.parentNode))

Problem: ThegetDefaultFontSize идеале @ должна быть простой функцией без побочных эффектов, которая возвращает размер шрифта по умолчанию. Но это ДЕЛАЕТ имеет неприятный побочный эффект: он изменяет DOM! Он добавляет ребенка, а затем удаляет ребенка. Присоединение ребенка необходимо для того, чтобы получить действительныйoffsetWidth свойство. Если вы не добавите ребенкаdiv для DOM,offsetWidthвойство @ остается в 0, потому что элемент никогда не отображается. Несмотря на то, что мы немедленно удаляем дочерний элемент, эта функция может создавать непреднамеренные побочные эффекты, такие как запуск события (например, Internet Exploreronpropertychange или W3C'sDOMSubtreeModified event), который прослушивал родительский элемент.

Вопрос Есть ли способ написать действительно побочный эффект бесплатноgetDefaultFontSize() функция, которая не будет запускать обработчики событий случайно или вызывать другие непреднамеренные побочные эффекты?

Ответы на вопрос(4)

в переменнойem.

Поместите этоdiv в любом месте вашего HTML-кода

<div id="div" style="height:0;width:0;outline:none;border:none;padding:none;margin:none;"></div>

Поместите эту функцию в свой файл JavaScript

var em;
function getValue(id){
    var div = document.getElementById(id);
    div.style.height = 1em;
    em = div.offsetHeight;
}

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

Ред .: Нет, нет.

Чтобы получить размер отображаемого шрифта для данного элемента, не влияя на DOM:

parseFloat(getComputedStyle(parentElement).fontSize);

Это основано на ответеэтот вопро.

Редактировать

В IE вам придется использоватьparentElement.currentStyle["fontSize"], но это не гарантирует преобразование размера вpx. Так что это вышло.

Кроме того, этот фрагмент не даст вам размер шрифта элемента по умолчанию, а скорее его Фактической размер шрифта, который важен, если у него действительно есть класс и стиль, связанный с ним. Другими словами, если размер шрифта элемента равен2em, вы получите количество пикселей в 2 ems. Если размер шрифта не указан встроенным, вы не сможете получить правильный коэффициент конверсии.

ре шрифта тела, а не элемента), я бы выбрал:

Number(getComputedStyle(document.body,null).fontSize.replace(/[^\d]/g, ''))

 Number(  // Casts numeric strings to number
   getComputedStyle(  // takes element and returns CSSStyleDeclaration object
     document.body,null) // use document.body to get first "styled" element
         .fontSize  // get fontSize property
          .replace(/[^\d]/g, '')  // simple regex that will strip out non-numbers
 ) // returns number

чтобы определить ширину окна. Затем мы делим ширину окна на ширину пикселя окна, чтобы получить окончательный результат. DOM не участвует, без побочных эффектов! С точки зрения производительности это занимает около 8 итераций и около 0,2 мс на моем компе.

const singleEmInPixels = getSingleEmInPixels();
console.log(`1em = ${singleEmInPixels}px`);

/**
 * returns the amount of pixels for a single em
 */
function getSingleEmInPixels() {
    let low = 0;
    let high = 200;
    let emWidth = Math.round((high - low) / 2) + low;
    const time = performance.now();
    let iters = 0;
    const maxIters = 10;
    while (high - low > 1) {
        const match = window.matchMedia(`(min-width: ${emWidth}em)`).matches;
        iters += 1;
        if (match) {
            low = emWidth;
        } else {
            high = emWidth;
        }
        emWidth = Math.round((high - low) / 2) + low;
        if (iters > maxIters) {
            console.warn(`max iterations reached ${iters}`);
            break;
        }
    }
    const singleEmPx = Math.ceil(window.innerWidth / emWidth);
    console.log(`window em width = ${emWidth}, time elapsed =  ${(performance.now() - time)}ms`);
    return singleEmPx;
}

ВАШ ОТВЕТ НА ВОПРОС