Friday, February 21, 2014

Theming Tooltip Box Shadows

The jQuery UI tooltip widget is themable, just like every other widget. Except, to a certain extent, it isn't. The tooltip uses the box-shadow CSS property to apply a decent-looking shadow around the element when it's displayed. It looks good with the smoothness theme, but with others, it's a little awkward.

For example, this is what the tooltip box shadow looks like with the humanity theme.

You can see that the color of the box shadow doesn't blend nicely with the border color of the tooltip. Conversely, it blends well if you're using the the default theme — smoothness. Why is that? The issue is that the border applied to the tooltip element gets it's color from the theme framework. Specifically, from the ui-widget-content class. The box-shadow property has nothing to do with the theme framework — it's part of the tooltip CSS, which isn't affected by theme changes.

To work around this issue and make the tooltip box shadows look a little nicer, we can sample the border color of the tooltip and use that to adjust the box-shadow value. Here's an example of how to do that.

We're applying this style hack in the open event handler we supply to the tooltip widget. Here's what that code looks like.

$( "#age" ).tooltip({
    
    open: function( e, ui ) {
        
        var $tt = $( this ).data( "ui-tooltip" )
                ._find( $( this ) ),
            color = $tt.css( "border-color" ),
            shadow = $tt.css( "box-shadow" ),
            regexp = /^rgb\(.*\)/;
        
        $tt.css({
            "box-shadow": shadow.replace( regexp, color )
        });
        
    }

});

All we're doing here is supplying an open callback function to the tooltip options. This is where the CSS is patched. We start be initializing a series of variables. The first is the tooltip element itself, and this goes in the $tt variable. Since the open event is triggered on the element the tooltip is bound to, in this case, an input, we have to perform some trickery to get the actual tooltip element. First we grab the tooltip widget instance using data(), then, we use the _find() method of the tooltip widget. There are other ways to do this, but believe it or not, this is the shortest. Now that we have the tooltip element, we can sample the border-color and box-shadow CSS values — these go in their respective variables — color and shadow. The regexp variable has the regular expression used to replace the RGB color component of the box-shadow.

The last step is to actually patch the CSS. We replace the sampled box shadow color with the sampled border color using a regular expression and css().