Search code examples
javascriptjquerycssflickerouterheight

jQuery outerHeight() & height change flicker/fail on window resize to odd pixels


I have two side-by-side elements on a page. One elements has a fixed size (100vh) – .hero-half – and the other is fluid with text of varying lengths – .project-details. When the fluid text container extends to be taller than the image container, I want to apply a class to it that restricts the height of one of its child elements to bing the total text container height back to equal with the image height.

HTML:

        <div class="project-details left">
          <h1 class="project">Title</h1>
          <div class="project-summary">
            <div class="summary-container">
              <p>A bunch of paragraphs here</p>
            </div>
            <a class="more" href="#">More</a>
            <a class="less" href="#">Less</a>
          </div>
        </div>
        <div class="hero hero-half right" style="background-image: url('/img/placeholder-vert1.jpg')"></div>

The relevant CSS:

.hero-half {
  width: 50%;
  height: 100vh;
}

.project-details {
  width: 50%;
  height: auto;
}

.project-summary .summary-container {
  overflow: hidden;

  &.restrict-height {

    .summary-container {
      // set max height
      max-height: calc(100vh - 615px);
    }
  }
}

Here is my JS code:

$(function () {

  var bpTab = 1024;

  resize = function() {
    var winWidth = $(window).width();
    var heroHeight = $(".hero-half").outerHeight();
    var boxHeight = $(".project-details").outerHeight();
    var $box = $(".project-summary");

    if ( boxHeight > heroHeight && winWidth > bpTab) {
      // if on desktop layout AND if text is pusing box too big, restrict box height
      $box.addClass("restrict-height");
    } else {
      // if not on desktop or text is not pushing box too big
        $box.removeClass("restrict-height");
      $box.removeClass("is-expanded");
    }; 
  };

  // resize on window resize 
  $(window).bind("resize orientationchange", function(){
    resize(); 
  });

  // resize on page load
  resize();
});

So when the project-details div reaches a height taller than .hero-half, it adds a class that sets a max-height on one of the children, which brings the total height of .project-details back to equal or less than .hero-half.

However when I resize my window to force the the text to push the project-details height too tall and trigger the restrict-height class, it only works when the screen width and height add up to even numbers (either both width and height are even, or both odd). If it's an odd total the outerHeight of project-details seems to calculate incorrectly.

The problem, I think, is that the outerHeight of .project-details is sometimes being calculated at it's natural height before the text height it restricted, and sometimes it's being calculates after that class is applied and after the text height it restricted, which therefor decreases the .project-details height back into an acceptable range.

I've tried adding a timeout delay for the addition of the class hoping that the extra time would mean the outerHeight calculation was always correct, but it didn't make a difference.

How should I alter this JS code to make sure the .project-details outerHeight is always reading the height before the restrict-height class is applied?

And related: why would the odd pixel dimensions have any effect here?


Solution

  • The solution was at add a reset before the if/else loop to standardise the div height be removing the extra classes that may alter its height first.

    var $box = $(".project-summary");
    
    // reset
    $box.removeClass("restrict-height");
    $box.removeClass("is-expanded");
    
    var winWidth = $(window).width();
    var heroHeight = $(".hero-half").outerHeight();
    var boxHeight = $(".project-details").outerHeight();