Welcome back to my ongoing series on optimizing the Telerik RadControls for ASP.NET AJAX. For those that are counting, this is the fifth installment in the series, so if you've missed the first four parts I suggest you go back and read them now. This article builds on some of the concepts we've covered previously, so a sound understanding of the earlier concepts is a plus. And before you get confused, you won't find the other installments on blogs.telerik.com. Up to now, this series has been running on my popular Telerik Watch blog, but going forward all installments will be published here. Capice? Good. Let's get down to business.
In this installment we are going to take a look at custom skins, specifically how to build them and how to optimize them for performance. With the latest release of the RadControls for ASP.NET AJAX, we can not only optimize the built-in skins for performance but also any custom skins we build. And since many "real world" applications require custom skinning, understanding how to optimize those skins is a handy trick. Let's take a closer look.
Before you can talk about optimizing a custom skin, first you have to build one. For this article, we're going to build and optimize a custom skin for RadTabStrip, but the approach used can be generally applied to any of the RadControls. Creating a custom skin basically consists of three steps:
1. Copy an existing skin
2. Modify the skin with your desired CSS customizations
3. Set properties on RadControls to use your custom skin
First, you copy an existing skin to establish a baseline that you can easily customize. You could, of course, build a skin completely from scratch, but that approach is significantly more difficult. Copying one of Telerik's eleven included skins (every skin exists for every control) is by far the best way to begin your customizations. To build my custom skin, I copied the Default skin for RadTabStrip.
Next, with your copied assets in a new App_Themes folder, it's time to start customizing. For simple customizations, you may only have to change some CSS. If you're after a very custom skin, though, you'll probably need to break out the Photoshop (or similar...though I'd always recommend Adobe tools for design) and build some custom images to use in your skin. These images are usually used to compose the background of your skin and they usually include variations for each state of the control (unselected, selected, hover, selected hover, etc.). My custom skin includes two image files- one for the tab backgrounds and one for the optional Tabstrip scroll buttons- but these images encapsulate all of the control's states. How? CSS Sprites.
Maximizing Skin Optimization: CSS Sprites
We need to pause for a second and talk about CSS Sprites. Using sprites to optimize image files is not an invention of the Internet era. Back in the day, video game designers would use sprites to save all of the graphical icons needed in a game as a way to conserve space (this was before game designers "needed" 50 GB to build a game) and improve performance. The concept: it is easier to load a single image file in to memory and reposition it to display the relevant data instead of loading and unloading many individual image files.
Okay, now that you understand what CSS sprites are and why they are important for building highly optimized skins, let's take a look at the sprite I built for my custom skin. You can see in the image below that my single image file contains all of the states I'll need in my Tabstrip skin. The size of this PNG file: less than 8 KB.
It looks strange at first, but when the CSS is applied, this image produces a RadTabStrip that looks something like this:
Don't worry if you still feel overwhelmed or if CSS sprites still seem confusing. I am providing the original Photoshop file used to build this custom skin at the end of this article, which should help you get an even better grasp on this process. But for now we need to move on.
Assuming you've built your skin, debugged your CSS, and everything is looking good, the last step is to apply your custom skin to your RadControl. This requires that you set two properties: EnableEmbeddedSkins and Skin. Set the first property, EnableEmbeddedSkins, to False. This tells the RadControl to look for external skin elements instead of using the Telerik-built embedded skins. By default, the RadControls will look in App_Themes > SkinName > ControlName to find the external skin, where "SkinName" is the value you set the Skin property to and ControlName is the name of the control (like TabStrip, Editor, Grid, etc.). With that, your control is ready consume your custom skin. To easily add references to your skin elements on the page, set the Page's Theme to the name of the Theme folder that contains your custom skin.
So you've built your custom skin, applied it to your RadControls, and everything is working great. But then you read my article on the RadManagers and were stoked about the page load performance gains those controls provide when using the built-in RadControl themes. "That's cool," you thought, "but I've got to use custom skinning. Is there any help for me?" Absolutely.
By taking the following steps, you can enable any custom skin to work with the RadStyleSheetManager, which means your custom skins can be automatically optimized with the rest of the RadControls on your page. Here's what you need to do:
1. Create a new Class Library project in your solution
2. Copy your skin CSS file and supporting image files to your new solution
3. Add WebResource references to your skin elements in the default class file
4. Mark all skin elements in your solution as "EmbeddedResources"
What you're doing is building a custom assembly to hold your custom skins. The RadStyleSheetManager can only optimize your skin if it is available as an embedded web resource, so you're adding you skin elements to an assembly that the RadStyleSheetManager will consume. I won't go in to the full details of how this process works in this article, but there is a great tutorial on Telerik.com that shows you exactly what to do. Follow that article that build your custom assembly.
Once your assembly is ready, reference it in your web project and configure your RadStyleSheetManager to use it. You must be using RadControls for ASP.NET AJAX Q1 2008 SP1 (2008.1.515) or later for this technique to work. To use my custom skin for RadTabStrip, I set the following in my RadStyleSheetManager:
In the previous snippet, "TelerikCustomSkins" is the name of the assembly I built to hold my custom skins and "TelerikCustomSkins.TabStripMidnightArrow.css" is the path to the "TabStripMidnightArrow.css" file in my skins project. With these settings in-place and the properties I previously configured still set (EnableEmbeddedSkins=false, Skin=MidnightArrow), my RadTabStrip is ready to use my highly optimized custom skin.
You now know how to build your custom skin and how to super optimize it with the RadStyleSheetManager, but is the effort worth it? Let's let the numbers talk. The following graph shows the comparison in page load times and number of requests on page load for an identical page, one with a RadTabStrip using my custom skin in the App_Themes directory, one with a "super optimized" version of my custom skin.
Clearly, the optimization benefits of reducing the requests on the page by enabling your custom skin to work with the RadStyleSheetManager are clear. Skins optimized to work with the RadStyleSheetManager helped reduce page load time on average by almost 10% and reduced the number of requests on page load from 8 to 7 (initial request + 3 for ASP.NET AJAX JS, 1 for Telerik JS, 1 image, 1 for CSS). You can expect the benefits would exponentially increase for more complex pages using several custom skins. Exponentially because as you add more custom skins to optimized pages you'll keep adding extra requests for CSS whereas super optimized skins will always generate a single CSS request.
The summary of this tip is pretty easy:
If you're using custom skins with the RadControls for ASP.NET AJAX, you need to "super optimize" them to work with the RadStyleSheetManager to maximize your page load performance.
Hopefully you found this overview of skinning and skinning optimization helpful. There are a lot of other great skinning resources on Telerik.com, including full guides for skinning all of the RadControls in online documentation. Use the information in those articles along with the tips you learned here to ensure your skinning is as optimized as possible and your pages load as quickly as possible. Until next time, have fun optimizing your apps and impressing your developer friends with your mad coding skills.