<p>Resize this frame to see the responsive effect.</p>
<p><i>Restricted width at larger vieweports for demo purposes:</i></p>
<div class="overlay-stacked-module md-50">
  <div class="overlay-stacked-module__image">
    <img src="https://res.cloudinary.com/andykirk/image/upload/v1488115638/nasa/pia20700.jpg" alt="Artist’s concept shows an unusual celestial object called CX330">
  </div>
  <div class="overlay-stacked-module__pull"></div>
  <div class="overlay-stacked-module__body">
    <h2>The Loneliest Young Star</h2>
    <p><b>An unusual celestial object called CX330 was first detected as a source of X-ray light in 2009. It has been launching “jets” of material into the gas and dust around it.</b></p>
    <p>
     <cite>—
        <a href="https://www.nasa.gov/multimedia/imagegallery/iotd.html">NASA</a>
      </cite>
    </p>
  </div>
</div>

<div class="overlay-stacked-module">
  <div class="overlay-stacked-module__image">
    <img src="https://res.cloudinary.com/andykirk/image/upload/v1488115638/nasa/pia20700.jpg" alt="Artist’s concept shows an unusual celestial object called CX330">
  </div>
  <div class="overlay-stacked-module__pull"></div>
  <div class="overlay-stacked-module__body">
    <h2>The Loneliest Young Star</h2>
    <p><b>An unusual celestial object called CX330 was first detected as a source of X-ray light in 2009. It has been launching “jets” of material into the gas and dust around it.</b></p>
    <p>
      <cite>—
        <a href="https://www.nasa.gov/multimedia/imagegallery/iotd.html">NASA</a>
      </cite>
    </p>
  </div>
</div>

<div class="overlay-stacked-module md-50">
  <div class="overlay-stacked-module__image">
    <img src="https://res.cloudinary.com/andykirk/image/upload/v1488115638/nasa/pia20492-1041.jpg" alt="Dione">
  </div>
  <div class="overlay-stacked-module__pull"></div>
  <div class="overlay-stacked-module__body">
    <h2>A Moon's Contrasts</h2>
    <p><b>Dione reveals its past via contrasts in this view from NASA's Cassini spacecraft.</b></p>
    <p>
      <cite>—
        <a href="https://www.nasa.gov/multimedia/imagegallery/iotd.html">NASA</a>
      </cite>
    </p>
  </div>
</div>

<div class="overlay-stacked-module">
  <div class="overlay-stacked-module__image">
    <img src="https://res.cloudinary.com/andykirk/image/upload/v1488115638/nasa/pia20492-1041.jpg" alt="Dione">
  </div>
  <div class="overlay-stacked-module__pull"></div>
  <div class="overlay-stacked-module__body">
    <h2>A Moon's Contrasts</h2>
    <p><b>Dione reveals its past via contrasts in this view from NASA's Cassini spacecraft.</b></p>
    <p>
      <cite>—
        <a href="https://www.nasa.gov/multimedia/imagegallery/iotd.html">NASA</a>
      </cite>
    </p>
  </div>
</div>

<div class="overlay-stacked-module md-50">
  <div class="overlay-stacked-module__image">
    <img src="https://res.cloudinary.com/andykirk/image/upload/v1488115637/nasa/ngc6357.jpg" alt="NGC 6357">
  </div>
  <div class="overlay-stacked-module__pull"></div>
  <div class="overlay-stacked-module__body">
    <h2>Cosmic ‘Winter’ Wonderland </h2>
    <p><b>Although there are no seasons in space, this cosmic vista invokes thoughts of a frosty winter landscape.</b></p>
    <p>It is, in fact, a region called NGC 6357 where radiation from hot, young stars is energizing the cooler gas in the cloud that surrounds them.</p>
    <p>
      <cite>—
        <a href="https://www.nasa.gov/multimedia/imagegallery/iotd.html">NASA</a>
      </cite>
    </p>
  </div>
</div>

