I solved this using jQuery. Until new CSS rules allow for this type of behavior natively I find it is the best way to do it.
Setup your divs
Below you have your div that you want the background to appear on ("hero") and then the inner content/text you want to overlay on top of your background image ("inner"). You can (and should) move the inline styles to your hero class. I left them here so it's quick and easy to see what styles are applied to it.
<div class="hero" style="background-image: url('your-image.png'); background-size: 100%; background-repeat: no-repeat; width: 100%;">
<div class="inner">overlay content</div>
</div>
Calculate image aspect ratio
Next calculate your aspect ratio for your image by dividing the height of your image by the width. For example, if your image height is 660 and your width is 1280 your aspect ratio is 0.5156.
Setup a jQuery window resize event to adjust height
Finally, add a jQuery event listener for window resize and then calculate your hero div's height based off of the aspect ratio and update it. This solution typically leaves an extra pixel at the bottom due to imperfect calculations using the aspect ratio so we add a -1 to the resulting size.
$(window).on("resize", function ()
{
var aspect_ratio = .5156; /* or whatever yours is */
var new_hero_height = ($(window).width()*aspect_ratio) - 1;
$(".hero").height(new_hero_height);
}
Ensure it works on page load
You should perform the resize call above when the page loads to have the image sizes calculated at the outset. If you don't, then the hero div won't adjust until you resize the window. I setup a separate function to do the resize adjustments. Here's the full code I use.
function updateHeroDiv()
{
var aspect_ratio = .5156; /* or whatever yours is */
var new_hero_height = ($(window).width()*aspect_ratio) - 1;
$(".hero").height(new_hero_height);
}
$(document).ready(function()
{
// calls the function on page load
updateHeroDiv();
// calls the function on window resize
$(window).on("resize", function ()
{
updateHeroDiv();
}
});