44

Let's say I have a DIV: <div></div> and I want to find out with JS what its line-height is. I know one can check the style attribute style.lineHeight, but I want to check the actual line-height, without it depending on the existence of a CSS rule.

Assuming the font family and font size are the same, both should output the same line-height:

<div>One line of text</div>
<div>Two <br /> Lines of text</div>

How can I get the line-height of an element with JavaScript?

JCOC611
  • 19,111
  • 14
  • 69
  • 90

9 Answers9

32

The answer is actually using .clientHeight. As Gaby said, this is not really reliable/trustworthy. However, it is! Here:

function getLineHeight(el) {
    var temp = document.createElement(el.nodeName), ret;
    temp.setAttribute("style", "margin:0; padding:0; "
        + "font-family:" + (el.style.fontFamily || "inherit") + "; "
        + "font-size:" + (el.style.fontSize || "inherit"));
    temp.innerHTML = "A";

    el.parentNode.appendChild(temp);
    ret = temp.clientHeight;
    temp.parentNode.removeChild(temp);

    return ret;
}

"Clone" the properties of your element into a new one, get the new's clientHeight, delete the temporary element, and return it's height;

Kerem
  • 11,377
  • 5
  • 59
  • 58
JCOC611
  • 19,111
  • 14
  • 69
  • 90
  • 2
    Be wary though, that since you are appending it to the document, it will inherit the styling of that part. It does not mean that the element you test for, has the same `line-height`, as some inner rule might be overriding it.. The `line-height` is not constant across the document.. – Gabriele Petrioli Dec 23 '10 at 09:26
  • I think I just fixed it, I did think of this from the start but I kinda was too lazy to put it there lol. I replaced `document` with `element.parentNode` :D – JCOC611 Dec 23 '10 at 19:08
  • 1
    @Davy8: I'm glad this is still helpful after so long! – JCOC611 Oct 04 '12 at 21:18
  • @MuhammadUmer: check out the other two answers and you'll see why it's not really an option. – JCOC611 Jul 10 '13 at 02:33
  • if it's normal that means it's about 1.2x the font height! – Muhammad Umer Jul 10 '13 at 18:45
  • 2
    @MuhammadUmer: yeah although it would probably depend on many things...so it's better to know an exact value than an ambiguous *normal*. – JCOC611 Jul 10 '13 at 22:07
  • Thanks for that sample. I suggest adding `position:absolute;` to the list of styles to avoid autosizing when the parent is e.g. a flex container. – Łukasz Nojek Jul 30 '19 at 10:17
  • This doesn't account for situations where `element` and `temp` receive different styles because of class name, or document position (`:first-child`, `:last-child'). It may be better to test using `element` itself, to ensure you're getting the same styles. – tvanc Oct 12 '19 at 00:09
  • @JCOC611 Your solution still is not adequate. The problem others have pointed out is that you can have `
    A
    `, and your solution is not going to give the correct answer. It will only give the correct answer if a) line-height happens to be "normal" b) there are no extra CSS rules that affect the clientHeight measurement, e.g. `*{padding:500px !important}` c) el's font size/family are set inline and not through CSS rules
    – Azmisov Jan 17 '23 at 20:30
  • You could change the question title/description to be: "Find the default line-height for a given font family and size", as that is more in line with what you are doing here. An *element* itself has no intrinsic line-height, it is a property of the font. Still, the current code would not be 100% accurate there either; anytime you add something to the DOM, CSS rules will affect it, either user defined, or browser defaults. You'd need to set inline !important styles on everything that can possibly affect clientHeight to ensure an accurate measurement. – Azmisov Jan 17 '23 at 20:46
17

Explained at quirksmode : http://www.quirksmode.org/dom/getstyles.html

example: http://www.jsfiddle.net/gaby/UXNs2/

function getStyle(el,styleProp)
{
    var x = document.getElementById(el);
    if (x.currentStyle)
        var y = x.currentStyle[styleProp];
    else if (window.getComputedStyle)
        var y = document.defaultView.getComputedStyle(x,null).getPropertyValue(styleProp);
    return y;
}

and use it like