<div class="overlay-stacked-module">
  <div class="overlay-stacked-module__image">
    <img src="https://res.cloudinary.com/andykirk/image/upload/v1488115637/nasa/ngc6357.jpg" alt="NGC 6357">
  </div>
  <div class="overlay-stacked-module__pull"></div>
  <div class="overlay-stacked-module__body">
    <h2>Cosmic ‘Winter’ Wonderland </h2>
    <p><b>Although there are no seasons in space, this cosmic vista invokes thoughts of a frosty winter landscape.</b></p>
    <p>It is, in fact, a region called NGC 6357 where radiation from hot, young stars is energizing the cooler gas in the cloud that surrounds them.</p>
    <p>
      <cite>—
        <a href="https://www.nasa.gov/multimedia/imagegallery/iotd.html">NASA</a>
      </cite>
    </p>
  </div>
</div>
/* Basic common settings: */
$primary-color: rgb(0,20,30);
$secondary-color: rgb(171, 101, 20);
$module-breakpoint: 30em;

*, ::before, ::after {
  box-sizing: border-box;
}

body {
  font-family: 'Lato', sans-serif;
  font-size: 0.9375rem;
  line-height: 1.4;
  padding: 1rem;
  margin: 0;
}


img {
  /* Remove whitespace under images: */
  vertical-align: middle;
}

a {
  color: $secondary-color;
  &:hover {
    color: lighten($secondary-color, 50);
  }
}


/* Double last margin prevention hack. Not intended for production. */
p:last-of-type {
  margin-bottom: 0;
}

/*
  Demonstrate container query-esque responsiveness:
*/
@media only screen and (min-width:40em) {
  .md-50 {
    max-width: 50%;
  }
}


.overlay-stacked-module {
  /* Cosmetics (not part of the pattern): */
  margin-bottom: 1em;
  background: $primary-color;
  color: #fff;
  /*border: 1px solid $primary-color;*/
  /*box-shadow: 0 0 6px 3px rgba($primary-color, 0.2);*/
  
  /*
    If the 'pull' is > module body content height, it'll protrude below the container, so hide it:
  */
  overflow: hidden;
}

.overlay-stacked-module__image {
  position: relative;
}

.overlay-stacked-module__image::after {
  content: "";
  display: block;
  position: absolute;
  left: 0;
  top: 0;
  /* Extra .5% to prevent bleed due to rounding: */
  height: 100.5%;

  /* Gradient to make the text more legible: */
  background-image: linear-gradient(to bottom, rgba($primary-color,0) 0%,rgba($primary-color,0) 50%,rgba($primary-color,1) 100%);

  /* Toggle gradient overlay at the same breakpoint as the 'pull': */
  width: calc((#{$module-breakpoint} - 100%) * -1000);
  max-width: 100%;
}

.overlay-stacked-module__image img {
  width: 100%;
}

.overlay-stacked-module__pull {
  /* Pull the text up over the image by this much: */
  margin-bottom: -10em;
  /* Don't allow this container to be larger than the same amount: */
  max-height: 10em;
  /* and hide any overflow, just to be on the safe side: */
  overflow: hidden;
}

.overlay-stacked-module__pull::before {
  content: "";
  display: block;
  /* Create the 'switch': */
  padding-bottom: calc((#{$module-breakpoint} - 100%) * 1000);
}

/*
Padding is based on width so we can have a width-based breakpoint.
Comparing it to the container width (100%) and multiplying it lots gives huge postive or negative padding.
Negative padding is invalid and thus treated as 0, so in effect we have padding = zero OR lots based on the container.
This padding then makes the parent have a height of zero OR lots, but the max-height means the switch goes between 0 and 9em.
*/

.overlay-stacked-module__body {
  padding: 1em;
  /* Ensure the body appears above the image: */
  position: relative;
}

External CSS

  1. https://fonts.googleapis.com/css?family=Lato

External JavaScript

This Pen doesn't use any external JavaScript resources.