Here is the version using jQuery. This is a bit more complicated than the other answers, but most of the complexity is related to how I made the animation. When the backlight changes, it stretches to a new place and then shrinks to fit. This is not what your layout does, but IMHO is a smoother effect.
It's hard to explain, but it's a JSFiddle, which shows what I mean.
http://jsfiddle.net/mcgraphix/4qe8uz06/9/
The HTML is pretty much like yours, except for the added highlight:
<div> <label> <input type="radio" name="radioBtn" ><span class="label">First Option</span> </label> <label> <input type="radio" name="radioBtn" checked><span class="label">Second Option</span> </label> <label> <input type="radio" name="radioBtn"><span class="label">Third Option with a long label</span> </label> <span class="highlight"></span> </div>
JS:
$(document).ready(function() { //handle to the highlight span var hl = $('.highlight'); var initialLabel = $('input[name="radioBtn"]:checked').parent(); //highlight the correct one initially in case it isn't the first one hl.css('width', initialLabel.css('width')); hl.css('left', ( initialLabel.offset().left - $("label").first().offset().left) + 'px'); //add listeners $("label").mouseup(function(event) { //figure out what we clicked on var selectedItem = $(this); //figure out where the left edge of it is var newLeft = (selectedItem.offset().left - $("label").first().offset().left); //how much do we need to change the left coordinate var changeAmount = Math.abs(parseInt(hl.css('left')) - newLeft); //figure out which direction we're going var direction = (parseInt(hl.css('left')) > newLeft) ? 'left' : 'right'; //remove all the classes to start hl.removeClass('grow-left').removeClass('grow-right').removeClass('shrink'); //set up the new CSS var newCss; if (direction === 'right') { //we're growing to the right newCss = { width: selectedItem.width() + selectedItem.offset().left - hl.offset().left + 'px' }; hl.addClass('grow-right'); } else { //we're growing to the left newCss = { width: hl.width() + changeAmount + 'px', left: newLeft + 'px' }; hl.addClass('grow-left'); } //set the initial change hl.css(newCss); //wait for it to be done, then finish the change hl.on('transitionend webkitTransitionEnd oTransitionEnd', function () { if (direction === 'right') { //we need to shrink to the right newCss = {width: selectedItem.css('width'), left: newLeft + "px"}; } else { //we need to shrink to the left newCss = {width: selectedItem.css('width')} } //apply the right transition class hl.removeClass('grow-left').removeClass('grow-right').addClass('shrink'); //apply the styles hl.css(newCss); //you could add a transitionend event listener to clean up the classes here }); }); });
The most important CSS styles are those that apply the transition with the correct attenuation and delay values:
span.highlight.grow-left { transition: left 0.2s ease-in-out, width 0.2s ease-in-out; } span.highlight.grow-right { transition: width 0.2s ease-in-out, left 0.2s ease-in-out 0.2s; } span.highlight.shrink { transition: width 0.2s ease-in-out, left 0.2s ease-in-out; }
The bottom line is that there is a "highlight" behind the labels. When you click one, it calculates the position of what you clicked, and adding classes for the right animation at the right time, you get the right animated "morphing"
mcgraphix
source share