cssflexboxoverlaycenteringcross-fade

How can I crossfade images inside a flexbox container?


To crossfade two images using CSS we normally do something like this (assume cross-browser compatibility for transitions is present in CSS)

#crossfade img {
  position: absolute;
  left: 0;
  width: 200px;
  transition: opacity 1s ease-in-out;
}
#crossfade img.top:hover {
  opacity: 0;
}
<div id="crossfade">
  <img class="bottom" src="http://badd.ie./_images/google-logo.png" />
  <img class="top" src="http://badd.ie./_images/chrome-logo.png" />
</div>

So far, so usual.

Now, if I want to vertically centre the images, I'd use flexbox:

CSS:

#crossfade {
  display: flex;
  align-items: center;
  justify-content: center;
}

But two problems arise. First, position: absolute; breaks the flexbox centering because the top left pixel of the image is centred by flexbox instead of the centre pixel. And second, using flexbox means that the images are now side by side and no longer overlaid on top of each other.

I've tried adding a container div around the images, centering that and then absolutely positioning the images within that but it made no difference. They both still appeared side by side and off center.

EDIT: Second issue solved. Thanks Chaz. See an MCVE below for better idea of what I'm trying to do. This is pretty much as-is except I've swapped out FontAwesome stuff for question marks.

EDIT: Both issues now solved. Thanks Neil. The below snippet has been updated to show working.

var minHeaderHeight = 100; // Height of shrunken header, in pixels
var header = document.querySelector("#header"); // The header object
var maxHeaderHeight = outerHeight(header, true); // Height of expanded header, in pixels

document.addEventListener("DOMContentLoaded", initHeader);

function initHeader() {
	var	landingImage = document.getElementById("landing-image");
	if (landingImage !== null) { 
		header.classList.add("expanded");
    window.addEventListener('scroll', scrollCallback);
	} else {
		header.parentNode.style.paddingTop = minHeaderHeight + "px";
	}
}

function scrollCallback() {
	var scrollOffset = windowScrollTop();
	var transitionEvent;
	if (scrollOffset > 10) {
		header.classList.remove("expanding");
		header.classList.add("shrinking");
		header.classList.remove("expanded");
	} else {
		header.classList.remove("shrinking");
		header.classList.add("expanding");
		header.classList.add("expanded");
	}
}

// THESE TWO FUNCTIONS REPLICATE SIMILAR FUNCTIONS FROM JQUERY
function outerHeight(el, withMargins) {
	withMargins = withMargins || false;
	if (withMargins) {
	  var height = el.offsetHeight;
	  var style = getComputedStyle(el);
	  height += parseInt(style.marginTop) + parseInt(style.marginBottom);
	  return height;
	} else {
		return el.offsetHeight;
	}
}

function windowScrollTop(pos) {
	if (typeof pos === 'undefined') {
		if (window.pageYOffset !== undefined) {
			return window.pageYOffset;
		} else {
			return (document.documentElement || document.body.parentNode || document.body).scrollTop;
		}
	} else {
		document.documentElement.scrollTop = pos;
		document.body.parentNode.scrollTop = pos;
		document.body.scrollTop = pos;
		window.pageYOffset = pos;
	}
}
#header {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  display: flex;
  justify-content: space-around;
  align-items: center;
  background-color: #000;
  height: 100px;
  text-transform: uppercase;
  font-size: 2em;
  color: white;
}

#header a {
	color: white;
  text-decoration: none;
}

#header-inner {
	width: 100%;
  z-index: 1;
  display: flex;
  justify-content: space-around;
  align-items: center;
}
 
#header.expanded {
	height: 100vh;
	background-color: transparent;
}

#header.expanding {
	-webkit-transition: height 300ms ease-in-out, background 300ms ease-in;
	-moz-transition: height 300ms ease-in-out, background 300ms ease-in;
	-ms-transition: height 300ms ease-in-out, background 300ms ease-in;
	-o-transition: height 300ms ease-in-out, background 300ms ease-in;
  transition: height 300ms ease-in-out, background 300ms ease-in;
}

#header.shrinking {
	-webkit-transition: height 300ms ease-in-out, background 300ms ease-in;
	-moz-transition: height 300ms ease-in-out, background 300ms ease-in;
	-ms-transition: height 300ms ease-in-out, background 300ms ease-in;
	-o-transition: height 300ms ease-in-out, background 300ms ease-in;
  transition: height 300ms ease-in-out, background 300ms ease-in;
}

#header-logos {
	position: relative;
}

#header-logos img {
	position: absolute;
	top: 50%;
	left: 50%;
    transform: translate(-50%, -50%);
	max-height: 100px;
}

#header.shrinking img {
	-webkit-transition: opacity 300ms ease-in-out, max-height 300ms ease-in-out;
  -moz-transition: opacity 300ms ease-in-out, max-height 300ms ease-in-out;
  -ms-transition: opacity 300ms ease-in-out, max-height 300ms ease-in-out;
  -o-transition: opacity 300ms ease-in-out, max-height 300ms ease-in-out;
  transition: opacity 300ms ease-in-out, max-height 300ms ease-in-out;
}

