embiem
embiem

Reputation: 113

CSS Background image, fade once loaded

I want to fade-in the "image" once it is loaded from an external url, but show a "imgPlaceholder" right from the beginning from local resources.

The HTML looks like this:

  <div className="bg-img" style={imgDivStyle}></div>

The CSS looks like this:

const imgDivStyle = {
  background: `url('${image}'), url('${imgPlaceholder}')`,
  backgroundSize: 'cover',
};

What I want to happen: Show "imgPlaceholder" from beginning and Fade-in "image" once it is loaded.

What is actually happening: "imgPlaceholder" is shown from beginning "image" is showing up instantly once it is loaded.

Is this achievable by pure CSS? Or do I need to load in the image using e.g. jQuery and trigger an animation manually?

Upvotes: 2

Views: 397

Answers (2)

Pete
Pete

Reputation: 58442

You can't check if the image has loaded with css alone so you could do something like the following (comments in code to show what is happening):

$('.inner').each(function() {
  var div = $(this),
    background = div.data('background');  // get background

  $('<img/>').attr('src', background).load(function() {  // create an image element with inner background and load it
    $(this).remove();  // remove it
    
    // set the inner background image and fade in:
    div.css('background-image', 'url(' + background + ')').delay(200).fadeIn(2000); // need a little delay to let the div render it's bg image before the fade starts
  });
});
.default,
.inner {
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center;
  
  /* just make sure inner div is same size as outer */
  width: 400px;
  height: 400px;
}

.default {
  background-image: url(https://lorempixel.com/900/900/city/1/); /* default background */
}

.inner {
  display:none; /* start of hidden */
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="default"><!-- default div with default background image -->
  <div class="inner" data-background="https://lorempixel.com/900/900/city/2/"><!-- inner div with background-image set as data attribute -->

  </div>
</div>

If you want to create the inner div on the fly, you can do something like this:

$('.background').each(function() {
  var div = $(this),
    background = div.data('background'), // get background
    html = div.html();  // get any contents

  $('<img/>').attr('src', background).load(function() {  // create an image element with inner background and load it
    $(this).remove();  // remove it
    div.empty();       // empty current div
    
    // create an inner div:
    $('<div/>')
      .css({
        'background-image': 'url(' + background + ')',
        'display': 'none'
      })                  // add background and hide
      .addClass('inner')      
      .html(html)           
      .appendTo(div)      // append to default div
      .delay(175)
      .fadeIn(2000); // need a little delay to let the div render it's bg image before the fade starts
  });
});
.background,
.inner {
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center;
}

.background {
  background-image: url(https://lorempixel.com/900/900/city/1/); /* default background */
  
  /* just make sure inner div is same size as outer */
  width: 400px;
  height: 400px;
}

.inner {width:100%; height:100%;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="background" data-background="https://lorempixel.com/900/900/city/2/"><!-- default div with default background image,  new background image set as data attribute -->
</div>

Upvotes: 2

ElementCR
ElementCR

Reputation: 178

I found a reference that utilizes @keyframes along with some attributes like 'opacity' within an animation frame.

You can try referencing some of the code in the link here -

https://codepen.io/davidhc/pen/nLpJk

@keyframes fade
{
0%   {opacity:1}
33.333% { opacity: 0}
66.666% { opacity: 0}
100% { opacity: 1}
}

Upvotes: -1

Related Questions