To achieve a smooth transition between two background images, my recommendation is to utilize the ::before
and ::after
pseudo-elements with background images. By adjusting the opacity on one of these elements, you can create the desired effect seamlessly.
For clarity, let me showcase the step-by-step modifications. The code snippet presented below mirrors the behavior of your original code, focusing solely on defining the --background-image
.
I want to emphasize the importance of avoiding the use of float
and position: absolute
unless you possess a thorough understanding of their impact on page flow. Following this principle, I have made adjustments in the CSS to eliminate those properties. Additionally, dealing with Bootstrap can be challenging as it often necessitates overriding default styles, much like how your CSS conflicted with Boostrap's implementation in the supplied snippet.
var index = 0;
var imageList = [];
var ANIMATION_DURATION = 8000;
imageList[0] = 'https://example.com/image1.jpg';
imageList[1] = 'https://example.com/image2.jpg';
imageList[2] = 'https://example.com/image3.jpg';
function switchImage() {
let nextIndex = index++ % imageList.length;
document.getElementById('hero-section').style.setProperty('--background-image', `url(${imageList[nextIndex]}`);
setTimeout(switchImage, ANIMATION_DURATION);
}
window.onload = switchImage;
#hero-section {
--foreground-img: '';
--background-image: '';
position: relative;
height: 100vh;
background-image: linear-gradient(to right bottom, #0d146f, transparent);
}
#hero-section::before,
#hero-section::after {
content: '';
position: absolute;
inset: 0px;
background-image: var(--foreground-img);
background-position: center;
background-size: cover;
background-repeat: no-repeat !important;
z-index: -1;
}
#hero-section::after {
background-image: var(--background-image);
z-index: -2;
}
.center {
display: inline-block;
position: relative;
margin-top: 10%;
margin-left: 20%;
text-align: center;
}
<html lang="en">
<head>
<link href="https://cdn.example.com/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-exampleHashValue" crossorigin="anonymous">
</head>
<body>
<div id="hero-section" class="text-white">
<div class="center" slot="float: right;">
<h3>Welcome!</h3>
<p>Lorem ipsum dolor sit amet</p>
</div>
</div>
<script src="https://cdn.example.com/js/bootstrap.bundle.min.js" integrity="sha384-exampleHashValue" crossorigin="anonymous"></script>
</body>
</html>
Expanding upon the previous code fragment, I've arranged for the outgoing visible image to act as the foreground image (::before
) while gradually fading out to reveal the new background image set at the back (::after
).
Furthermore, I have included animation speed configurations directly in the code for straightforward adjustment, eliminating the need to juggle values across multiple files if customization is required.
As an additional enhancement, preloading of subsequent images has been integrated. This ensures a smooth transition without transitioning to unloaded images.
var index = 0;
var imageList = [];
var nextImage = new Image();
var ANIMATION_DURATION = 8000;
var FADE_SPEED = 1500;
imageList[0] = 'https://example.com/image1.jpg';
imageList[1] = 'https://example.com/image2.jpg';
imageList[2] = 'https://example.com/image3.jpg';
function switchImage() {
let heroSectionEl = document.getElementById('hero-section');
let currentImg = (index-1) % imageList.length;
let currIndex = index++ % imageList.length;
let nextIndex = index % imageList.length;
if (nextImage.src) {
heroSectionEl.style.setProperty('--foreground-img', `url(${imageList[currentImg]}`);
heroSectionEl.style.setProperty('--background-image', `url(${imageList[currIndex]}`);
heroSectionEl.style.setProperty('--fade-speed', FADE_SPEED + 'ms');
toggleForegroundFade();
setTimeout(toggleForegroundFade, FADE_SPEED);
} else {
heroSectionEl.style.setProperty('--background-image', `url(${imageList[currIndex]}`);
}
setTimeout(() => {
nextImage.src = imageList[nextIndex];
}, FADE_SPEED);
setTimeout(switchImage, ANIMATION_DURATION);
}
function toggleForegroundFade() {
document.getElementById('hero-section').classList.toggle('foreground-hidden');
}
window.onload = switchImage;
#hero-section {
--foreground-img: '';
--background-image: '';
--fade-speed: '';
position: relative;
height: 100vh;
background-image: linear-gradient(to right bottom, #0d146f, transparent);
}
#hero-section.foreground-hidden::before {
opacity: 0;
transition: opacity var(--fade-speed);
}
#hero-section::before,
#hero-section::after {
content: '';
position: absolute;
inset: 0px;
background-image: var(--foreground-img);
background-position: center;
background-size: cover;
background-repeat: no-repeat !important;
z-index: -1;
}
#hero-section::after {
background-image: var(--background-image);
z-index: -2;
}
.center {
display: inline-block;
position: relative;
margin-top: 10%;
margin-left: 20%;
text-align: center;
}
<html lang="en">
<head>
<link href="https://cdn.example.com/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-exampleHashValue" crossorigin="anonymous">
</head>
<body>
<div id="hero-section" class="text-white foreground-hidden">
<div class="center">
<h3>Welcome!</h3>
<p>Lorem ipsum dolor sit amet</p>
</div>
</div>
<script src="https://cdn.example.com/js/bootstrap.bundle.min.js" integrity="sha384-exampleHashValue" crossorigin="anonymous"></script>
</body>
</html>