ASP.NET Controls– Applying CSS styles to a Menu control
This is subject to which I ended up returning from time to time, either for professional purposes, for some pet project or simply to help a friend.
For those of you that already played with Menu control knows that applying CSS styles to the standard ASP.NET Menu control can be a real frustrating task. For all the other I hope that this post avoid or at least reduce this pain.
Problem
The main question regarding styles is how the control renders. The Menu control renders HTML element TABLE, TR and TD and this approach bring us two main problems:
- Turns CSS style configuration more complex
- Increases the overall HTML size
I’m not sure why the control renders like this but I believe is related to multi browser CSS compatibility. We must not forget that even today we face several multi browser CSS problems (with IE8 the differences went minimal but we still have to deal with older browsers for many years) and by the time NetFX 2.0 saw the daylight the gap between browsers were larger and rendering HTML elements TABLE, TR and TD was the one that offered less compatibility issues.
Solution
Fortunately, ASP.NET 2.0 added the concept of ControlAdapter. This is a piece that can be associated to a control type and enable us to change the way that control renders.
As you can imagine, this opened a door to adjust controls without changing the control itself. But, there’s always a but, those kind of associations Adapter/Control are (out of the box) an application setting.
The mapping is made with a Browser Definition File Schema that should look similar to:
<browsers> <browser refID="Default"> <controlAdapters> <adapter controlType="System.Web.UI.WebControls.Menu" adapterType="YourMenuAdapter" /> </controlAdapters> </browser> </browsers>
These files should be deployed to the App_Browsers folder.
Now that we know about the ControlAdapters is clear that we need one to the Menu control. Since I’m a lazy programmer, I won’t create from scratch a MenuAdapter. Instead I will use an existing one.
You can find in CodePlex a project that give us a set of Adapters very useful in most common scenarios: ASP.NET 2.0 CSS Friendly Control Adapters.
Between those adapters there’s a specific one for the Menu control. This adapter renders the Menu control as an unordered list using Div, Ul e Li HTML elements and this way allow us to easily apply CSS styles without loosing multi browser compatibility and with less Html signature. Here is an Html sample:
<div class="AspNet-Menu-Horizontal"> <ul class="AspNet-Menu"> <li class="AspNet-Menu-WithChildren AspNet-Menu-Selected"><a href="javascript:__doPostBack('ctl00$B$fvMenu','bTest 0')" class="AspNet-Menu-Link AspNet-Menu-Selected">Test 0</a> <ul> <li class="AspNet-Menu-WithChildren AspNet-Menu-ParentSelected"><a href="javascript:__doPostBack('ctl00$B$fvMenu','bTest 0\\Test 1')" class="AspNet-Menu-Link AspNet-Menu-ParentSelected">Test 1</a> <ul> <li class="AspNet-Menu-Leaf AspNet-Menu-ParentSelected"><a href="javascript:__doPostBack('ctl00$B$fvMenu','bTest 0\\Test 1\\Test 1a')" class="AspNet-Menu-Link AspNet-Menu-ParentSelected">Test 1a</a> </li> <li class="AspNet-Menu-Leaf AspNet-Menu-ParentSelected"><a href="javascript:__doPostBack('ctl00$B$fvMenu','bTest 0\\Test 1\\Test 1b')" class="AspNet-Menu-Link AspNet-Menu-ParentSelected">Test 1b</a> </li> <li class="AspNet-Menu-Leaf AspNet-Menu-ParentSelected"><a href="javascript:__doPostBack('ctl00$B$fvMenu','bTest 0\\Test 1\\Test 1c')" class="AspNet-Menu-Link AspNet-Menu-ParentSelected">Test 1c</a> </li> </ul> </li> <li class="AspNet-Menu-Leaf AspNet-Menu-ParentSelected"><a href="javascript:__doPostBack('ctl00$B$fvMenu','bTest 0\\Test 2')" class="AspNet-Menu-Link AspNet-Menu-ParentSelected">Test 2</a> </li> <li class="AspNet-Menu-Leaf AspNet-Menu-ParentSelected"><a href="javascript:__doPostBack('ctl00$B$fvMenu','bTest 0\\Test 3')" class="AspNet-Menu-Link AspNet-Menu-ParentSelected">Test 3</a> </li> <li class="AspNet-Menu-Leaf AspNet-Menu-ParentSelected"><a href="javascript:__doPostBack('ctl00$B$fvMenu','bTest 0\\Test 4')" class="AspNet-Menu-Link AspNet-Menu-ParentSelected">Test 4</a> </li> </ul> </li> </ul> </div>
A great sample is available here and the source code can be downloaded here.