How to detect if element has 'auto' height
Asked Answered
U

4

15

Both window.getComputedStyle(element).height and element.clientHeight are returning the current height of the element in pixels, regardless of the value set in the CSS.

Is there any way to find out if the height was set to auto, or other units than pixels ?


One solution that @pvnarula suggests through the page he linked is to temporarily change the contents of the element, then compare heights. A little bit hacky...

Unquestioned answered 11/6, 2013 at 12:42 Comment(0)
A
2

Update:

Based on other answers and lot of online research I came up with a mix of everything in a single function. Check out the jsfiddle here: https://jsfiddle.net/oriadam/d01ap7r6/3/

// input a jQuery element
// return true for elements with auto height (90-100% is considered auto as well)
// return false for elements with fixed height
function is_height_auto($e) {
    var e = $e[0],
        // check fixed style:
        chk = function(value) {
            return /\d/.test(value) && !/^(100|9\d)\%/.test(value);
        };

    // start from the first, easiest, inline styles
    if (chk(e.style.height)) {
        // console.log('fixed for having style', e.style.height)
        return false;
    }

    // start from the first, easiest, inline styles
    var overflow = getComputedStyle(e)['overflow'];
    if (overflow == 'scroll' || overflow == 'auto' || (e.tagName == 'BODY' && overflow == 'visible')) {
        // console.log('auto for having overflow or is body', getComputedStyle(e)['overflow'], e.tagName);
        return true;
    }

    // deprecated chrome way - check each rule that applies to the element
    if (typeof getMatchedCSSRules == 'function') {
        var i, MatchedCSSRules = getMatchedCSSRules(e) || [];
        for (i = MatchedCSSRules.length; i; i--) {
            if (MatchedCSSRules[i - 1].style.height) {
                // console.log('found height at MatchedCSSRules[' + (i - 1) + ']: ', MatchedCSSRules[i - 1], ' All matches: ', MatchedCSSRules)
                return !chk(MatchedCSSRules[i - 1].style.height);
            }
        }
    }

    // append something, see if height was changed, remove the something
    var originalHeight = $e.height(),
        $ghost = jQuery('<b style="display:block;height:1px;width:1px;padding:0;margin:0;">').appendTo($e),
        newHeight = $e.height();
    $ghost.remove(); // cleanup
    // console.log('Using a ghost got ',newHeight > originalHeight,' originalHeight=' + originalHeight + ' newHeight=' + newHeight) 
    return newHeight > originalHeight;
} //is_height_auto()

** Ghost element method explained (Previous answer):**

Greg Pettit had a pretty good answer in his blog, here is the main idea:

