'DOM Element Width before Appended to DOM

I'm sure the answer is no, but is it possible to determine the width of an element before it is appended to the DOM?

Once it's appended, I know I can use offsetWidth and offsetHeight.

Thanks



Solution 1:[1]

The trick is to show the element (display:block) but also hide it (visibility:hidden) and to set it’s position to absolute so that it doesn’t affect the page flow.

The MooTools Element.Measure class does this, as Oscar mentioned.

Solution 2:[2]

The Mootools Element.Measure functionality that Oscar mentioned is awesome. For those that use jQuery, here's a quick plugin that accomplishes the same thing:

$.fn.measure = (fn)->
  el = $(this).clone(false)
  el.css
    visibility: 'hidden'
    position:   'absolute'
  el.appendTo('body')
  result = fn.apply(el)
  el.remove()
  return result

You can call it like this, making sure to return the value (thanks Sam Fen for pointing that out!):

width = $('.my-class-name').measure( function(){ return this.width() } )

Solution 3:[3]

Modified the code a bit. Here is a pure JS solution:

function measure(el, fn) {
    var pV = el.style.visibility, 
        pP = el.style.position;
        
    el.style.visibility = 'hidden';
    el.style.position = 'absolute';
    
    document.body.appendChild(el);
    var result = fn(el);
    el.parentNode.removeChild(el);
    
    el.style.visibility = pV;
    el.style.position = pP;
    return result;
}

var div = document.createElement('div');
div.innerHTML = "<p>Hello</p><br/>";

alert(div.offsetHeight); // 0

alert(measure(div, function(el){return el.offsetHeight})); // 68

Solution 4:[4]

What you can do with MooTools is use the Element.Measure class - meaning, you inject the element to the DOM, but keep it hidden. Now, you can measure the element without actually showing it.

http://mootools.net/docs/more/Element/Element.Measure

Solution 5:[5]

It is not possible, at least not accurately, because styling affects these properties, and where it's put determines how it is styled and what rules affect it.

For example placing a <p></p> in the page would by default be the width of the body if appended as a child to it, but if you appeneded it inside for example a <div style="width: 100px;"></div>, then you see how that quickly changes things.

Solution 6:[6]

/**
 * Get bounding client rect for an element (not exists at current DOM tree)
 * @param {!HTMLElement} el
 * @return {!Promise<!ClientRect>}
 */
function getElementRect(el) {
  return new Promise(resolve => {
    const element = el.cloneNode(true);
    element.style.visibility = "hidden";
    element.style.position = "absolute";
    document.body.appendChild(element);

    resolve(element.getBoundingClientRect());
    element.remove();
  });
}

const div = /** @type {!HTMLElement} */ (document.createElement("div"));
div.innerHTML = "<p>Hello</p><br/>";

// Execute
(async () => {
  const rect = await getElementRect(div);
  console.log(rect.width);
})();

DEMO

Solution 7:[7]

A slightly different version of @kashesanders: Add the element to a div and put that div inside the DOM.

function getSizeOfNonDomElement(domElement)
{
  // setup
  let div = document.createElement("div");
  div.style.position = "absolute";
  div.style.visibility = "hidden";
  div.style.display = "block";

  div.appendChild (domElement);
  document.body.appendChild (div);

  // run
  let rect = domElement.getBoundingClientRect ();

  // cleanup
  document.body.removeChild (div);
  div.removeChild (domElement);

  return rect;
}

If you want to make it more secure, add a construct to check whether it already has a parent and/or is inside the DOM.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Steve
Solution 2
Solution 3 kashesandr
Solution 4 Oskar Krawczyk
Solution 5 Nick Craver
Solution 6 Zuhair Taha
Solution 7 DarkTrick