How can I smoothly transition to CSS background images?

The main solution:

"Just load the download screen before the page loads."

But my goal is to create pages that present the basics very quickly, without a loading screen, and then move on to images and fancy features when they are ready. Therefore, I will wait until it boots up and then disappears. Or I will download a very low resolution version and then fade out in high resolution when it is ready.

One aspect of this practice that I have not yet understood is how to do this using background images.

How can I achieve a smooth fading effect in background images?

I am ready to use:

  • Javascript
  • JQuery
  • Any modern jQuery library
  • CSS tricks / hacks

But I want to avoid:

  • .
+4
3

@dandavis, CSS: background-image.

, CSS:

  • : , . ( , !);

  • transition: background-image 1s,

  • Javascript, reset , . CSS .

  • background-size ( ).

  • , , .


var image = new Image();
image.onload = function () {
        $(".element").css("background-image", "url('" + image.src + "')");
}

image.src = "https://c1.staticflickr.com/3/2439/3728897793_ff1c78c5d9.jpg"; //image to be transitioned to
html{
    width:100%;
    height:100%;
}
body{
    width:100%;
    height:100%;
    padding:0px;
    margin:0px;
}
.element{
    width:100%;
    height:100%;
    background-image:url('http://i.imgur.com/HRV3DsM.jpg');
    -webkit-transition: background-image 5s;
}
<div class="element">
</div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
Hide result
+5

, ! (, , :)

//library (minified)
this.BgImgFader=function(){var styleRules;function getArray(str){if(str.indexOf(',')==0){str.substring(1);}if(str.lastIndexOf(',')==str.length-1){str.substring(0,str.length-1);}if(str.indexOf(',')==-1){var selectors=[str];}else{var selectors=str.split(',');}for(var i=0;i<selectors.length;i++){selectors[i]=selectors[i].trim();}return selectors;}function getStyleSheet(style){if(typeof style==='number'){return document.styleSheets[style];}else{for(var i=0;i<document.styleSheets.length;i++){var file=document.styleSheets[i].href;file=file.substring(file.lastIndexOf('/')+1);if(file.toLowerCase()==style.toLowerCase()){return document.styleSheets[i];}}}}function addStyleRule(sheet,selector,declarations){if(sheet.addRule){sheet.addRule(selector,declarations);}else{sheet.insertRule(selector+'{'+declarations+'}');}}this.prepare=function(style,selectors){var selectors=getArray(selectors);var styleSheet=getStyleSheet(style);for(var i=0;i<selectors.length;i++){addStyleRule(styleSheet,selectors[i],'position:relative;');addStyleRule(styleSheet,selectors[i]+'::after','position:absolute;top:0;right:0;bottom:0;left:0;opacity:0.0;content:"";');}};this.fade=function(style,selectors,global,opacity,endOpacity,delta){var selectors=getArray(selectors);var styleSheet=getStyleSheet(style);styleRules=styleSheet.rules?styleSheet.rules:styleSheet.cssRules;fadeOpacity(selectors,global,opacity,endOpacity,delta,[]);};function fadeOpacity(selectors,global,opacity,endOpacity,delta,rules){opacity+=delta;if(rules.length==0){for(var i=0;i<selectors.length;i++){for(var j=0;j<styleRules.length;j++){if(global&&styleRules[j].selectorText.toLowerCase().indexOf(selectors[i].toLowerCase()+'::after')!=-1){rules.push(styleRules[j]);}else if(styleRules[j].selectorText.toLowerCase()==selectors[i].toLowerCase()+'::after'){rules.push(styleRules[j]);break;}}}}for(var i=0;i<rules.length;i++){rules[i].style.opacity=opacity;}if(opacity<endOpacity){setTimeout(function(){fadeOpacity(selectors,global,opacity,endOpacity,delta,rules);},0);}else{for(var i=0;i<rules.length;i++){rules[i].style.opacity=endOpacity;}rules.length=0;}}};

//instantiate BgImgFader in global domain
var BgImgFader = new BgImgFader();

window.onload = function(){
  //prepare specified elements
  BgImgFader.prepare(0, '.exampleClass'); //style, selectors

  //fade specified elements
  BgImgFader.fade(0, '.exampleClass', true, 0, 0.5, 0.002); //style, selectors, global, startOpacity, endOpacity, delta
};
#exampleId {
  width: 300px;
  height: 200px;
  margin: 10px 0px 0px 10px;
  background-color: #AAAAAA;
}
#exampleId .exampleClass {
  width: 200px;
  height: 130px;
  padding: 5px;
}
#exampleId .exampleClass::after {background:url(https://placeimg.com/640/480/any) center/cover no-repeat;}
<div id="exampleId">
  Some other text to illustrate how this can be implemented.
  <div class="exampleClass">
    I assume you want transparent background images because you have text in the element that you do want to show from the start?
  </div>