#header.expanding img {
	-webkit-transition: opacity 300ms ease-in-out, max-height 300ms ease-in-out;
  -moz-transition: opacity 300ms ease-in-out, max-height 300ms ease-in-out;
  -ms-transition: opacity 300ms ease-in-out, max-height 300ms ease-in-out;
  -o-transition: opacity 300ms ease-in-out, max-height 300ms ease-in-out;
  transition: opacity 300ms ease-in-out, max-height 300ms ease-in-out;
}

#header-logo-top {
	opacity: 0;
}

#header.expanded #header-logo-top {
	opacity: 1;
}

#header.expanded img {
  max-height: 500px;
}

#landing-image {
	height: 100vh;
	background-position: center;
	background-repeat: no-repeat;
	background-size: cover;
}

#landing-image.home-page {
	background-image: url("https://upload.wikimedia.org/wikipedia/commons/2/2f/KANTHALLOOR%2CEruvikulam%26Anamalais_in_the_background.jpg");
}

#page-content {
    max-width: 750px;
}
<div id="header">
  <div id="header-inner">
	  <div class="header-button menu-bars">
	      <a href="#">?</a>
	  </div>
    <div id="header-link-1" class="header-button">
        <a href="#" class="btn">Link 1</a>
    </div>
    <div id="header-link-2" class="header-button">
        <a href="#" class="btn">Link 2</a>
    </div>
    <div id ="header-logos" class="header-button">
			<a href="#"><img id="header-logo-bottom" src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Google_%22G%22_Logo.svg/1000px-Google_%22G%22_Logo.svg.png"></a>
			<a href="#"><img id="header-logo-top" src="https://upload.wikimedia.org/wikipedia/commons/thumb/e/e2/Google_Chrome_icon_%282011%29.svg/2000px-Google_Chrome_icon_%282011%29.svg.png"></a>
	  </div>
    <div id="header-dates" class="header-button">
        1 | 2 | 3 JAN 2018
    </div>
    <div id="header-socials" class="header-button">
			<a href="#">?</a>
			<span>|</span>
			<a href="#">?</a>
			<span>|</span>
			<a href="#">?</a>
			<span>|</span>
			<a href="#">?</a>
			<span>|</span>
			<a href="#">?</a>
    </div>
	  <div class="header-button spacer">
	  </div>
  </div>
