I recently read a book called "Speed Up Your Site" which I highly recommend. It deals with how to optimize wesbites in a number ways for speed, ease of use, search engines, etc. As expected, one of the book's recommendations are to get away from using <table> based layouts and move to <div> based layouts. There are a number of very convincing reasons to do this. One of the main reasons is that <table> based skins require a two-pass evaluation by the client browser in order to calculate the widths of all the columns of each table before rendering the page. I originally started this exercise in an attempt to see if I could replicate the look/feel of the skins shipping with DNN 3.x. using only <div>s to optimize the skins for performance.
Unfortunately, there are quite a number of frustrating bugs (mostly with IE) that make creating a pure <div> based skin a daunting task. After much effort, I was able to come fairly close to the original design. However, during testing, I ultimately came to the conclusion that while <div> based skins may offer a performance boost, they are not ideal for a content management system such as DNN. <div> based skins are ideal whenever the content is known and author has the opportunity to fine tune the controlling CSS file to arrange everything just right to make the content line up correctly. This may work fine in a case where the skin will be used by a fairly techincally procifient author who knows how the skin is built, understands the differences in how the various browsers parse the DOM/CSS, and knows what NOT to do to break the skin. In addiiton, the way that DNN currently works in admin mode can actually make certain <div> based skins look broken even if it looks correct during normal mode (has to do with changing the position attribute and border of content panes).
However, for a general purpose skin that will be used by people of various technical abilities, and, in an environment such as DNN, the primary requirement of a skin is not performance, it is flexibility. The skin must be flexible and robust enough to gracefully handle any type of content that the author might place into a pane area without breaking. <div> based skins are fairly fragile and can be broken quite easily if the content within a <div> is not what was envisioned by the skin creator. The very reason that <table> based skins are slower is also the reason why they are so flexible. The browser will automatically size the containing <table> to fit the content. Thus <table> based skins will automatically expand or shrink to fit the content on the page. <div> based skins are relatively rigid in this respect.
So, in the end, I abandoned my quest to make a <div> based skin. However, during the exercise, I did discover a number of other opportunities for improvement.
Here is a list of issues I found with the skins packaged with DNN. Some might just be personal preference, but many are quite prominant upon playing with the skins and containers for a while.
Not xhtml compliant
It is my belief that we should try to make DNN as future proof as possible by being as XHTML compliant as it can be.
There were several things I noticed missing including:
- Well formed tags. xhtml requires all elements to be closed even if they self close such as "<hr />". There were several instances of tags left open.
- Quotation marks around every element attribute. There were several instances of attributes with no quotaion marks.
- Lower case - xhtml specifies all markup should be in lowercase. Most of the HTML in the .ascx was in uppercase. This is probably due to the particular editor used. For example, for some reason, Visual Studio like to write all its HTML in uppercase.
- Unit specification - xhtml requires that units are specified on any attributes (i.e. 12px rather than just 12)
Presentation code in the markup
Ideally, the skin should try to keep separate the structure markup and the presentation code as much as possible. The .ascx should contain only the structure of the layout while the CSS files contain all of the presentation code. Amoung other reasons, this greatly speeds up the download because the .ascx file will be smaller and the CSS file will be cached on the client browser. There were many instances of presentation code embedded in the structure of the HTML.
For example:
Bloated HTML
As much as possible, the amount of code sent across the wire should be reduced, eliminated, and combined. The .ascx files for both the skins and the containers contain alot of bloat that doesnt need to be there especially with the presentation code issue listed above. I was able to eliminate almost 30% of the size of some of the .ascx files. I think there may be a lot more opportunity to combine elements into common classes, but I got tired, and the way it is now is more straitforward for the person trying to see what I did.
For example:
- Skins - .pagemaster <table> - This wrapping table is there seemingly to set the properties of the page. This can and should be handled by the BODY css element.
- width, border, etc - can all be handled via CSS
- Containers - have a <br> (unclosed) at the end of the file. This is seemingly there to create vertical space between modules placed within the same pane. This would be better handled by using a margin-bottom css element for the module. As-is, <br> will be affected by the user changing their browser font size and that could have a dramatic effect on the vertical gutters between modules.
- Containers - several of them have a dozen or so line breaks at the end of the file. This is just wasted bytes.
Column widths not right
The side columns are specified to be 175px wide and yet a module placed inside one of these columns is not 175 px wide. In fact, the only time a module will be 175px wide, is if there is another module in the pane that contains non-wrappable content that forces the pane to expand past 175px wide. The reason for this is that the middle column (ContentPane) is specified at 100% width.
As-is the 175px specification has almost no effect. Its very confusing and difficult to get a consistant width among multiple modules in the same pane.
Uneven margins/gutters
This bothered me a great deal. The margins between elements on the page all appear to be random.
For example:
- The top and bottom margins around the logo section are not even (bottom is bigger).
- The bottom margin below modules is created with a <br> in the container.
- The left/right margins around modules are unbalanced. This issue is made more obvious whenever one of the side panes has content and the other doesn't. For example, put something in the LeftPane and ContentPane but not in the RightPane and notice the large gap on the right side of the page.
- Most of all, the horizontal gutters are not even close to the width of the vertical gutters. To me, it feels very taxing on the eye because everything appears to be placed semi-ramdomly on the page. The brain gets tired of make visual sense out of the image when everything is unbalanced. A consistant gutter just makes everything look cleaner and feel better.
Lessons I learned from trying to correct this:
- To control the vertical gutters in between modules and other module and modules the edge of the page:
- Use a symetrical left/right padding on the ContentPane, TopPane, and BottomPane (use same number for each pane)
- Use the same padding for the left side of the LeftPane, but no padding on the right side of the LeftPane
- Use the same padding for the right side of the RightPane, but no padding on the left side of the RightPane
- Set the visible property of the LeftPane and RightPane to false. DNN will turn it back on if there is content present and this will activiate the additional padding specified on the LeftPane and RightPane above and create consistant vertical gutters across the page. However, if they are empty, they will remain hidden and the ContentPane will expand to fill the void yet still have the same gutter as everywhere else on the page.
- To control the horizontal gutters in between modules:
- Use a margin-bottom (same size as above) on the container. This will keep modules that are placed in the same pane separated vertically by the same amount that they are separated horizontally.
- If you want gutters that will size with user's choice of text size, use em rather than px. I choose to use PX for the margins here because all of the text is also defined in px or pt. However, this is another sore spot I have, so perhaps I'll do another version that will use only em or % so as to make the skin more accessible to the visually impaired.
Overloaded CSS files
This is more a personal preference, but I prefer a separate CSS file for each skin rather than a common CSS file for all four within the group. As is, the single file will contain many elements that arent not used at all by the choosen skin and just waste bandwidth. There is a possible savings though if you will be using multiple skins/containers from the same group at the same time. For example, if you were to use all four of the DNN - Blue containers on the same page, it would actually be faster to just download one CSS file that applies to all four rather than four individual ones. So, for this reason, I separated the skin css files and combined the container css files. I figure that generally, people will pick one skin for the site and go with it.
Images
The background images used are larger than they need to be at 32px wide. I reduced them to 1px wide with the same effect.
Vertical Menu placement
This again might be personal preference, but I think the Menu should be one of the most prominent elements of the page. As is, the menu actually appears below the TopPane. If there were several modules places in the TopPane, the menu could potentially not even appear on the initial page load (above the fold). The menu should be at the top left most place within the content area. I slightly restructed the vertical skins layout to accomplish this.