What’s unique about having auto height? Well, the fact that it allows height to change dynamically, of course!

  1. Clone the element
  2. Put it in visibility:hidden and position:absolute
  3. Remove it's content
  4. See if height changed (it should be around 0 now).
  5. Cleanup

    var isAutoHeight = function(element) { // make a staging area for all our work. $('body').append('');

    // assume false by default
    var autoHeight = false;
    
    // clone the div and move it; get its height
    var clone = element.clone();
    clone.appendTo('#stage');
    var initialHeight = clone.height();
    
    // destroy all the content and compare height
    clone.html('');
    var currentHeight = clone.height();
    if (currentHeight &lt; initialHeight) {
        autoHeight = true;
    }
    
    // get that clone and its smelly duplicate ID out of the DOM!
    clone.remove();
    // do the same for the stage
    $(&#039;#stage&#039;).remove();
    
    return autoHeight;
    

    };

Alhambra answered 9/6, 2015 at 19:32 Comment(0)
V
4

Please try:

document.getElementById("ele_id").style.height

Also check the following plugin:

http://gregpettit.ca/2012/jquery-check-if-element-has-auto-widthheight/

Vanda answered 11/6, 2013 at 12:44 Comment(3)
This works, but only if the style is applied inline, through the style attribute :(Unquestioned
thanks! I ended up cloning the element in the background then compared the heightsUnquestioned
You need to use getComputedStyle().Reputed
A
2

Update:

Based on other answers and lot of online research I came up with a mix of everything in a single function. Check out the jsfiddle here: https://jsfiddle.net/oriadam/d01ap7r6/3/

// input a jQuery element
// return true for elements with auto height (90-100% is considered auto as well)
// return false for elements with fixed height
function is_height_auto($e) {
    var e = $e[0],
        // check fixed style:
        chk = function(value) {
            return /\d/.test(value) && !/^(100|9\d)\%/.test(value);
        };

    // start from the first, easiest, inline styles
    if (chk(e.style.height)) {
        // console.log('fixed for having style', e.style.height)
        return false;
    }

    // start from the first, easiest, inline styles
    var overflow = getComputedStyle(e)['overflow'];
    if (overflow == 'scroll' || overflow == 'auto' || (e.tagName == 'BODY' && overflow == 'visible')) {
        // console.log('auto for having overflow or is body', getComputedStyle(e)['overflow'], e.tagName);
        return true;
    }

    // deprecated chrome way - check each rule that applies to the element
    if (typeof getMatchedCSSRules == 'function') {
        var i, MatchedCSSRules = getMatchedCSSRules(e) || [];
        for (i = MatchedCSSRules.length; i; i--) {
            if (MatchedCSSRules[i - 1].style.height) {
                // console.log('found height at MatchedCSSRules[' + (i - 1) + ']: ', MatchedCSSRules[i - 1], ' All matches: ', MatchedCSSRules)
                return !chk(MatchedCSSRules[i - 1].style.height);
            }
        }
    }

    // append something, see if height was changed, remove the something
    var originalHeight = $e.height(),
        $ghost = jQuery('<b style="display:block;height:1px;width:1px;padding:0;margin:0;">').appendTo($e),
        newHeight = $e.height();
    $ghost.remove(); // cleanup
    // console.log('Using a ghost got ',newHeight > originalHeight,' originalHeight=' + originalHeight + ' newHeight=' + newHeight) 
    return newHeight > originalHeight;
} //is_height_auto()

** Ghost element method explained (Previous answer):**

Greg Pettit had a pretty good answer in his blog, here is the main idea:

What’s unique about having auto height? Well, the fact that it allows height to change dynamically, of course!

  1. Clone the element
  2. Put it in visibility:hidden and position:absolute
  3. Remove it's content
  4. See if height changed (it should be around 0 now).
  5. Cleanup

    var isAutoHeight = function(element) { // make a staging area for all our work. $('body').append('');

    // assume false by default
    var autoHeight = false;
    
    // clone the div and move it; get its height
    var clone = element.clone();
    clone.appendTo('#stage');
    var initialHeight = clone.height();
    
    // destroy all the content and compare height
    clone.html('');
    var currentHeight = clone.height();
    if (currentHeight &lt; initialHeight) {
        autoHeight = true;
    }
    
    // get that clone and its smelly duplicate ID out of the DOM!
    clone.remove();
    // do the same for the stage
    $(&#039;#stage&#039;).remove();
    
    return autoHeight;
    

    };

Alhambra answered 9/6, 2015 at 19:32 Comment(0)
N
1

Ran into a bug using the method of clone->heightCheck->remove innerHTML->heightCompare. Where it does not register a change in height, even if the element has 100%/auto height.

Instead, this method appears to work:

let autoHeight = false;
// Set up stage area with 100% height/width
const stage = document.createElement('div');
      stage.setAttribute('style', "position: relative; height: 100%; width: 100%;");
// Add stage to body
document.body.appendChild(stage);
// Clone the element and append to stage
const clone = element.cloneNode(false);
stage.appendChild(clone);
// Get Initial Height
const initialHeight = clone.offsetHeight;
// Squish content
stage.setAttribute('style', "position: relative; height: 1px; width: 1px;");
// Get new height
const currentHeight = clone.offsetHeight;
// Get max height (if it exists)
const hasMaxHeight = getComputedStyle(clone)["maxHeight"];
// Compare
if (currentHeight < initialHeight && hasMaxHeight == 'none') {
  // Has 100% or auto height, and no maxHeight
} else if (hasMaxHeight !== 'none') {
  // Flexible, but has a maxHeight
} else {
  // Constrained by height size
}
// Remove elements
stage.remove();
Nicolnicola answered 4/2, 2021 at 16:57 Comment(0)
M
1

Starting by Oriadam answer I created following jQuery function:

/**
* Checks if the element has explicitly set height by CSS styles.
* E.g.:
* 
*      var $myElement = jQuery('.my-element');
*      if ($myElement.hasExplicitHeight()) {
*          //...
*      }
* 
* This function is needed as .height() or .css('height') return a value, even 
* if no height property was explicitly set using CSS. 
* 
* @returns {Boolean}
*/
jQuery.fn.hasExplicitHeight = function() {
    var $element = jQuery(this);
    var $clone = $element.clone();
    $clone.html('');
    $clone.css('visibility', 'hidden');
    $clone.css('position', 'absolute');
    $clone.insertAfter($element);
    var hasExplicitHeight = $element.css('height') === $clone.css('height');
    $clone.remove();
    return hasExplicitHeight;
};

It works fine under condition that it is called only after the document is ready:

jQuery(function() { 
    // this code is launched only after the document is ready
    jQuery('.my-element').hasExplicitHeight();
});
Mabel answered 16/2, 2022 at 10:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.