4

This function was adapted from the website: http://eriwen.com/javascript/measure-ems-for-layout/

function getEmSize(el) {
    var tempDiv = document.createElement("div");
    tempDiv.style.height = "1em";
    el.appendChild(tempDiv);
    var emSize = tempDiv.offsetHeight;
    el.removeChild(tempDiv);
    return emSize;
}

I am running this function as part of another function on window.resize, and it is causing performance problems on Firefox 3.6 that do not exist on current Safari or Chrome. Firefox's profiler says I'm spending the most time in this function and I'm curious as to why that is.

Is there a way to get the em size in javascript without doing all this work? I would like to recalculate the size on resize incase the user has changed it.

zsalzbank
  • 9,685
  • 1
  • 26
  • 39
macrael
  • 298
  • 5
  • 10
  • can you show us how this function is used in the other function on window.resize? – mauris Dec 31 '10 at 18:57
  • @thephpdeveloper I could, but I think it is superfluous. The function is only called once in that function and the result is cached. – macrael Jan 01 '11 at 19:20
  • Firefox has a profiler? Is it built-in or are you talking about JavaScript Debugger (Venkman)? – Tyler Jan 02 '11 at 16:57
  • 1
    @MatrixFrog Sorry, not built into FF. Firebug has some profiling capabilities. – macrael Jan 03 '11 at 19:01

2 Answers2

14

Seems like the function could just be

function getEmSize(el) {
    return Number(getComputedStyle(el, "").fontSize.match(/(\d+)px/)[1]);
}

In other words, you can just get the computed font size of the element rather than creating a div and sizing it.

David Baron
  • 920
  • 4
  • 5
  • Thank you for your answer, David. I wrote the original function back in 2008 when we still had to support Safari 2 (which does not have *getComputedStyle()*). I suspect that the best answer is actually your answer with the caching idea. I have updated my blog post accordingly. – Eric Wendelin Jan 05 '11 at 05:23
  • I like this. The only strange bug I've hit is on Chrome. Because I'm calling this function on resize Chrome will log some errors to the console that make it seem like it is running two copies of the function concurrently with some data getting left out. – macrael Jan 09 '11 at 22:22
  • 1
    By the way, the resulting pixel value could be a floating point, so the regular expression should look something like `/(\d+(\.\d*)?)px/`. – mgiuffrida May 05 '12 at 21:06
  • 1
    or `parseFloat(getComputedStyle(el, "").fontSize)`; – Cristi Mihai Aug 08 '14 at 07:01
2

Try this (it's the same function with the value stashed so it only runs once):

var getEmSize =  function() {
    var underlyingFunction = function(el) {
      var tempDiv = document.createElement("div");
      tempDiv.style.height = "1em";
      el.appendChild(tempDiv);
      var emSize = tempDiv.offsetHeight;
      el.removeChild(tempDiv);
      underlyingFunction = function() {
        return emSize;
      };
      return emSize;
    };
    return function(el) {
       return underlyingFunction(el);
    };
};
Michael Lorton
  • 43,060
  • 26
  • 103
  • 144