</div>
<div id="landing-image" class="home-page"></div> 
<div id="page-content">
LOREM IPSUM DOLOR SIT AMET, consectetur adipiscing elit. Nullam scelerisque magna non dui auctor placerat. Vestibulum cursus placerat mauris eget luctus. Maecenas sollicitudin mauris id erat porttitor, in dapibus ligula commodo. Donec sagittis sagittis felis non elementum. Nam facilisis non sapien non ultrices. Morbi cursus molestie nibh non tincidunt. Sed sagittis erat eu enim condimentum, ut lobortis nisi faucibus. Cras orci felis, molestie in ligula sit amet, vestibulum malesuada augue. Nullam id aliquam enim, eu vestibulum massa. Mauris ultricies ante sit amet leo ullamcorper, a lacinia nulla hendrerit. Aenean eros dolor, semper non nisi eu, maximus accumsan felis. Donec facilisis pellentesque lacus, quis vestibulum ipsum pretium tempus. 
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Interdum et malesuada fames ac ante ipsum primis in faucibus. Ut ultrices quam quis augue scelerisque, vitae hendrerit nunc iaculis. Morbi lobortis, arcu non luctus scelerisque, quam libero ullamcorper neque, eget rhoncus nulla enim sit amet metus. Praesent eget risus euismod, posuere turpis in, lobortis dui. Aliquam mattis leo elit, a accumsan urna maximus a. Duis lacinia ex hendrerit, lobortis massa volutpat, lacinia mi. Vivamus ullamcorper mauris libero, a semper justo vulputate ut. In eget semper nibh. Fusce venenatis maximus nisi. Integer vel suscipit risus. Nulla mollis est a velit molestie pharetra. Donec sed imperdiet dui, id ultricies massa. Aliquam dictum arcu ac viverra fringilla. In placerat lorem in egestas cursus. Sed eleifend tortor quis augue accumsan, eget rhoncus turpis finibus. 
Fusce aliquet finibus lectus, bibendum ornare ex aliquam nec. Fusce efficitur felis luctus fermentum ullamcorper. Maecenas eget urna nibh. Nulla luctus sit amet sem eget interdum. Aenean placerat fermentum metus, a tempus purus imperdiet quis. Aliquam ac quam a dui volutpat sagittis. Duis mollis scelerisque tristique. Quisque lacinia consectetur metus, non vulputate tortor malesuada sed. Curabitur dictum ac risus in elementum. 
Vivamus ultricies lacinia tempus. Donec eu mi arcu. Ut porttitor nulla vel elit faucibus condimentum. Mauris volutpat orci non libero tristique, vel euismod nisi aliquam. Phasellus fermentum euismod erat vitae feugiat. Nulla venenatis auctor venenatis. Praesent ullamcorper eget odio ac blandit. Aliquam non lacus a risus aliquet ornare eget id justo. Donec quis elementum orci, non dapibus lectus. Mauris sodales tortor id leo posuere feugiat. Cras congue commodo justo, a commodo dolor luctus ut. Quisque fringilla rhoncus nunc, eget tincidunt justo pharetra quis. Donec condimentum dapibus ex, non condimentum ex varius eu. Maecenas a lectus ut ipsum interdum vulputate. Morbi ac lorem a turpis sollicitudin bibendum non eu lectus. Quisque pretium lacus eu ipsum eleifend efficitur. 
Nulla fermentum enim quis sapien accumsan, sit amet consectetur justo laoreet. Integer tortor nibh, dapibus quis nisi nec, euismod sagittis arcu. Ut vehicula nisi vitae ante efficitur congue. Vivamus malesuada facilisis tortor. Maecenas maximus felis at justo finibus volutpat vitae sed dolor. Suspendisse quis nulla massa. Aliquam dignissim leo ut arcu viverra fringilla. Morbi convallis dignissim augue, at pharetra purus. Cras neque elit, dictum et eros eget, faucibus varius ligula. In tincidunt dolor quis accumsan ornare. Ut eget efficitur sapien. Maecenas nunc justo, malesuada quis porta quis, dignissim ac enim. Nulla vestibulum odio ac sem egestas, et lobortis metus aliquam. Mauris at tincidunt erat. Fusce ut dictum diam. 
Sed luctus sem vel euismod imperdiet. Fusce non tincidunt elit, id aliquet ipsum. Aliquam quam libero, tincidunt id diam eu, pretium porta velit. Mauris placerat efficitur ipsum non fringilla. In suscipit ipsum quis leo faucibus, ut porttitor diam porta. Donec luctus, mauris non posuere aliquam, neque velit euismod ipsum, vitae ornare erat sapien in nulla. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nunc consequat tortor sed dui placerat lacinia. Vivamus tempus ultrices massa, vitae sagittis enim convallis sed. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. 
Phasellus volutpat, dolor vel laoreet efficitur, nunc mauris tempus velit, at rhoncus orci magna ut eros. Proin elementum, nibh vitae eleifend venenatis, ante lacus iaculis arcu, nec varius justo nunc nec lorem. In faucibus ligula dui, vitae tincidunt libero ullamcorper sit amet. In in consectetur velit. Proin non elit ut purus ullamcorper ultricies sed pharetra ex. Proin neque elit, suscipit quis dui id, varius consequat libero. Aenean pharetra massa vel tortor hendrerit bibendum. Phasellus aliquam vulputate neque eu interdum. Quisque commodo faucibus ullamcorper. Morbi accumsan, nisl id porta bibendum, metus tortor faucibus leo, in volutpat arcu enim a nunc. Vestibulum hendrerit, mi vel bibendum tincidunt, nibh sem sagittis purus, quis tincidunt nibh magna in sem. Nunc placerat mollis dolor, at volutpat libero commodo id. Suspendisse suscipit mattis libero, suscipit iaculis nibh rhoncus et. 
Quisque vitae metus diam. Cras at tempus ipsum. Etiam gravida ornare ante, vitae facilisis lacus maximus vitae. Donec gravida interdum ante, quis euismod urna vulputate id. Suspendisse diam nunc, interdum nec elementum vel, dapibus at risus. Phasellus varius scelerisque mi. Duis scelerisque neque sit amet ligula gravida pharetra. Duis pretium id lectus id viverra. Sed pellentesque, sem in rhoncus euismod, justo libero tincidunt erat, id pellentesque ex sapien gravida quam. Duis urna nisl, accumsan quis mi molestie, finibus pellentesque metus. Aenean semper velit id neque dignissim, eget gravida lacus interdum. Nullam a tincidunt justo, et fermentum eros. Nunc eget dolor erat. Integer id lorem finibus, sodales nunc ut, vulputate est. 
Donec varius nulla eros, quis accumsan velit euismod nec. Sed tempus nulla sed faucibus sodales. Mauris at ligula arcu. Integer vulputate tincidunt arcu sit amet lacinia. Integer placerat quis lectus lobortis sagittis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque ac pretium enim. Donec libero turpis, pellentesque non sagittis quis, vehicula at ex. Maecenas semper purus sed blandit tincidunt. Ut in scelerisque mi. Vivamus erat nunc, sagittis non augue blandit, molestie porttitor nunc. Aliquam laoreet non dolor vitae varius. Proin lorem dui, maximus ac tortor in, faucibus tristique ex.
</div>


Solution

  • Thanks go to both Neil and Chaz below. The answer is as follows:

    Inside the flexbox item you have a container for the images. Then the following styling applies to the container and the images:

    .image-container {
      position: relative;
    }
    
    .image-container img {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }
    

    Then the image container can be placed inside a flexbox item container.

    I have updated the code snippet above to show it working.