03 September 2008

Writing DNN Skins

This is the second of three blog entries that make up a full introduction to DotNetNuke (DNN) from a developer's point of view. This time I cover writing a skin and a container to change the appearance of a DNN web site. Last time, I gave an Introduction to DNN - next will be Writing Custom Modules. A concise version of the complete article first appeared on 1 July 2008 in UK programming magazine VSJ.

The simple skin and container used in this blog can be downloaded here.

DNN5 has a new extension/package structure for custom modules and skins - however 'legacy' DNN3 and DNN4 skins will install in DNN 5 - select Skin as the legacy skin type.

Overview

This time, I look at how to create a skin that defines the appearance of a site and write custom modules that provide content on a page. The figure below shows a typical DNN layout: the skin defines the page layout, including one or more panes. An admin user can place one or more modules in a pane, with each module wrapped in a container.

Skins

A skin package defines how DNN presents its content, ie the overall HTML of the page, all the CSS styles, and various parameters for the breadcrumb and menu screen elements. A container package defines how each module container looks in a similar way. If you install a ‘skin’ it typically contains both skin and container packages. An individual skin package may contain several different layouts, eg fixed width and full-screen instances.

DNN seems to have a preference for fixed-width skins and fixed size fonts. I presume that this is an attempt to achieve a perfect appearance on the page. However, it is best to make use of all the screen width and make the page work well as font sizes are changed by the user. Fixed sizes may achieve the desired effect in Internet Explorer, as long as the user doesn't Zoom. However in FireFox, changing the text size also changes fixed point sizes in the same way as IE Zoom. For more details, see my previous blog entries: DotNetNuke Internet Explorer fixed size fonts and DotNetNuke Internet Explorer font scaling.

These CSS files are used by DNN, in this order, with the Portal CSS included last so its definitions take precedence over any earlier ones.

  1. Portal default CSS (in /portals/_default/default.css)
  2. Current skin CSS
  3. Current container CSS
  4. Portal CSS (eg in /Portals/0/portal.css)
The ‘portal default CSS’ defines styles for most generic HTML elements (H1, TD etc) though strangely not P – using fixed-point font sizes in most cases; it also defines CSS classes for all the standard DNN elements.

The ‘portal CSS file’ contains blank elements to let you know what the standard definitions are – this file can be updated in the [Admin][Site Settings] menu.

Skin and container development

If you have installed the DNN Starter Kit into Visual Studio, you can create a skin and container using [File][New][File] - "DotNetNuke Skin" template. However, to illustrate a basic skin and container, I have developed a simple example which you can download. These are the files that I used to create the example:
skins/simpleskin.htm
skins/skin.css
skins/skin.xml
skins.zip

containers/simplecontainer.htm
containers/container.css
containers/container.xml
containers.zip

simple.zip

The files in the skins directory are zipped up to make skins.zip, ditto for containers. Then these two are zipped together to make simple.zip that contains both the skin and container packages.

Each site has one current skin and one current container. When you install a skin, the files are unzipped and a skin user control is created - when chosen as the current skin, this user control is inserted into the main page output. A skin has pane elements - DNN inserts the right modules into each pane, each wrapped in a container. The current container is also a user control with a ContentPane that contains the actual module output.