getStyle('test', 'line-height' )
Gabriele Petrioli
  • 191,379
  • 34
  • 261
  • 317
  • 6
    Pretty interesting, although it returns "normal" rather than a number, at least in Chrome. – JCOC611 Dec 08 '10 at 22:31
  • I am not sure if you can get more info out of that case, since `normal` is a valid value for `line-height`. See http://stackoverflow.com/questions/3614323/jquery-css-line-height-of-normal-px – Gabriele Petrioli Dec 08 '10 at 22:42
  • Indeed, but when I wrote the question I was looking for something like `.clientWidth()`, which is used to retrieve the "real" width of an element. – JCOC611 Dec 08 '10 at 22:46
  • 1
    you could use the `clientHeight` of the element, but it will need to only have a single line to work (*and no padding etc.. not very trustworthy*). Also note that IE will also return `normal` and it need to be called with `lineHeight` and not `line-height`. – Gabriele Petrioli Dec 08 '10 at 23:01
  • yes, I wonder if there is any way to get the *line height* the way `.clientHeight()` gets the *element height* – JCOC611 Dec 09 '10 at 01:33
  • is it possible to get a line height of certain line in a paragraph. Let's say you have a inlineblock element in line 5 with height of 50px; – Muhammad Umer Jul 11 '13 at 17:13
10

This solution works for me. It uses the value of the line-height property when it has been set explicitly or, when the value has not been set, it calculates the value by finding the difference in the height of the object when its contents are augmented by one line.

function calculateLineHeight (element) {

  var lineHeight = parseInt(getStyle(element, 'line-height'), 10);
  var clone;
  var singleLineHeight;
  var doubleLineHeight;

  if (isNaN(lineHeight)) {
    clone = element.cloneNode();
    clone.innerHTML = '<br>';
    element.appendChild(clone);
    singleLineHeight = clone.offsetHeight;
    clone.innerHTML = '<br><br>';
    doubleLineHeight = clone.offsetHeight;
    element.removeChild(clone);
    lineHeight = doubleLineHeight - singleLineHeight;
  }

  return lineHeight;
}
furf
  • 2,689
  • 1
  • 18
  • 13
5

See currentStyle for IE and getComputedStyle() for other browsers (also supported by IE9).

Phrogz
  • 296,393
  • 112
  • 651
  • 745
  • 1
    Assuming *element* references a HTML DIV Element, `element.currentStyle` returns undefined and `element.getComputedStyle()` throws error (undefined too), in Chrome. – JCOC611 Dec 08 '10 at 22:26
  • although this method is explained in the second answer – JCOC611 Dec 08 '10 at 22:28
5

This is easy now with window.getComputedStyle.

function getLineHeight(el: HTMLSpanElement) {
  return window.getComputedStyle(el).lineHeight;
}
Chris Esplin
  • 842
  • 9
  • 16
3

It’s fairly complicated. I made an npm package for clamping text to a certain number of lines or a pixel height.

You can’t just check line-height. Sometimes that’s normal which is no help at all.

You can’t put the text in another element because it may receive different styles.

The most solid method I found was to remove all text from the element and measure its height. Then add a line and measure the height. the height the first line adds isn’t always the same as subsequent lines. Then add another line. The second and all subsequent lines all add the same amount.

My tool exposes a method called calculateTextMetrics() that which uses the above strategy and returns the resulting measurements.

https://github.com/tvanc/lineclamp#getting-text-metrics

tvanc
  • 3,807
  • 3
  • 25
  • 40
1

One intuitive way (that doesn't require element reference) is to use selection and range APIs to get cursor height.

const range = window.getSelection().getRangeAt(0);
const height = (range.getClientRects()[0]).height;

ref: https://developer.mozilla.org/en-US/docs/Web/API/Element/getClientRects

GorvGoyl
  • 42,508
  • 29
  • 229
  • 225
  • Unfortunately `range.getClientRects` gives the border box of the element... equivalent to `element.getClientRects`. So for elements that are not inline (block, inline-block, etc), it will not be accurate. – Azmisov Jan 17 '23 at 23:19
0

The line-height: normal is actually 110% to 120% of the font-size. So, based on this fact, I use this code everywhere I need to get the line height of any element.

JavaScript:

function getLineHeight(elem) {
    let computedStyle = window.getComputedStyle(elem);
    let lineHeight = computedStyle.getPropertyValue('line-height');
    let lineheight;
    
    if (lineHeight === 'normal') {
        let fontSize = computedStyle.getPropertyValue('font-size'); // Get Font Size
        lineheight = parseFloat(fontSize) * 1.2; // 'normal' Line Height Equals To 120% Of Font Size In Most Browsers
    } else {
        lineheight = parseFloat(lineHeight); // The Line Height That Is Not 'normal'
    }
    
    return lineheight;
}
-1

This is the best way to me. No error for me so far

function getLineHeight(element) {

oldHtml = element.innerHTML

element.innerHTML = "A"
lineHeight = element.offsetHeight

element.innerHTML = oldHtml

return lineHeight }
T H
  • 423
  • 4
  • 7