Text drop shadows can be used to improve headline legibility or simply for decorative purpose. In my latest project, I’ve had to use drop shadows just for the reasons above and ended up writing a Mootools class.
There are a few techniques to generate text drop shadows, all of which are based on creating a duplicate text layer to simulate a drop shadow, but not all of them are scalable; meaning that when user resizes web page text, using browser controls (ctr +/-,ctr + mouse scroll, etc), the drop shadow may not always follow the element it’s supposed to shadow. In the particular technique I’m using, however, a container div is used to hold both text elements, insuring a uniform look, regardless of the size. Although, it may not scale as nicely as one would expect, in certain situations…

You can take a look at the demo here. If that’s something you may be interested in, here is how to use it (also check out the demo’s source code for more examples):

<script type="text/javascript" src="js/mootools.v1.11.js"></script>
<script type="text/javascript" src="js/mootools.tds.js"></script>

<script type="text/javascript">
//<![CDATA[

	var Site = {

		start: function(){
			//simple ds with no options
			new TextDropShadow($('element'));

			//all elements with particular class name
			new TextDropShadow($$('element.classname'));

			//set ds color to #222 and it's opacity to 50%
			//when using apacity, you must specify background color or IE will output junk
			new TextDropShadow($('element'), {color:'#222', opacity: 0.5, background: '#fff'});

			//specify color and direction
			new TextDropShadow($('element'), {color:'#222', top:2, left:2});

			//shadow direction can take negative values as well
			new TextDropShadow($('element'), {color:'#222', top:-1, left:-1});
		}

	};

	window.addEvent('domready', Site.start);
//]]>
</script>

The script is available for download here