</div>
Hide result
codepen: https://codepen.io/anon/pen/QMLPbr

. JavaScript, jQuery.


, , BgImgFader JS:

//instantiate BgImgFader in global domain
var BgImgFader = new BgImgFader();

window.onload = function(){
  //prepare specified elements
  BgImgFader.prepare(0, '.exampleClass'); //stylesheet, selectors

  //fade specified elements
  BgImgFader.fade(0, '.exampleClass', true, 0, 0.5, 0.002); //stylesheet, selectors, global, startOpacity, endOpacity, delta
};

CSS:

#example {...}
#example::after {background:url(path/to/image.png) center/cover no-repeat;}

, #example::after { . ( HTML, CSS.)


. . script HTML- , ( ):

<script type="text/javascript" src="path/to/bgimgfader.js"></script>

/**
 * BgImgFader - Library:
 * This library makes it possible to fade the background-image of an element.
 * The image can be faded in or out.
 * 
 * Compatibility:
 * - IE9 and higher should be fine, lower could give trouble.
 * - Older versions of FF/Chrome will probably give some problems too, but I think we can safely assume 
 *   that those who chose either one of these browsers, did so because they choose NOT to live in the past..
 * - Opera and others... I have absolutely no idea.
 * 
 * #################################################################################
 * INSTRUCTIONS---------------------------------------------------------------------
 * 1. In CSS:
 *    a. For every element with a background-image, create an '::after' rule, and put the image in there:
 *       (You don't have to create these '::after'-elements in the HTML)
 * 
 *          #element {...}
 *          #element::after {background:url(path/to/image.png) center/cover no-repeat;}
 * 
 *       The following declarations will be added by the BgImgFader, keep that in mind:
 *          #element {position:relative;}
 *          #element::after {position:absolute; top:0;right:0;bottom:0;left:0; opacity:0.0; content:"";}
 * 
 *          (The important one is 'position:relative;', the ones on the '::after'-element have no consequences) 
 * 
 * ---------------------------------------------------------------------------------
 * 2. In JavaScript:
 *    a. Instantiate the BgImgFader in the global domain:     var BgImgFader = new BgImgFader();
 * 
 * 
 *    b. Prepare the elements with a background-image:     BgImgFader.prepare(0, 'elements'); //style, selectors
 * 
 *       - style: Reference to the style sheet with the rules for the specified elements.
 *                This can be either an INTEGER for internal style sheets (0), 
 *                or a STRING of a filename for external style sheets ('style.css').
 *       - selectors: STRING reference to the selectors in the style rules.
 *                    This works the same as in the CSS, below a few examples.
 *                         Individual tags:     ('div')	        ('#id')          ('.class')
 *                           Multiple tags:     ('div.class')   ('#id .class')   ('.class.subclass')
 *                      Multiple selectors:     ('div, #id, div.class, #id .class, .class.subclass')
 * 
 * 
 *    c. Initiate the fade:     BgImgFader.fade('style.css', 'elements', true, 0, 0.5, 0.005); //style, selectors, global, startOpacity, endOpacity, delta
 * 
 *       - style: See 2b for the details.
 *       - selectors: See 2b for the details.
 *       - global: BOOLEAN that deternimes whether only complete matches for the selectors are allowed, 
 *                 or partial matches as well, increasing the range of the BgImgFader.
 *                 TRUE allowes partial matches: feed the BgImgFader '.class' and it will also try to fade 'div .class'.
 *                 FALSE allowes only complete matches.
 *       - startOpacity: FLOAT that indicates the start opacity (0.0  -  1.0).
 *       - endOpacity: FLOAT that indicates the end opacity (0.0  -  1.0).
 *       - delta: FLOAT that indicates the delta of every fade-iteration (1.0  -  0.00000000...1).
 *                The effective range is approximately (0.1  -  0.0001).
 *                A smaller delta means a slower fade.
 *                A positive delta in combination with start<end fades the image in.
 *                A negative delta in combination with start>end fades the image out.
 * 
 * #################################################################################
 */

