JavaScript: Find DIV's line-height, not CSS property but actual line-height
Asked Answered
A

9

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?

Argufy answered 8/12, 2010 at 22:8 Comment(0)
A
34

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;

Argufy answered 23/12, 2010 at 2:43 Comment(10)
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..Timeless
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 :DArgufy
@Davy8: I'm glad this is still helpful after so long!Argufy
@MuhammadUmer: check out the other two answers and you'll see why it's not really an option.Argufy
if it's normal that means it's about 1.2x the font height!Salvation
@MuhammadUmer: yeah although it would probably depend on many things...so it's better to know an exact value than an ambiguous normal.Argufy
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.Travax
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.Shaunda
@Argufy Your solution still is not adequate. The problem others have pointed out is that you can have <div style='line-height: 500px;'>A</div>, 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 rulesSharyl
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.Sharyl
T
18

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' )
Timeless answered 8/12, 2010 at 22:21 Comment(6)
Pretty interesting, although it returns "normal" rather than a number, at least in Chrome.Argufy
I am not sure if you can get more info out of that case, since normal is a valid value for line-height. See #3614823Timeless
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.Argufy
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.Timeless
yes, I wonder if there is any way to get the line height the way .clientHeight() gets the element heightArgufy
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;Salvation
P
11

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;
}
Palingenesis answered 25/8, 2013 at 15:45 Comment(0)
A
7

This is easy now with window.getComputedStyle.

function getLineHeight(el: HTMLSpanElement) {
  return window.getComputedStyle(el).lineHeight;
}
Audette answered 7/10, 2021 at 17:13 Comment(2)
This actually worked for me. ThanksDesiderata
This doesn't work when the source CSS is line-height: normal; as normal is a valid computed value.Parkins
S
5

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

Saccharine answered 8/12, 2010 at 22:13 Comment(2)
Assuming element references a HTML DIV Element, element.currentStyle returns undefined and element.getComputedStyle() throws error (undefined too), in Chrome.Argufy
although this method is explained in the second answerArgufy
S
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

Shaunda answered 1/1, 2021 at 10:30 Comment(0)
A
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

Albertoalberts answered 26/2, 2022 at 16:17 Comment(1)
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.Sharyl
M
1

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;
}
Mosira answered 12/7, 2023 at 17:12 Comment(0)
L
-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 }
Limeade answered 4/8, 2021 at 16:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.