I\'ve found a CSS transition that works on hover just fine, it slides my background color over, but only on hover. Is there a way with CSS to make this happen on load not hover?
There is no way, using CSS alone, to delay the execution/application of an animation or transition effect until the exact moment a particular resource has been loaded. However, it can be done using JavaScript, but it's still tricky, as there is no load
/onload
event for background images loading (afaik).
But you could take advantage of browser's caching mechanism: it doesn't load a resource more than once if it is used several times in the page (unless under very specific circumstances, which are not default, hence don't apply here).
So the solution would be to use the background image of your element as src
of an , and trigger the animation inside the
onload
event of that .
Proof of concept:
body {
margin: 0;
min-height: 100vh;
background: #ccc url('https://s22849.pcdn.co/wp-content/uploads/2016/10/placeholder-large-1.png') no-repeat center 0;
transition: background-position 1s cubic-bezier(.4,0,.2,1);
}
body.loaded {
background-position: center center;
}
.placeholder {
height: 0;
}
The key parts are:
has a height of 0
(so it's not displayed).A cleaner way to do it is without adding the to DOM at all.
When changing the src
property of an , the browser will load it, even if it hasn't yet been added to the Document Object Model. And the
onload
event will still fire on that , as soon as the browser is ready to render it (which means right away for already cached images).
So all you need to do is create an , set its
src
to your element's current backgroundImage
(stripping the surrounding url()
) and, in its onload
event trigger the animation. In our case, that's done by adding loaded
class to the element.
const element = document.body,
src = window.getComputedStyle(element).backgroundImage.slice(4, -1).replace(/"/g, "");
if (src && src.length) {
const img = document.createElement('img');
img.onload = () => element.classList.add('loaded');
img.src = src;
}
body {
margin: 0;
min-height: 100vh;
background: #ccc url('https://s22849.pcdn.co/wp-content/uploads/2016/10/placeholder-large-1.png') no-repeat center 0;
transition: background-position 1s cubic-bezier(.4, 0, .2, 1);
}
body.loaded {
background-position: center center;
}
If you have trouble implementing the above into your project, provide more code (and I'll show you how to do it for your particular case).
As you can test, the animation is always performed after the image has loaded. (Test in an incognito window or with cache disabled).
An even better test would be to use a broken URL (while making it very obvious when the element has loaded
class - I added a red border to it). Since the resource is not found, the loaded
class should never be applied and the animation should not be performed.
Finally, after 4 seconds, let's place a valid backgroundImage
on the element, run our routine again and see if the background animates correctly:
function onLoadBackgroundImage(element) {
const src = window.getComputedStyle(element).backgroundImage.slice(4, -1).replace(/"/g, "");
if (src && src.length) {
const img = document.createElement('img');
img.onload = () => element.classList.add('loaded');
img.src = src;
}
}
/* 4 seconds later...
* we actually load a valid image so we can see
* if the animation happens when it loads or it already happened */
setTimeout(function() {
const el = document.body;
el.style.backgroundImage = `url('https://s22849.pcdn.co/wp-content/uploads/2016/10/placeholder-large-1.png')`;
onLoadBackgroundImage(el);
}, 4000);
body {
margin: 0;
min-height: 100vh;
background: #ccc url('https://non-existent-url') no-repeat center 0;
transition: background-position 1s cubic-bezier(.4, 0, .2, 1);
}
body.loaded {
background-position: center center;
border: 3px solid red; /* let's make the application of .loaded obvious */
box-sizing: border-box;
}