this.BgImgFader = function() {
  var styleRules;
  
//GET/SET-FUNCTIONS=================================================================
//GET SELECTORS---------------------------------------------------------------------
  function getArray(str) {
    /* This function is invoked by this.prepare() and this.fade().
     * This function converts the specified string of selectors to an array, and returns that.
     */
    //strip trailing comma's
    if (str.indexOf(',')==0) {str.substring(1);} //strip first comma
    if (str.lastIndexOf(',')==str.length-1) {str.substring(0,str.length-1);} //strip last comma
    //store selectors in array
    if (str.indexOf(',')==-1) {var selectors = [str];}
    else {var selectors = str.split(',');}
    //trim trailing spaces
    for (var i=0; i<selectors.length; i++) {
      selectors[i] = selectors[i].trim();
    }
    return selectors;
  }
//GET STYLE SHEET-------------------------------------------------------------------
  function getStyleSheet(style) {
    /* This function is invoked by this.prepare() and this.fade().
     * This function returns a reference to the specified style sheet, 
     * based on either a number or a filename of the sheet.
     * A number is for internal sheets, where the number stands 
     * for its location in the HTML (e.g. the first '<style></style>').
     * A filename is for external sheets (e.g. 'style.css').
     * See the instructions in the header of this file for details.
     */
    if (typeof style === 'number') {
      return document.styleSheets[style];
    } else {
      //find style sheet
      for (var i=0; i<document.styleSheets.length; i++) {
        var file = document.styleSheets[i].href;
        file = file.substring(file.lastIndexOf('/')+1);
        if (file.toLowerCase() == style.toLowerCase()) {
          return document.styleSheets[i];
        }
      }
    }
  }
//SET STYLE RULE--------------------------------------------------------------------
  function addStyleRule(sheet, selector, declarations) {
    /* This function is invoked by this.prepare().
     * This function dynamically adds the specified rule to the specified style sheet.
     */
    if (sheet.addRule) {sheet.addRule(selector,declarations);} //IE...
    else {sheet.insertRule(selector+'{'+declarations+'}');} //NON-IE...
  }
  
//PREPARE===========================================================================
  this.prepare = function(style, selectors) {
    /* This function is invoked by an external function, outside of the library.
     * This function is an interface for external scripts to access this library.
     * The function prepares the elements specified by the selectors, by adding certain style rules 
     * to them that are necessary for this library to successfully manipulate the background-image.
     */
    var selectors = getArray(selectors);
    var styleSheet = getStyleSheet(style);
    for (var i=0; i<selectors.length; i++) {
      addStyleRule(styleSheet,selectors[i],'position:relative;');
      addStyleRule(styleSheet,selectors[i]+'::after','position:absolute; top:0;right:0;bottom:0;left:0; opacity:0.0; content:"";');
    }
  };
  
//FADE BACKGROUND IMAGE=============================================================
//INIT------------------------------------------------------------------------------
  this.fade = function(style, selectors, global, opacity, endOpacity, delta) {
    /* This function is invoked by an external function, outside of the library.
     * This function is an interface for external scripts to access this library.
     * The function initiates the fading process. It first stores the appropriate 
     * set of style rules into the style rules variable, and then invokes 
     * fadeOpacity() to start the fading.
     */
    var selectors = getArray(selectors);
    var styleSheet = getStyleSheet(style);
    styleRules = styleSheet.rules ? styleSheet.rules : styleSheet.cssRules; //IE uses 'rules', NON-IE use 'cssRules'
    fadeOpacity(selectors,global,opacity,endOpacity,delta,[]);
  };
  
//FADE------------------------------------------------------------------------------
  function fadeOpacity(selectors, global, opacity, endOpacity, delta, rules) {
    /* This function is invoked by fade().
     * This function fades the background-image of the specified elements, by 
     * adding the delta to the current opacity, and then setting the opacity 
     * of all specified elements to that new value.
     */
    opacity += delta;
    if (rules.length == 0) {
      //find the css-rules that match the specified selector(s)
      for (var i=0; i<selectors.length; i++) {
        for (var j=0; j<styleRules.length; j++) {
          if (global && styleRules[j].selectorText.toLowerCase().indexOf(selectors[i].toLowerCase()+'::after')!=-1) {
            rules.push(styleRules[j]);
          } else if (styleRules[j].selectorText.toLowerCase() == selectors[i].toLowerCase()+'::after') {
            rules.push(styleRules[j]); break;
          }
        }
      }
    }
    //set the opacity of the background-image for every matched rule
    for (var i=0; i<rules.length; i++) {
      rules[i].style.opacity = opacity;
    }
    //check if the end-opacity is reached
    if (opacity < endOpacity) {
      setTimeout(function(){fadeOpacity(selectors,global,opacity,endOpacity,delta,rules);},0); //invoke itself again
    } else {
      //manually set the opacity to the end-opacity (otherwise it'll be off by a fraction)
      for (var i=0; i<rules.length; i++) {
        rules[i].style.opacity = endOpacity;
      }
      rules.length = 0;
    }
  }
};
source code of library, not a working code snippet!
Hide result
( , )

: jsfiddle.net, , , ( ) CSS.

+5

, : <img> , <img> (: inline-block; visibility: hidden;) :

$("high-res").load(function() {
    $(this).css({visibility: "hidden", opacity: 0}).fadeIn("slow");
}

: ( , ) . .

CSS . . , , <div> <img> .

+2

Source: https://habr.com/ru/post/1544396/


All Articles