Learn More





DNN Community Blog

The Community Blog is a personal opinion of community members and by no means the official standpoint of DNN Corp or DNN Platform. This is a place to express personal thoughts about DNNPlatform, the community and its ecosystem. Do you have useful information that you would like to share with the DNN Community in a featured article or blog? If so, please contact .

The use of the Community Blog is covered by our Community Blog Guidelines - please read before commenting or posting.

Make your DNN Module XHTML compliant


A. XHTML forces you to create clean code
B. The separation of content and layout potentially makes XHTML pages better for viewing on mobile devices (although this only true if you use less or no tables)
C. For the same reason they are better for accessibility
D. In a lot of countries there are regulations that make XHTML for public or government websites mandatory.

For these reasons we are trying to get the core and all modules to validate for XHTML.
This is part of the release process now and this document is intended to you as a developer some guidelines on how to get you module XHTML compliant.


Here are some tools that can help you develop XHTML valid modules:
1. Visual Studio / Visual Web Developer express.
The editor can warn you for XHTML errors, they will be visible in the "Error List" pane.
In Visual Web developer Express edition
            Menu: Tools > options > validation
            For target: Choose "XHTML Transitional" and check "Show errors".
This will only show you static XHTML errors, not what is generated in code.
This also forces the editor to close all your tags, including
2. Testing in DNN - XHTML compliant skin
Use the latest version of DNN to test and use an XHTML compliant skin.
(DNN with the the Minimal Extropy skin is XHTML compliant since DNN 5.1)
3. Test rendered output in the browser
There are some valuable plugins for testing for XHTML compliance:
A. "Html Validator" extension for FF.
It integrates with the "Source view" in Firefox.
Install the extension.
Choose Tools > Html Validator option" and set
- Algorithm to "Serial"
- Enable validation in Browser, this will show an Error icon in the browser (right bottom) if there are errors.
Double-clicking the icon will open the source view, showing the errors / warnings.
If you double-click an error it shows the offending HTML in the top pane of the source view window.
Note: This validator has one problem, it shows a warning about ID's starting with an underscore (viewstate), this is invalid for HTML, but valid for XHTML (if the tags are wrapped in a div), so you can ignore this.
B. Internet Explorer: web developer toolbar
Firefox: Web Developer extension
Both can validate local and online pages, but IMO the FF extension is easier to use.

They will open a new page with the test page in the W3C validator for an XHTML compliance test.
* Mostly one XHTML violation causes more then one error in the test.
* Some errors can also hide other errors, so you'll have to test again after your changes.

Where to start?

There are a few simple things you can do to get rid of 90% of the XHTML violations.
These will prevent you from having to go through a lot of issue if you test your module in an XHTML validator.

A. Use Visual studio to clean your ASCX

1. Open your ASCX files in Visual Studio
2. Switch to Source view
3. Select all
4. Right Click and choose "Format Selection"
This will get rid of all CASE errors and add a closing / to all image tags

B. Search for unclosed elements

Search the ASCX for "<br>" and "<hr>" and fix them by adding a closing /
C. Check for Images without alt attributes
1. Search for "<asp:Image>" & <asp:ImageButton> and make sure they all have the "AlterNateText" attribute set
2. Search for <img> and check if there is an Alt attribute, if not add one.

D. Check Label controls

You should only use a Label control if you are 100% sure it will never contain block elements (<p>, <div>, etc).
In general, if the user can change the text you cannot be sure this is the case.
Replace the label control with a panel or a literal.

Use an XHTML validator

Finally you should test you module with either a plug in or one of the online validators to find the remaining issues.
Most validators give you some guidance on how to solve an issue too.

Other common problems:

A list of the problems we see most during the module XHTML tests:

-All tags should be closed
Wrong: <br>, <hr>, <img src="test.gif" alt="test">
Correct: <br />, <hr />, <img src="test.gif" alt="test" />

-All tags and attributes should be in lowercase
Wrong: <DIV Class="test">, <div onClick="myfunction">
Correct: <div class="test">, <div onclick="myfunction">

-All Attribute values should be quoted
Wrong: <td colspan=2>
Correct <td colspan="2">

-Every img tag should have an alt attribute.
Wrong: <img src="test.gif" />
Correct: <img src="test.gif" alt="test image" />
This attribute is mandatory to help the visually impaired, you will not help them by adding alt="".
Please use descriptive alt text values.

-Deprecated tags
Wrong: <center></center>
Correct: <div style="text-align:center"></div>

-Block elements inside inline elements
Wrong: <span><div>test</div></span>, <p><div>test</div></p>
Correct: <div><div>test</div></div>
This is often caused by the use of the label control, use the literal control instead (with a div).
If you have to add a block element inside an inline element, use an inline element and set its CSS to display:block, the result is the same and it will validate.

CSS files linked in the Body
All linked CSS files should be in the head of the page.
Adding a CSS file link directly in your ASCX will lead to an XHTML violation.
Add your CSS links with this code:

Dim oLink As New HtmlGenericControl("link")
oLink.Attributes("href") = "YourFile.css"
oLink.Attributes("type") = "text/css"
oLink.Attributes("rel") = "stylesheet"
Dim oCSS As Control = Me.Page.FindControl("CSS")
oCSS.Controls.AddAt(0, oLink)

