ASP.NET Menu with jQuery Superfish

by Arnold Matusz 9 8 2009

Choosing the right type of menu for a website is not easy at all. The ASP.NET Menu Control is definitely NOT a good starting point due to the horrendous markup it renders, nor is it good for SEO because of the Markup/Content ratio, neither can it be easily styled.

Of course there is the CSSFriendly Control Adapters project that started back in 2006, which made the the ASP.NET Menu (and many other ghastly markup rendering controls) render beautiful <div> based markup. In the case of the Menu it rendered <div> and <ul>-<li> type markup which is probably the most widely spread technique used for creating menus known to mankind.

To every upside there is a downside. Although there are some examples online for both integration and styling I really find the CssFriendly Menu Adapter a bit difficult to style. The online example shows the styling technique on 3 different levels which then results in a huge CSS file. To give it some credit, the supplied CSS example is extremely well commented, so one with little CSS experience will do just fine.

But in Mythbusters tradition: “If it’s worth doing, it’s worth overdoing”, the idea is to use a modified version of the CssFriendly Menu adapter with the jQuery Superfish plugin.

I’ve renamed all the css class names in the CssFriendly project (the ones like: “AspNet-Menu-Vertical”, “AspNet-Menu-Leaf”, “AspNet-Menu-WithChildren”) to their Superfish equivalent ("sf-menu”, “sf-with-ul”, etc.). Now you can use the jQuery Superfish Menu Plugin out of the box with it’s standard css class names.

You need use the same sort of markup for your server side ASP.NET Menu control like you’ve used with the standard CssFriendly Menu Adapter, and make the JavaScript call needed to set the Superfish plugin up.

<asp:Menu ID="mnu" runat="server" CssSelectorClass="myMenu">
    <Items>
        <asp:MenuItem NavigateUrl="#" Text="Item1">
            <asp:MenuItem NavigateUrl="#" Text="Sub1 Item1"></asp:MenuItem>
            <asp:MenuItem NavigateUrl="#" Text="Sub1 Item2"></asp:MenuItem>
            <asp:MenuItem NavigateUrl="#" Text="Sub1 Item3"></asp:MenuItem>
            <asp:MenuItem NavigateUrl="#" Text="Sub1 Item4"></asp:MenuItem>
        </asp:MenuItem>
        <asp:MenuItem NavigateUrl="#" Text="Item2">
            <asp:MenuItem NavigateUrl="#" Text="Sub2 Item1"></asp:MenuItem>
            <asp:MenuItem NavigateUrl="#" Text="Sub2 Item2"></asp:MenuItem>
            <asp:MenuItem NavigateUrl="#" Text="Sub2 Item3">
                <asp:MenuItem NavigateUrl="#" 
                              Text="Sub2 Item3 Item1 and some 
                                    very very very long text">
                </asp:MenuItem>
                <asp:MenuItem NavigateUrl="#" Text="Sub2 Item3 Item2"></asp:MenuItem>
                <asp:MenuItem NavigateUrl="#" Text="Sub2 Item3 Item3"></asp:MenuItem>
            </asp:MenuItem>
        </asp:MenuItem>
        <asp:MenuItem NavigateUrl="#" Text="Item3">
            <asp:MenuItem NavigateUrl="#" Text="Sub3 Item1"></asp:MenuItem>
            <asp:MenuItem NavigateUrl="#" Text="Sub3 Item2"></asp:MenuItem>
            <asp:MenuItem NavigateUrl="#" Text="Sub3 Item3"></asp:MenuItem>
        </asp:MenuItem>
        <asp:MenuItem NavigateUrl="#" Text="Item4"></asp:MenuItem>
    </Items>
</asp:Menu>

The necessary JavaScript:

<script type="text/javascript">
    // initialize plugins
    $(function() {
        $("ul.sf-menu").supersubs({
            minWidth: 13,
            maxWidth: 40,
            extraWidth: 5
        }).superfish();
    });
</script>

And the outcome looks like …

jQuery Superfish example

I like it allot how you can take advantage of jQuery and make this menu animate when submenu items open, I also like how easy it is to create and maintain the css for the menu. Then there is the fact that you can couple Superfish with other plugins like bgIframe, hoverIntent, and also Supersubs, which enables you to resize the width of submenu items independently according to the longest item within that group. Most of all, I like how my menu looks the same in all browsers including that … IE6 – no comment here.

The downside is that there is no graceful degradation. But this is always a problem with ASP.NET Webforms with that __doPostback function() and as I’m building the whole functionality upon jQuery the full featured JavaScript library the website has no sense without JavaScript.

I would like to point out that I have not created the CssFriendly Menu Control Adapter, I have only renamed the css class names, so no copyright infringement intended.

The CssFriendly project pages:

jQuery Superfish plugin:

Download the solution containing a sample website and the altered CssFriendly Menu Adapter project: CssFriendly ASP.NET Menu with Superfish.

What do you use to create a menu with ASP.NET?

DZone it Digg it Submit to StumbleUpon Submit to Technorati Submit to reddit.com Submit to del.icio.us Submit to NewsVine Submit to Furl Submit to BlinkList

Tags: , , ,

ASP.NET | JavaScript

Comments

8/9/2009 8:48:18 PM #

trackback

ASP.NET Menu with jQuery Superfish

You've been kicked (a good thing) - Trackback from DotNetKicks.com

DotNetKicks.com |

8/9/2009 8:48:24 PM #

trackback

ASP.NET Menu with jQuery Superfish

You are voted (great) - Trackback from WebDevVote.com

WebDevVote.com |

8/18/2009 8:51:51 PM #

Alexandros Ilatzis

thanks for the cool project! Can we extended a bit more?

Is it possible to create the whole control content from c#
i mean dynamic content creation.

get results from a db table

structure the code as this

<asp:Menu ID="mnu" runat="server" CssSelectorClass="myMenu">
02.    <Items>
03.        <asp:MenuItem NavigateUrl="#" Text="Item1">
04.            <asp:MenuItem NavigateUrl="#" Text="Sub1 Item1"></asp:MenuItem>
05.            <asp:MenuItem NavigateUrl="#" Text="Sub1 Item2"></asp:MenuItem>
06.            <asp:MenuItem NavigateUrl="#" Text="Sub1 Item3"></asp:MenuItem>
07.            <asp:MenuItem NavigateUrl="#" Text="Sub1 Item4"></asp:MenuItem>
08.        </asp:MenuItem>
09.        <asp:MenuItem NavigateUrl="#" Text="Item2">
10.            <asp:MenuItem NavigateUrl="#" Text="Sub2 Item1"></asp:MenuItem>
11.            <asp:MenuItem NavigateUrl="#" Text="Sub2 Item2"></asp:MenuItem>
12.            <asp:MenuItem NavigateUrl="#" Text="Sub2 Item3">
13.                <asp:MenuItem NavigateUrl="#"
14.                              Text="Sub2 Item3 Item1 and some
15.                                    very very very long text">
16.                </asp:MenuItem>
17.                <asp:MenuItem NavigateUrl="#" Text="Sub2 Item3 Item2"></asp:MenuItem>
18.                <asp:MenuItem NavigateUrl="#" Text="Sub2 Item3 Item3"></asp:MenuItem>
19.            </asp:MenuItem>
20.        </asp:MenuItem>
21.        <asp:MenuItem NavigateUrl="#" Text="Item3">
22.            <asp:MenuItem NavigateUrl="#" Text="Sub3 Item1"></asp:MenuItem>
23.            <asp:MenuItem NavigateUrl="#" Text="Sub3 Item2"></asp:MenuItem>
24.            <asp:MenuItem NavigateUrl="#" Text="Sub3 Item3"></asp:MenuItem>
25.        </asp:MenuItem>
26.        <asp:MenuItem NavigateUrl="#" Text="Item4"></asp:MenuItem>
27.    </Items>
28.</asp:Menu>

and then let the jquery do its job

is it possible?

Alexandros Ilatzis Greece |

8/23/2009 11:17:28 PM #

Arnold Matusz

Hi

Of course this would work with dynamic Menu contents. The whole idea is this: let the menu generate whatever content it wants, the adapter takes over which then renders the nice css friendly markup using div, ul, li-s, and then on the client side javascript takes over and makes a nice menu out of the markup.

No matter what items, sub menu items there are, you can add them during runtime, this will definitely work!
Ain't that nice? Smile.

Arnold Matusz Romania |

9/2/2009 4:06:38 PM #

Shahid

How to implement this on same asp:menu but with vertical orientation?

Shahid |

9/2/2009 6:20:31 PM #

Arnold Matusz

The jQuery Superfish plugin also supports vertical menus. So you'd only need to adjust the orientation of the ASP.NET menu.

Arnold Matusz Romania |

9/9/2009 9:32:44 AM #

pingback

Pingback from thenetgod.netau.net

ContinousLearner: Links (8/13/2009) | Astha

thenetgod.netau.net |

9/9/2009 3:16:05 PM #

Patrick Kelly

I have done the same thing, with a slight twist.  I used the SQLSiteMapProvider in congunction wtih the CSSFriendly adapters to create my menu. But rather than modifying the CSSFriendly code I used jquerys removeClass() to strip all the Asp-Net-Menu classes and thenaddClass() to add the superfish sfmenu class. While this does rely on jquery to modify the markup at render time it allows me to leave the CssFriendly code alone. And I figure that I am dependent on jquery to make the menu look right anyway. That said I havent tested how it degrades but it does work on all major browsers as long as javascript, jquery, is enabled.

Patrick Kelly United States |

9/9/2009 5:20:04 PM #

Arnold Matusz

This is an interesting approach, although it seems like a bit of "performance overhead" on the client. Since CssFriendly does it's job anyway, it's not worth overloading the client with such a task on every postback.

I normally don't like to modify open source code, because it changes allot so it's a pain to maintain after a new shiny version comes out.

But this part of CssFriendly (Menu) is available since it came out, and it suffered no modifications since. That's also why I created a separate assembly that only contains the MenuAdapter.

Anyway, your approach is very ingenious, congratulations for that Smile.

Arnold Matusz Romania |

9/14/2009 1:14:44 PM #

trackback

ASP.NET Menu with jQuery Superfish

DotNetBurner - burning hot .net content

DotNetBurner - Javascript |

11/27/2009 3:17:39 AM #

Hubert

Thank you very much. Exactly what I needed!!!

Hubert Austria |