If you install a skin from the [Admin] menu, then the packages will be installed in directory \portals\0\skins\simple\ and \portals\0\containers\simple\. The file simpleskin.htm contains various template tokens, such as [LOGO], that are expanded on installation into file simpleskin.ascx – the ASP.NET user control that is included in the DNN output. If you update the in-situ simpleskin.htm, then click on "Parse Skin Package" in [Admin][Skins] to recreate simpleskin.ascx to see your changes. (Don't include any ascx files in your final skin/container zip package.)

The SimpleSkin.htm skin template defines the basic HTML of the main DNN output, typically using tables for layout. Various tokens appear in square brackets, replaced by DNN at install/runtime. The main output panes are defined in this example as table cells with the predefined correct id names. If you are better at XHTML than I am, change this template to avoid tables.

<table class="ss_header" width="100%">
<tr>
<td>[LOGO]</td>
</tr>
</table>

<table class="ss_menurow" width="100%">
<tr>
<td class="ss_menu">[SOLPARTMENU]</td>
<td class="ss_menu_user">[USER] [LOGIN]</td>
</tr>
</table>

<table class="ss_main" width="100%">
<tr>
<td class="ss_crumb">[BREADCRUMB]</td>
<td class="ss_date">[CURRENTDATE]</td>
</tr>
</table>

<table class="ss_content" width="100%">
<tr>
<td id="LeftPane" runat="server" />
<td id="ContentPane" runat="server" />
</tr>
</table>

The skin.css file contains all the definitions you want (not forgetting to override the DNN defaults if required), eg simply:
.ss_date,.ss_menu_user
{
text-align:right;
}
The skin.xml file defines parameters that are used by DNN. The first one shown tells DNN to use the » character as a separator between the breadcrumb page names. The second set of parameters makes the menu horizontal, etc.
<Objects>
<Object>
<Token>[BREADCRUMB]</Token>
<Settings>
<Setting>
<Name>Separator</Name>
<Value><![CDATA[ » ]]></Value>
</Setting>
</Settings>
</Object>
<Object>
<Token>[SOLPARTMENU]</Token>
<Settings>
<Setting>
<Name>display</Name>
<Value>horizontal</Value>
</Setting>
...
The SkinContainer.htm container template looks similar to the skin template, with tokens replaced when the container is rendered. The main module output is in the ContentPane. The container.css file contains definitions for the CSS classes used in the container template. Similarly, container.xml defines various container-level parameters.
<table width="100%" class="c_all">

<tr>
<td class="c_header" colspan="2">
<table width="100%">
<tr>
<td>[SOLPARTACTIONS]</td>
<td>[ICON]</td>
<td style="width:100%;" class="c_header_title">[TITLE]</td>
</tr>
</table>
</td>
</tr>

<tr>
<td class="c_content" id="ContentPane" runat="server" colspan="2" />
</tr>

<tr>
<td>[ACTIONBUTTON:1]</td>
<td>[ACTIONBUTTON:2]</td>
</tr>

</table>
There are many more tokens and options that you can use. Ideally you should also include a preview of your skin and container by including in each zip a JPG with same name as your template file.

16 comments:

Anonymous said...

author is a noun and not a verb. One does not 'author' something, one *is* an author

Chris Cant said...

Fair enough - I'll change it to create.

Anonymous said...

Hi. I'm new to skinning and found your article very informative. I'm using DNN V4.09, and I've successfully created a new skin by modifying the default skin, MinimumExtrophy. I've removed some of the DNN tokens that I don't want, and I've made no changes to the skin.xml file --- which I know is wrong. I understand that the html and xml files must "match", but I don't know in what way. Obviously, the tokens should match, however, I've noticed that there is no [LOGO] token in the default xml file. Also, do the tokens in the xml file have to appear in the same order as in the html file? Finally, although I haven't changed the xml file to match the html, I have been able to see all my changes, although the site doesn't render properly in IE - it's fine in FF... which is what led me to learn about the xml file. Sorry for such basic questions, but I appreciate your help tremendously.

Chris Cant said...

skin.xml configures how various elements are displayed. I'm not a skin expert, but I don't think that there are any options for [LOGO] so it doesn't need to be in skin.xml. The order of items in XML files don't usually matter. I'd usually leave the skin.xml alone initially - it's probably an HTML/CSS issue that causes the problem in IE.

Did you mean that you had changed the ascx to match the html? Don't forget that you can use "Parse Skin Package" in [Admin][Skins] to recreate the ascx.

Anonymous said...

Thanks for your reply. I've learned a few things - thanks for the important step that I had missed and do not see in any other documentation than yours - remove the ascx file from my newly-built zip file. I think the error regarding the [USER] token had to do with packaging the original ascx file, and not parsing it. Anyway, that cleaned up some points. Your logic also seems reasonable as to why there is no [LOGO] token. I've left a message in the Skinning forum to try to determine why there are differences between IE and FF with just the default MinExt skin. My final issue has to do with the upload and parse procedures - even after I comment-out some tokens from both the html and xml files, they still appear during the upload and the parse operations. It doesn't cause problems - yet - it's just interesting that they appear at all. I'm using the standard html comment syntax in xml, should I use something else to comment-out an xml statement? Thanks for your wonderful help!

Chris Cant said...

The upload/parse operations probably simply list all the tokens that they are looking for - whether or not they are used in your skin.

Chris Cant said...

http://en.wikipedia.org/wiki/XML
This is what wikipedia says about XML comments:

"XML comments start with <!-- and end with -->. Two consecutive dashes (--) may not appear anywhere in the text of the comment."

Anonymous said...

Thanks for your fabulous help - your answers and explanations are clear, concise and make a lot of sense. It appears that I'll have to upgrade to DNN V4.9.2 to have IE render the MinExt skin properly - UGH! Anyway, thanks a million!

Anonymous said...

We need to revoke someone's grammar police badge:

http://dictionary.reference.com/browse/author

Author is both noun and verb, but thanks for trying.

Mark Abraham said...

Chris,
Would you let me know how to change the default skin destination file location?

When I follow your "[File][New][File]" instruction, I receive the warning, "A file or folder with name 'Container.css' already exists."

Thanks much for the prescient info.

Mark

Chris Cant said...

Mark

Assuming that you are inserting into the root of your VS project, the new skin and container will go in the existing /Portals/0/Skins and /Portals/0/Containers/ directories, in sub-directories called SkinName. If these folders already exist, then you might get a warning, though I didn't just now. You should delete both these folders beforehand. And rename them afterwards to the name of your skin/container.

Hope that helps, Chris

Anonymous said...

Author is most certainly a verb.

http://www.merriam-webster.com/thesaurus/author[verb]

Anonymous said...

Hi Chris

Do you know any tool that can convert my Web HTML pages ans CSS to DNN skins?

Artisteer does not seem to be able to i,port directly from HTML.

THANKS

Chris Cant said...

I don't know of a tool to convert HTML and CSS into a template - this might be hard to do automatically, though not necessarily too hard by hand if you know what to replace with the appropriate DNN tokens. You then have to package it up by zipping as described in the article.
Chris

Chris Cant said...

Cartoon about how to get comments in blogs:
http://www.shof.msrcsites.co.uk/net_a.jpg

Anonymous said...

>author is a noun and not a verb. >One does not 'author' something, >one *is* an author

WRONG:Author is a noun and a verb.

Hate word fascists, but love themwhen they are wrong