<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sed voluptates, cupiditate ratione impedit maxime corporis delectus quo consequuntur quis dolorem enim perferendis voluptas sit! Voluptatum soluta corporis harum quam beatae.</p>

<div id="adzone"></div>

<p>Consectetur nam eaque facilis, non consequatur laborum dicta vel autem, omnis unde commodi veniam eligendi quod nostrum quisquam blanditiis dolore? Asperiores odit quasi expedita voluptatum suscipit necessitatibus, amet architecto nemo.</p>
body {
  max-width: 300px;
  margin: 1rem auto;
}
p {
  margin: 1rem 0;
}

#adzone {
  max-height: 0;
  overflow: hidden;
}
.ad {
  background: lightyellow;
  padding: 1rem;
  p {
    margin: 0;
  }
  img {
    display: block;
    margin: 0 0 1rem 0;
  }
}

.test-height-element {
  position: absolute;
  top: -9999px;
  left: -9999px;
  padding: 1rem;
}



// We aren't using this, but if we wanted to go with a mostly-CSS solution, we could apply a class to the ad that used this. It's just not as nice with the magic number in there instead of measuring.
@keyframes slideOpen {
  to {
    max-height: 500px;
    padding: 1rem;
    margin: 0 0 1rem 0;
  }
}
// This is already in the DOM. It's where we're gonna drop in the ad.
var adZone = document.querySelector("#adzone");

// Dependency-free Ajax library
axios({
  method: 'GET',
  url: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/example-ad.html'
}).then(function(response) {
  
  // Any DOM manipulation we want to do we can do upfront
  var adHTML = "<div class='ad'>" + response.data + "</div>";
    
  // The CSS Way (not used in this tutorial)
  // adZone.classList.add("loaded");
  // We're going to do this mostly in JS
  
  // We need to figure this out!
  var ajaxContentHeight = 0;
  
  // We need a dummy element
  var testerElement = document.createElement("div");
  // That is exactly as wide as were we're putting the ad
  testerElement.style.width = adZone.offsetWidth;
  // Position it off screen though, nobody needs to see it
  testerElement.classList.add("test-height-element");
  // Temporarily put the ad in there
  testerElement.innerHTML = adHTML;
  // Plop it on the page for a sec
  document.body.appendChild(testerElement);
  // If there are any images in it, we need to wait for them to
  // load, otherwise our measuremenets will be off
  imagesLoaded(testerElement, function() {
    // Now we can measure the height!
    ajaxContentHeight = testerElement.offsetHeight + "px";
    // Nuke the dummy element
    testerElement.remove();
    // Drop the ad in the real place
    // It's collapsed by default
    adZone.innerHTML = adHTML;
    // Now apply some styles to allow it to transition 
    adZone.style.transition = "1s";
    adZone.style.maxHeight = ajaxContentHeight;
    // After it's done, remove the max height, in case of reflow
    setTimeout(function() {
      adZone.style.maxHeight = "none";
    }, 1001);
    
  });

});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/axios/0.15.3/axios.min.js
  2. https://unpkg.com/imagesloaded@4.1/imagesloaded.pkgd.js