Dave's Notebook

Why CSS ID selectors are Evil in ASP.NET Web Forms

Anyone familiar with CSS knows that class selectors are generally reserved for controlling how an element looks (font, color, size, etc) and id selectors are generally reserved for where the element is positioned on the screen. The reason for this is that id selectors correspond to the id attribute of the elements on the screen and if you are using well formed html, you can only have one element on the page with any specific ID. That is, IDs are unique. However, ASP.NET uses that exact same feature of IDs… that they are unique.. to ensure that an ASP.NET control or an HTML control with the runat=”server” attribute set also have unique IDs, and this is where all the problems start. Let’s say you have an aspx page with an asp:Label control on the screen with an ID of label1. (Highly descriptive name, I know, but this is just an example.) For our first example, we will just place this on a regular aspx page and there won’t be any master pages or user controls involved. In our css file, we can then create a rule: #label1{ layout information here } And everything will work as intended. But, place that same label inside of a user control and it won’t work. This is because the asp.net runtime will generate a new ID attribute that is a combination of the user control’s ID and the Label control’s ID. You get a similar behavior when you put a label in an ASPX page that has a master page attached to it. In this case, you end up with an ID prefixed with ctl00_. (You ARE using master pages, right?!) OK, you say. So, we just won’t use id selectors in combination with ASPX Controls. We’ll do all of our positioning with DIVs that have IDs. Well, that sounds good until the real world strikes. What happens when you discover that you need to make that DIV a runat=”server” control? Yep, you run into all the same issues. That rule that was working so beautifully suddenly stops working. Arrrgh! So, what to do? Well, you really have two choices. You can come up with some sort of naming convention that let’s everyone know that the ID is part of a CSS rule and therefore the element it is in can’t be made a runat=”server” control. Or, you can avoid using ID selectors in ASP.NET completely. In this case, you might use multiple classes per element. One class would be the positioning class and the other would be the presentation class. Like so:

more text and html here
The advantage of using a special naming convention is that you can still be sure the names are unique. The disadvantage is that you are going to have times when you are going to need to do some wacky html tricks to achieve what you want. For example, you may need to hide a div using the code behind file. But, because you can’t make it a runat=”server” control, you will need to create another div that is runat=”server” so that you can hide the element without killing the rule. On the other hand, if you use classes, you have no assurance that the class will be assigned uniquely to one an only one element. But, you will be able to make any control on the screen a runat=”server” control if you need to. For my own coding purposes, I’ve chosen to use classes exclusively and have banned ID selectors from my style sheets. In my mind the flexibility outweighs the possibility that I’ll be using the same positioning class in multiple locations. So, how have you solved this issue? Let me know in the comments section.