HyperLink control
When you use the Hyperlink control with the ImageUrl attribute set, but without the
Text attribute set, the image will not get an alt tag.
In many cases you will need to add an Image control inside the HyperLink control to be XHTML compliant.
    <asp:HyperLink ID="lnk" ImageUrl="~/desktopmodules/Module/icon.gif" runat="server" />
You could replace it with:
    <asp:HyperLink ID="lnk" runat="server">
    <asp:Image ID="lnkIcon" runat="server" ImageUrl="~/desktopmodules/Module/icon.gif " AlternateText="Link Icon" />

But this does mean you need to check your code if you are setting the ImageUrl attribute dynamically.

Things to avoid

<br />
The main reason for a module developer to render a Break is mostly because he used a label and wants to force the next element on a new line.
If you render a div instead of a label (or any other inline element) the result is the same and it's a lot better for skinners.
(A div can be forced to float left, a <br /> cannot)

If you want to avoid XHTML errors you should not be using these in your controls at all. A <p> element can only contain inline elements, which means a <div> inside it will be an XHTML violation.
Mostly these are used to create some distance to the element above it.
There is no guarantee this will actually work because most skinners will overrule the <p> margin-top to 0.
It is better to use a div or a literal and set the margin-top for the element, or even better; add a class and set the margin-top in module.css.

A lot of developers use this to get some space between two inline controls. The problem is that the distance depends on the font size and if the two controls don't fit in the available width, the second will float down and the &nbsp; could be in front if it.
Instead use CSS: padding-right for the first or both elements.

Module.css vs. inline styles
Try to separate content and layout by putting all you CSS in module.css, try to avoid inline CSS.
It's much easier to use inline CSS, but it will make your module a lot more difficult to skin.
The advantage of putting the CSS in module.css is that you are forced to assign classes to the objects and this means a skinner can use these classes too.
If you use inline CSS, there is no way a skinner can address the tag, unless you provide a class or id.
Make sure the classes / CSS either uses the default DNN classes or is specific enough so it doesn't influence the rest of the site.

Question / suggestions

I hope this document helps with the process of getting a module XHTML compliant.
If you have any questions or suggestions, feel free to contact me.

Useful links


Comment Form

Only registered users may post comments.


2sic Daniel Mettler (124)
Aderson Oliveira (15)
Alec Whittington (11)
Alex Shirley (10)
Andrew Nurse (30)
Anthony Glenwright (5)
Antonio Chagoury (28)
Ash Prasad (21)
Ben Schmidt (1)
Benjamin Hermann (25)
Benoit Sarton (9)
Beth Firebaugh (12)
Bill Walker (36)
Bob Kruger (5)
Brian Dukes (2)
Brice Snow (1)
Bruce Chapman (20)
Bryan Andrews (1)
cathal connolly (55)
Charles Nurse (163)
Chris Hammond (203)
Chris Paterra (55)
Clinton Patterson (28)
Cuong Dang (21)
Daniel Bartholomew (2)
Dave Buckner (2)
David Poindexter (3)
David Rodriguez (2)
Doug Howell (11)
Erik van Ballegoij (30)
Ernst Peter Tamminga (74)
Geoff Barlow (6)
Gifford Watkins (3)
Gilles Le Pigocher (3)
Ian Robinson (7)
Israel Martinez (17)
Jan Blomquist (2)
Jan Jonas (3)
Jaspreet Bhatia (1)
Jenni Merrifield (6)
Joe Brinkman (269)
John Mitchell (1)
Jon Henning (14)
Jonathan Sheely (4)
Jordan Coopersmith (1)
Joseph Craig (2)
Kan Ma (1)
Keivan Beigi (3)
Ken Grierson (10)
Kevin Schreiner (6)
Leigh Pointer (31)
Lorraine Young (60)
Malik Khan (1)
Matthias Schlomann (15)
Mauricio Márquez (5)
Michael Doxsey (7)
Michael Tobisch (3)
Michael Washington (202)
Mike Horton (19)
Mitchel Sellers (28)
Nathan Rover (3)
Navin V Nagiah (14)
Néstor Sánchez (31)
Nik Kalyani (14)
Peter Donker (52)
Philip Beadle (135)
Philipp Becker (4)
Richard Dumas (22)
Robert J Collins (5)
Roger Selwyn (8)
Ruben Lopez (1)
Ryan Martinez (1)
Salar Golestanian (4)
Sanjay Mehrotra (9)
Scott McCulloch (1)
Scott S (11)
Scott Wilkinson (3)
Scott Willhite (97)
Sebastian Leupold (80)
Shaun Walker (237)
Shawn Mehaffie (17)
Stefan Cullmann (12)
Stefan Kamphuis (12)
Steve Fabian (31)
Timo Breumelhof (24)
Tony Henrich (3)
Torsten Weggen (2)
Vicenç Masanas (27)
Vincent Nguyen (3)
Vitaly Kozadayev (6)
Will Morgenweck (37)
Will Strohl (163)
William Severance (5)
Try Evoq
For Free
Start Free Trial
a Demo
See Evoq Live
Need More Information?