在 Javascript 中将 em 转换为 px(并获取默认字体大小)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10463518/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Converting em to px in Javascript (and getting default font size)
提问by Channel72
There are situations where it can be useful to get the exact pixel width of an em
measurement. For example, suppose you have an element with a CSS property (like border or padding) which is measured in ems, and you need to get the exact pixel width of the border or padding. There's an existing question which touches on this topic:
在某些情况下,获取em
测量的精确像素宽度会很有用。例如,假设您有一个具有以 em 为单位的 CSS 属性(如边框或内边距)的元素,您需要获取边框或内边距的准确像素宽度。有一个现有问题涉及此主题:
How can i get default font size in pixels by using JavaScript or JQuery?
如何使用 JavaScript 或 JQuery 以像素为单位获取默认字体大小?
This question is asking about getting the default font size- which is necessary in order to convert a relative em
value to an exact px
value.
这个问题是关于获取默认字体大小- 这是将相对em
值转换为精确px
值所必需的。
This answerhas a pretty good explanation of how to go about getting the default font size of an element:
这个答案很好地解释了如何获取元素的默认字体大小:
Since ems measure width you can always compute the exact pixel font size by creating a div that is 1000 ems long and dividing its client-Width property by 1000. I seem to recall ems are truncated to the nearest thousandth, so you need 1000 ems to avoid an erroneous truncation of the pixel result.
由于 ems 测量宽度,您总是可以通过创建一个 1000 ems 长的 div 并将其 client-Width 属性除以 1000 来计算确切的像素字体大小。我似乎记得 ems 被截断到最近的千分之一,所以你需要 1000 ems避免错误地截断像素结果。
So, using this answer as a guide, I wrote the following function to get the default font size:
因此,使用此答案作为指导,我编写了以下函数来获取默认字体大小:
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;
}
Once you have the default font size, you can convert any em
width to px
width by just multiplying the ems by the element's default font size and rounding the result:
获得默认字体大小后,您可以通过将 em 乘以元素的默认字体大小并将结果四舍五入来将任何em
宽度转换为px
宽度:
Math.round(ems * getDefaultFontSize(element.parentNode))
Math.round(ems * getDefaultFontSize(element.parentNode))
Problem:The getDefaultFontSize
is ideally supposed to be a simple, side-effect free function that returns the default font size. But it DOEShave an unfortunate side effect: it modifies the DOM! It appends a child and then removes the child. Appending the child is necessary in order to get a valid offsetWidth
property. If you don't append the child div
to the DOM, the offsetWidth
property remains at 0 because the element is never rendered. Even though we immediately remove the child element, this function can still create unintended side effects, such as firing an event (like Internet Explorer's onpropertychange
or W3C's DOMSubtreeModified
event) that was listening on the parent element.
问题:该getDefaultFontSize
理想地应该是一个简单的,无副作用的函数,返回的默认字体大小。但它确实有一个不幸的副作用:它修改了 DOM!它附加一个孩子,然后删除孩子。为了获得有效的offsetWidth
属性,必须附加孩子。如果您不将子元素附加div
到 DOM,则该offsetWidth
属性将保持为 0,因为该元素永远不会被呈现。即使我们立即删除了子元素,该函数仍然会产生意想不到的副作用,例如触发正在侦听父元素的事件(如 Internet Exploreronpropertychange
或 W3C 的DOMSubtreeModified
事件)。
Question:Is there any way to write a truly side-effect free getDefaultFontSize()
function that won't accidentally fire event handlers or cause other unintended side effects?
问题:有没有办法编写一个真正无副作用的getDefaultFontSize()
函数,它不会意外触发事件处理程序或导致其他意外的副作用?
采纳答案by mgiuffrida
Edit: No, there isn't.
编辑:不,没有。
To get the rendered font size of a given element, without affecting the DOM:
在不影响 DOM 的情况下获取给定元素的渲染字体大小:
parseFloat(getComputedStyle(parentElement).fontSize);
This is based off the answer to this question.
这是基于对这个问题的回答。
Edit:
编辑:
In IE, you would have to use parentElement.currentStyle["fontSize"]
, but this is not guaranteed to convert the size to px
. So that's out.
在 IE 中,您必须使用parentElement.currentStyle["fontSize"]
,但这不能保证将大小转换为px
. 所以就这样了。
Furthermore, this snippet won't get you the default font size of the element, but rather its actualfont size, which is important if it has actually got a class and a style associated with it. In other words, if the element's font size is 2em
, you'll get the number of pixels in 2 ems. Unless the font size is specified inline, you won't be able to get the conversion ratio right.
此外,这个片段不会让你获得元素的默认字体大小,而是它的实际字体大小,如果它实际上有一个与之关联的类和样式,这很重要。换句话说,如果元素的字体大小是2em
,您将获得 2 em 的像素数。除非内联指定字体大小,否则您将无法获得正确的转换率。
回答by 10011101111
I have a better answer. My code will store the length of 1em
(in CSS pixel px
units in the JavaScript variable em
:
我有一个更好的答案。我的代码将在 JavaScript 变量中存储1em
(以 CSS 像素为px
单位)的长度em
:
Place this
div
anywhere in your HTML code<div id="div" style="height:0;width:0;outline:none;border:none;padding:none;margin:none;box-sizing:content-box;"></div>
Place this function in your JavaScript file
var em; function getValue(id){ var div = document.getElementById(id); div.style.height = '1em'; return ( em = div.offsetHeight ); }
将其
div
放在 HTML 代码中的任何位置<div id="div" style="height:0;width:0;outline:none;border:none;padding:none;margin:none;box-sizing:content-box;"></div>
将此函数放在您的 JavaScript 文件中
var em; function getValue(id){ var div = document.getElementById(id); div.style.height = '1em'; return ( em = div.offsetHeight ); }
Now, whenever you will call this function 'getValue'
with id of that test div in parameter, you will have a variable name em
which will contain value of 1 em in px.
现在,每当您'getValue'
在参数中使用该测试 div 的 id调用此函数时,您将拥有一个变量名称em
,该名称将包含 1 em(以 px 为单位)的值。
回答by Anthony
If you need something quick and dirty (and based on base font-size of body, not an element), I'd go with:
如果您需要快速而肮脏的东西(并且基于正文的基本字体大小,而不是元素),我会选择:
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
回答by Nadav Parag
The following solution uses binary search and window.matchMedia to find out the em width of a window. We then divide the window em width with the window pixel width to get the final result. No DOM involved, side-effects free! In terms of performance it takes around 8 iterations at around 0.2ms on my comp.
以下解决方案使用二分搜索和 window.matchMedia 来找出窗口的 em 宽度。然后我们将窗口 em 宽度除以窗口像素宽度以获得最终结果。不涉及 DOM,无副作用!在性能方面,我的comp上大约需要 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;
}