Fade-Replace Text with JavaScript and CSS
From Zanecorpwiki
TODO: this is missing a 'demo' page; which will be provided shortly. TODO: untested code.
Contents |
Goal
To swap two block content by progressively fading one in whilst fading another out.
Idea
Invisibly position one element under the other. During the fade process, the top element is made progressively more transparent while the bottom element becomes more opaque until finally the top element has become fully transparent/invisible and the top level reaches the target opacity. If necessary, the "z index" of the elements is swapped so that the top element becomes the bottom and the bottom the top. The process is trivially reversible.
Preferred Implementations
The basic idea is to rely to use absolute positioning to get the two elements to occupy the same space. It's perfectly fine of both elements are absolutely position, but only one element need be. The context of surrounding elements will usually dictate which approach is best.
If both items may be absolutely positioned, then simply give them each the same position, like:
<!-- HTML --> <div id="quoteOne">Quote One</div> <div id="quoteTwo">Quote Two</div>
/* CSS */
#quoteOne, #quoteTwo {
position: absolute;
height: 1em;
border: 1px solid block;
-moz-border-radius:6px;
-webkit-border-radius:6px;
top: 0;
right: 0;
}
#quoteOne {
z-index: 9998;
}
#quoteTwo {
opacity: 0;
-moz-opacity:0;
-khtml-opacity: 0;
filter:alpha(opacity=0);
z-index: 9997;
}
The alternative is to use only "pin" one item, while keeping the other in the normal flow. This is useful if the swapped content needs to be in flow with other items. Note, however, this can be difficult to get right if the items are not pinned to a corner of the containing block and in general has many more considerations (scaling effects, non-homogeneous swapped content, etc.)
<!-- HTML --> <div id="main"> <div id="quoteThree">Quote Three</div> <div id="quoteFour">Quote Four</div> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </div>
/* CSS */
#quoteOne, #quoteTwo {
height: 1em;
border: 1px solid block;
-moz-border-radius:6px;
-webkit-border-radius:6px;
}
#quoteOne {
float: left;
z-index: 9998;
}
#quoteTwo {
position: absolute;
top: 0;
right: 0;
opacity: 0;
-moz-opacity:0;
-khtml-opacity: 0;
filter:alpha(opacity=0);
z-index: 9997;
}
In either case, the heart of the JavaScript is the same:
/**
* Swaps the opacity of two elements; often used to fade-swap one
* opaque item for one fully transparent/invisible item, though the
* algorithm doesn't assume 0 and 100% extremes. The first element
* must the more opaque, which we be faded, and the second the more
* transparent, which will be made more visible.
*
* The config parameter is optional. An unspecified configuration
* parameters will result in the use of default values. Possible config
* values are:
*
* - steps : how many steps to take in the fade process
* - interval : the time (in milliseconds) interval to wait between
* steps
* - swapZ : whether once the fade is complete, the z position of the
* elements should be swapped
* - swapDisplay : whether, the complete, the display of the bottom and
* top images should be swapped
* - killDisplay : whether, once the fade is complete, the bottom
* element should be removed from the display entirely, via
* 'display : none'
*/
function fadeSwap(elementOne, elementTwo, config) {
if (config == null) confic = new Object();
// always make the default values of optional parameters explicity
if (config.swapZ == null) config.swapZ = false;
if (config.swapDisplay == null) config.swapDisplay = false;
if (config.killDisplay == null) config.killDisplay = false;
if (config.steps == null) config.steps = 20;
if (config.interval == null) config.interval = 50;
// set up the baseline parameters to use in the algorithm
var targetOpacity = determineOpacity(elementOne);
var targetTransparency = determineOpacity(elementTwo);
var elementOneOpacity = targetOpacity;
var elementTwoOpacity = targetTransparency;
var stepFactor = (targetOpacity - targetTransparency) / config.steps;
var stepCcount = 0;
// helper function that actually does the fading / un-fading
function doFade() {
if (count == steps) {
clearInterval(interval);
// set target opacities directly to fix any rounding errors
setOpacity(elementOne, targetTransparency);
setOpacity(elementTwo, targetOpacity);
}
else {
elementOneOpacity -= stepFactor;
elementTwoOpacity += stepFactor;
setOpacity(elementOne, elementOneOpacity);
setOpacity(elementTwo, elementTwoOpacity);
stepCount += 1;
}
}
var interval = setInterval(doFade, config.interval);
}
The above function has a number of refinements which may not be necessary for your particular case, but are useful in a general purpose function. The functions determineOpacity() and setOpacity() simply read and set the CSS/element style as appropriate and are omitted for brevity. See the example for implementation.
Notes
The various effects and determining how to set the killZ, swapDisplay, and killDisplay require careful consideration when setting. The question is usually whether the elements are the same size and if one or the other is flowed with surrounding content. The swap and kill display options may be used together, but in practice are intended for different situations. Specifically, if both true, and the initial bottom element has something other than display : none, then if the fade process is potentially cycled, following cycles may display different layout behavior.


