We've all had that problem - designing our web sites to have a certain look and feel. Unfortunately, not every visitor will view the site the way you intended. This is due to the fact that different operating systems render native browser controls differently. The buttons in OS X have the aqua look while the buttons in Windows 2000 look gray and outdated.
Using the AnyButton
Until now, to enforce a consistent look, a popular option was using images as buttons. This is a great alternative except that when it comes to adding new buttons or modifying existing ones, you better have Photoshop [and the time] handy to get it done.
I’ve created a control called the
AnyButton which derives from
System.Web.UI.WebControls.ImageButton. This button uses image templates as skins. It will take a JPG, GIF or PNG as a template. It is really easy to use, and best of all, looks just like a real button. This control is compatible with IE6, Firefox, Netscape and Safari browsers.
The control takes in a single image as a template. The button supports three different states –
press. Moreover, each button supports three different skins – 1 for each state. This allows you to create as many types of buttons as you’d like by subclassing the base
Button class. For instance, you could have an
AmazonComButton, etc. The best part is, you don’t have to use Photoshop to create your buttons – if you see a button on a site you like, screen shot it, crop out the middle part and you’re pretty much ready to go.
Here’s an example using the XP button as a skin:
- This is the default state template that I will assign to the button:
- This is the hover state template that I will assign to the button:
- And this is the press state template that I will assign to the button:
As you can see, the red lines dictate how to slice the button. These lines must be the exact RGB color (255, 0, 0) or #FF0000.
Each button has a
ButtonConfig class as a property. The
ButtonConfig class contains all the information about the button templates. Here's an example using all button states, generating a button that resembles the XP Silver button:
public class XPButton : AnyButton
this.EnableHover = true;
this.EnablePress = true;
public XPButton(Page page)
this.Page = page;
this.EnableHover = true;
this.EnablePress = true;
protected override void OnInit(EventArgs e)
protected override void OnLoad(EventArgs e)
protected void Initialize()
Font f = new Font("Tahoma", 8, FontStyle.Regular);
ButtonConfig buttonConfig = new ButtonConfig();
buttonConfig.TemplatePath = "~/xp_button/default.png";
buttonConfig.OutputPath = "~/output/xp";
buttonConfig.Font = f;
buttonConfig.VerticalTextOffset = 1;
buttonConfig.FontColor = Color.Black;
this.Config = buttonConfig;
ButtonConfig hoverConfig = new ButtonConfig();
hoverConfig.TemplatePath = "~/xp_button/hover.png";
hoverConfig.OutputPath = buttonConfig.OutputPath;
hoverConfig.Font = buttonConfig.Font;
hoverConfig.VerticalTextOffset = buttonConfig.VerticalTextOffset;
hoverConfig.FontColor = buttonConfig.FontColor;
this.HoverConfig = hoverConfig;
ButtonConfig pressConfig = new ButtonConfig();
pressConfig.TemplatePath = "~/xp_button/press.png";
pressConfig.OutputPath = buttonConfig.OutputPath;
pressConfig.VerticalTextOffset = buttonConfig.VerticalTextOffset + 1;
pressConfig.HorizontalTextOffset = buttonConfig.VerticalTextOffset + 1;
pressConfig.Font = hoverConfig.Font;
pressConfig.FontColor = buttonConfig.FontColor;
this.PressConfig = pressConfig;
This example is pretty straightforward. One thing to note is the
HorizontalTextOffset properties being utilized in the
pressConfig. To get a true pressed effect, the text should move to the bottom right 1 pixel by 1 pixel.
This example demonstrates how to create an XP Themed button. To get you started right away, I've packaged the
XPButton along with the AnyButton assembly. I did this so you could use the
AnyButton without a template (XP), right off the bat. The three state templates for the
XPButton come embedded as part of the DLL. When the
XPButton is first called, it will need to extract out the templates to a specified path. This path is settable via the
TemplateExtractPath property. This property is unique only to the
XPButton and only used to extract its templates.
When a button deriving from
AnyButton is called, it must save these generated images to a location on disk for later use. Each state on each type of button can technically have a different output path. Most likely, the output path will be the same for all states of the button. To set the output path, use the
OutputPath property. This property will accept application-scope paths (~/). It is imperative that the ASPNET user account have read/write access to this path.
So far so good, right? Using the control is the easiest part. Have a look:
<%@ Register TagPrefix="btn" Namespace="MyNamespace" Assembly="MyAssembly" %>
<btn:XPButton Runat="server" Text="Click Me"/>
This is the result of the previous call:
As you can see, three images were created; 1 for each state. Any subsequent requests for an
XPButton with text "Click Me" will now be redirected to the already-generated button image. To clear the cache of images, simply delete the output directory.
If you are using PNG files and you want to enforce transparency, set the
AlphaPng setting to
true. This is necessary because IE does not support alpha PNG (right on MS). When
true, a special CSS filter will be added only to IE users (Firefox, Safari, etc. users will not be affected).
Use this property when you want to enforce a certain width regardless of the actual width of the text.
Handy little property that can be set in the markup adding client side function call when the button is pressed.
true by default, applies anti-aliasing and
By default, an
ImageButton (from which this control derives) is a submit button. To disable posting back, set
This isn't a property, but rather a querystring variable that, when present, will force the redrawing of the buttons, ignoring cache. [Example usage: http://www.mysite.com/default.aspx?ForceRedraw=true.]
That's pretty much all there is to it.