Ok. This is impossible using CSS, so here is a how to do it using jQuery.
To acheive the transition, we'll have to use two divs, one in the background and one in the front that will fade in giving us the illusion of transition. The .bg div should contain those two divs:
<div class="bg">
<div class="back"></div>
<div class="front"></div>
</div>
The css should change to:
.bg {
position: absolute;
width: 100%;
height: 100%;
z-index: -1;
background-color: #989898;
background-blend-mode: multiply;
transition: background-image 1s ease
}
.bg > * {
background: url(http://ejournalz.com/wp-content/uploads/2017/06/Dog-Care.jpg) no-repeat center;
background-size: cover;
position: absolute;
width: 100%;
height: 100%;
}
Which just removes any css transitions and make the inner divs overlap and as big as their parent .bg.
Now for the js part - where the actual transition takes place. When the mouse enters a .p area, we just call the function changeTo with the corresponding image. The function takes the current image from the front to the back, sets the new image as the front image. Doing that will be choppier than the css transition because the opacity doesn't match. Making the front image the back one should be accompaigned with an invertion of the opacity of the front. That is achieved by just getting the opacity and substracting it from 1. After we do that, we just animate the front image opacity from whatever value it is now to 1. The speed of this animation should be relative to what the opacity is:
var $back = $(".bg .back"),
$front = $(".bg .front");
function changeTo(img) {
$front.stop(); // stop any animation that may be in progress
var op = $front.css("opacity"); // get the opacity value (stoping the animation will let the opacity hanging between 0 and 1 inclusive, so we get that value to transition from it)
$back.css("background-image", $front.css("background-image")); // make the front image the back one
$front.css({
opacity: 1 - op, // because we made the front image the back one we need to invert the front image's opacity to give the illusion that the back image (which is now the front one) is shown at the original opacity. That's how math works!
"background-image": img // and of course make the front image our desired one
});
$front.animate({ // animate the front image's
opacity: 1 // ... opacity from whatever value it is to 1
}, 500 * op, "linear"); // in a period of 0.5s accouunting for the opacity delta, in other words animating from opacity 0.5 to 1 will take only half the time as animating from 0 to 1. That also how math works! :P
}
$('.p1').on("mouseenter", function() { // when mouse enters .p1
changeTo(img1); // change to img1
});
$('.p2').o...
Working example:
var img1 = 'url(http://ejournalz.com/wp-content/uploads/2017/06/Dog-Care.jpg)';
var img2 = 'url(https://www.focusdogtraining.com/wp-content/uploads/2017/10/puppies.jpg)';
var img3 = 'url(https://www-tc.pbs.org/wgbh/nova/assets/img/full-size/clever-dog-lab-merl.jpg)';
var $back = $(".bg .back"),
$front = $(".bg .front");
function changeTo(img) {
$front.stop();
var op = $front.css("opacity");
$back.css("background-image", $front.css("background-image"));
$front.css({
opacity: 1 - op,
"background-image": img
});
$front.animate({
opacity: 1
}, 500, "linear");
}
$('.p1').on("mouseenter", function() {
changeTo(img1);
});
$('.p2').on("mouseenter", function() {
changeTo(img2);
});
$('.p3').on("mouseenter", function() {
changeTo(img3);
});
.bg {
position: absolute;
width: 100%;
height: 100%;
z-index: -1;
background-color: #989898;
background-blend-mode: multiply;
transition: background-image 1s ease
}
.bg > * {
background: url(http://ejournalz.com/wp-content/uploads/2017/06/Dog-Care.jpg) no-repeat center;
background-size: cover;
position: absolute;
width: 100%;
height: 100%;
}
.projects {
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100vw;
height: 16em;
}
.p {
font-size: 1.2em;
position: relative;
padding: 2rem 0;
color: #fff;
opacity: 0.5;
letter-spacing: 4px;
text-indent: 4px;
font-weight: 400;
transition: opacity 0.5s ease;
text-align: center;
}
.p:hover {
opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="bg">
<div class="back"></div>
<div class="front"></div>
</div>
<div class="projects">
<div class="p p1">1</div>
<div class="p p2">2</div>
<div class="p p3">3</div>
</div>