ccleve
ccleve

Reputation: 15799

Measure bounding box of text node in Javascript

I'm having trouble getting the size, in pixels, of a text node using Javascript. Example:

<p>
  first text block
  <b>second text block</b>
</p>

I need to get the bounding box of the two text blocks independently. I could get the size of the second block just by measuring the <b> element, but the first one eludes me. It doesn't appear that textnodes in Javascript have a height or width, so far as I can tell.

Wrapping the first text block in a <span> and measuring that is not an option, because I've discovered that a span does not necessarily inherit all of the styles above it, and when I wrap the text it suddenly changes size. It's like the Heisenberg Uncertainty Principle of Javascript; my attempt to measure something changes it.

I'm building an app that breaks HTML into pages (EPUB HTML, actually), and I need to know the position, height, and width of each block of text on the page so I can know whether to put it on this page or the next page.

Any suggestions?

Upvotes: 22

Views: 9758

Answers (3)

ינון רחמים
ינון רחמים

Reputation: 706

I used a simple solution - if you have permission to edit the html - wrap the text in span, then simply measure span.offsetHeight.

so in your case -

<p>
  <span> <!-- ADD SPAN -->
    first text block
    <b>second text block</b>
  </span>
</p> 
<!-- span.offsetHeight its what you need :) -->

Upvotes: 0

Tim Down
Tim Down

Reputation: 324567

You can do this with a Range that supports CSSOM View extensions, which is most recent browsers (Firefox 4+, WebKit since early 2009, Opera 11, maybe earlier) and a TextRange in IE. The TextRange code is tedious, so I've omitted it here.

jsFiddle: http://jsfiddle.net/gdn6C/1/

Code:

function getTextNodeHeight(textNode) {
    var height = 0;
    if (document.createRange) {
        var range = document.createRange();
        range.selectNodeContents(textNode);
        if (range.getBoundingClientRect) {
            var rect = range.getBoundingClientRect();
            if (rect) {
                height = rect.bottom - rect.top;
            }
        }
    }
    return height;
}

Upvotes: 32

Aadit M Shah
Aadit M Shah

Reputation: 74204

Try making the elements you wish to measure inline. Inline elements only take up as much space as required. Thus, it has an absolute width and height that can be retrieved by javascript. Block elements fill up the entire width of the containing element. Thus javascript cannot access its width.

Upvotes: 0

Related Questions