23 Responses to “Mootools text drop-shadow”

  • […] pr0digy.com » Mootools text drop-shadow 3 hours agoAs always - an addition to the mootools repotoire because you know how designers love […]

  • Gravatar
    May 13th, 2008 at 1:26 pm
    magoo101 says:

    Just wanted to let you know that you have a couple code errors in your example above.


    //specify color and direction
    new TextDropShadow($('element'), {color:'#222', top:2 left:2);

    …should actually be…


    //specify color and direction
    new TextDropShadow($('element'), {color:'#222', top:2, left:2});

  • Yep thanks - corrected the typo.

  • hi,

    will you touch it again to make it also working with mootools 1.2? would be fantastic! :-)
    thank you for your great work.

  • Hi Florian, I’m thinking of rewriting (adjusting) the scripts for 1.2. Though I can’t really give you the time frame on that :(

  • Gravatar
    August 7th, 2008 at 12:36 pm
    batman42ca says:

    I just converted it to 1.2. All you have to do is the following:

    Inside applyDropShadow(), do the following

    add this:

    var size = el.getSize();

    replace this

    height: el.getSize().size.y + offsetY,
    width: el.getSize().size.x + offsetX

    with this

    height: el.size.y + offsetY,
    width: el.size.x + offsetX

    and replace this
    el.remove();

    with this
    el.destroy();

  • Thanks for that, Batman :) I’ll be converting most of the scripts to 1.2, soon :)

  • I am kind of frustrated, even before batman42ca’s post I was tinkering with things to try and get it working with 1.2 and kept getting this:


    TextDropShadow is not defined

    start()
    E()mootools-1.2-core... (line 56)
    extend(undefined)mootools-1.2-core... (line 57)
    fireEvent(function())mootools-1.2-core... (line 173)
    fireEvent("domready", undefined, undefined)mootools-1.2-core... (line 174)
    onAdd()mootools-1.2-core... (line 248)
    C()mootools-1.2-core... (line 168)
    [Break on this error] new TextDropShadow($$('.textshadow'), {color:'#fff', top:1, left:1})...

    even after the changes posted I still get the undefined error.

    I have the exact same instantiation as the demo, save my elements switched in under the object's, and it blows up every time.

    for some reason the instantiation of this class looks wierd...

    here is my page's script init:

    var Site = {

    start: function(){
    new TextDropShadow($$('.textshadow'), {color:'#fff', top:1, left:1});
    }
    };

    window.addEvent('domready', Site.start);

    Any help here would be greatly appreciated

  • Hmm, looks like you forgot to include the drop shadow script… Essentially, the error means, that TextDropShadow object does not exist.

  • Wow, that was stupid, I was missing one ellipsis dot for the JS file path!

    But when that was fixed I did get one error that needed correction from what batman42ca posted:

    height: el.size.y + offsetY,
    width: el.size.x + offsetX

    his fix for this section should not have the el before size.x and size.y, I got a firebug break on that and it cleared right up when the el was erased.

    Anywho, sorry for that last dumbassical post, great script Alex and thanks for the help with the 1.2 convert Batman - Blamo, Pow!

    old school batman stuff, in case you didn’t get that :)

  • Gravatar
    August 8th, 2008 at 11:56 am
    batman42ca says:

    Daniel,

    Thanks for spotting the typo. The corrected changes to convert from 1.1 to 1.2 are:

    Inside applyDropShadow(), do the following

    add this:


    var size = el.getSize();

    replace this


    height: el.getSize().size.y + offsetY,
    width: el.getSize().size.x + offsetX

    with this


    height: size.y + offsetY,
    width: size.x + offsetX

    and replace this


    el.remove();

    with this


    el.destroy();

  • I wonder if the same technique can be used to add glow effect. Some browsers will not display the CSS glow effect you know.

  • It’s doable. Personally, I don’t see much use for it.

  • Great stuff! Here’s an idea for improvement:

    I generally find a 2-pixel drop shadow looks best for the text sizes I use, but the shadow is a bit too hard. So, why not apply *two* drop shadows - a harder (opacity 0.5) 1-pixel shadow upon a softer (opacity 0.25) 2-pixel shadow.

    Would this be feasible? Newbie question: how can the opacity parameter be accessed within the script? Thanks!

  • Nick, yes it’s quite feasible - I’ll look into that.

    Opacity and the rest of the options can be accessed like this:

    var tds = new TextDropShadow($('desiredelement'), {'opacity': .5});
    
    console.info(tds.options);
    console.info(tds.options.opacity);
    

    By the way, console is a Firebug feature.

  • working on adding this to a header where the text is centered via css text-align:center
    In which case the drop shadow element aligns it to the left.
    i’ve tried setting the attributes to center it but it removes the drop shadow as well have tried numerous CSS and div implementations with no success to center the text with the drop shadow.
    Any clues?

  • Hope you don’t mind but posting the converted drop shadow code for mootools 1.2.1

    var TextDropShadow = new Class({
    		options: {
    			color: '#333',
    			left: 1,
    			top: 1,
    			position: 'absolute'
    		},
    
    		initialize: function(obj, options){
    				this.setOptions(options)
    				this.createDropShadows(obj);
    		},
    
    		createDropShadows: function(obj){
    			if('element' == $type(obj)) {
    				this.applyDropShadow(obj)
    			} else if('array' == $type(obj)) {
    				obj.each( function(el) {
    					this.applyDropShadow(el);
    				}, this);
    			} else {
    				return false;
    			}
    		},
    
    		applyDropShadow: function(el){
    			var size = el.getSize();
    			var original = el.clone();
    			var shadow = el.clone();
    
    			var offsetY = this.options.top ? this.options.top.toInt() : this.options.bottom.toInt();
    			if(offsetY < 0) offsetY = offsetY * (-1);
    
    			var offsetX = this.options.left ? this.options.left.toInt() : this.options.right.toInt();
    			if(offsetX < 0) offsetX = offsetX * (-1);
    
    			var container = new Element('div', {
    					'styles': {
    							position: 'relative',
    							left: 0,
    							top: 0,
    							height: size.y + offsetY,
    							width: size.x + offsetX
    					}
    			});
    
    			original.setStyles({position: 'absolute', left: 0, top: 0});
    			shadow.setStyles(this.options);
    
    			container.adopt(shadow).adopt(original);
    			container.injectAfter(el);
    			el.destroy();
    		}
    });
    TextDropShadow.implement(new Options, new Events);
    
    /*
    var addDS = {
    	start: function(){
    		new TextDropShadow($$('.ds'), {color:'#222', top: 1, left: 1}); //{color:'#222', opacity: 0.5, background: '#fff'});
    	}
    };
    */
    
  • […] When you need a full cross-browser compatibility and still want to use CSS3 properties, JavaScript is always here to help. This tutorial will show you how to recreate the text-shadow CSS property using the MooTools JavaScript framework. » Read tutorial […]

  • […] When you need full cross-browser compatibility and still want to use CSS3 properties, JavaScript is always here to help. This tutorial will show you how to recreate the text-shadow CSS property using the MooTools JavaScript framework. » Read tutorial […]

  • I was trying to use dropshadows on a menumatic horizontal menu (http://greengeckodesign.com/?q=menumatic) and having the primary menu items with dropshadows (so none of the submenu items).

    The problem was the applyDropShadow code was “destroy”ing the elements that the menumatic code relied on. So I changed the dropshadow code so no elements are destroyed, but instead the original elements are simply ammended/appeneded. This might come in handy for people in similar situations.

    I also added a few lines that wraps a around the first word of a menu item so I can bold it in css (it’s a pretty cool affect).

    Anyway, here is the code for applyDropShadow in case it helps someone:

    applyDropShadow: function(el){
    
    			var size = el.getSize();
    
    			// Wrap  around the first word if there is one
    			var marray = el.get('html').split(' ');
    			if (marray.length > 1) marray[0] = '' + marray[0] + '';
    			el.set('html', marray.join(' '));
    
    			var clone = el.clone();
    
    			var offsetY = this.options.top ? this.options.top.toInt() : this.options.bottom.toInt();
    			if(offsetY < 0) offsetY = offsetY * (-1);
    
    			var offsetX = this.options.left ? this.options.left.toInt() : this.options.right.toInt();
    			if(offsetX < 0) offsetX = offsetX * (-1);
    
    			var container = new Element('div', {
    					'styles': {
    							position: 'relative',
    							left: 0,
    							top: 0,
    							height: size.y + offsetY,
    							width: size.x + offsetX
    					}
    			});
    
    			el.setStyles({position: 'absolute', left: 0, top: 0});
    			container.wraps(el);
    			clone.setStyles(this.options);
    			clone.inject(el, 'before');
    
    		}
    
  • […] When you need full cross-browser compatibility and still want to use CSS3 properties, JavaScript is always here to help. This tutorial will show you how to recreate the text-shadow CSS property using the MooTools JavaScript framework. » Read tutorial […]

  • […] When you need full cross-browser compatibility and still want to use CSS3 properties, JavaScript is always here to help. This tutorial will show you how to recreate the text-shadow CSS property using the MooTools JavaScript framework. » Read tutorial […]

  • […] When you need full cross-browser compatibility and still want to use CSS3 properties, JavaScript is always here to help. This tutorial will show you how to recreate the text-shadow CSS property using the MooTools JavaScript framework. » Read tutorial […]

Leave a Reply


XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>