Recently on ilovetypography.com there was a guide to web typography. Whilst reading through it I remembered a little web tool that I put together a while back now to help me choose my font settings.
The basic idea original came from the alistapart.com article Setting Type on the Web to a Baseline Grid and a set of Intelligent font fall back rules.
I hope that you find the font tester tool a useful part of your design toolkit.
Monday, 3 March 2008
A CSS Font Tester Tool for your web design toolkit
XHTML 2 XHTML
As mentioned before Serif uses XSLT for it's transforms as this is a readily available technology and why should we reinvent the wheel.
So previously we have been talking about the ideal XHTML markup to use for your menus but our system doesn't actually give us all the info we want, CSS classes especially. What we need to do is parse the generated XHTML and add what we need, so lets first look at what we have to play with:
<ul class="main-menu">
<li><a href="/page-one.aspx">Page One</a></li>
<li><a href="/page-two.aspx">Page Two</a></li>
<li><a href="/page-three.aspx">Page Three</a></li>
<li><a href="/page-four.aspx">Page Four</a></li>
</ul>
And what we want;
<ul class="main-menu px-menu">
<li class="first odd page-one-link"><a href="/page-one.aspx"><span>Page One</span></a></li>
<li class="even page-two-link"><a href="/page-two.aspx"><span>Page Two</span></a></li>
<li class="odd page-three-link"><a href="/page-three.aspx"><span>Page Three</span></a></li>
<li class="last even page-four-link"><a href="/page-four.aspx"><span>Page Four</span></a></li>
</ul>
So we've got a few things to do here including adding CSS classnames and some extra XHTML elements as well. lets look at an xslt transform that literaly loops through our menu and rebuilds it.
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="urn:ext-methods">
<!-- Match on the root UL element node -->
<xsl:template match="/">
<ul>
<xsl:attribute name="class">
<xsl:if test="not(@class = '')">
<xsl:value-of select="@class" />
<xsl:text> </xsl:text>
</xsl:if>
<xsl:text>px-menu</xsl:text>
</xsl:attribute>
<xsl:apply-templates select="li"/>
</ul>
</xsl:template>
<!-- Match on a single li element node -->
<xsl:template match="li">
<xsl:variable name="title">
<xsl:value-of select="a" />
</xsl:variable>
<xsl:variable name="link">
<xsl:value-of select="a/@href" />
</xsl:variable>
<li>
<xsl:attribute name="class">
<xsl:call-template name="general-position-class" />
<xsl:text> </xsl:text>
<!-- Add a CSS class name to identify the text of the link -->
<xsl:value-of select="translate($title,' \/:*?<>|ABCDEFGHIJKLMNOPQRSTUVWXYZ', '---------abcdefghijklmnopqrstuvwxyz')"/>
<xsl:text>-link</xsl:text>
</xsl:attribute>
<!-- Add a span tag inside the anchor tag -->
<a href="^{$link}.aspx" title="{$title}">
<span><xsl:value-of select="$title"/></span>
</a>
</li>
</xsl:template>
<!-- Add CSS class names based on the position() of the passed element within the current nodeset -->
<xsl:template match="general-position-class">
<xsl:choose>
<xsl:when test="position() mod 2 = 0">even</xsl:when>
<xsl:otherwise>odd</xsl:otherwise>
</xsl:choose>
<xsl:if test="position() = 1"> first</xsl:if>
<xsl:if test="position() = last()"> last</xsl:if>
</xsl:template>
</xsl:stylesheet>
The transform we have here is a fairly simple one the first template matches on the root node
<ul/> and generates XHTML with the added CSS class name px-menu allowing us to identify this as a menu in the XHTML. it then selects the <li/> elements into a nodeset and applys the second template. for each <li/> in the nodeset we add some CSS class names and a span inside the anchor tag.The final template is called from each
<li/> and literally examines the position of the node within the nodeset and applies CSS class names approriately.So there we have it, a transform that can take a simple XHTML list and turn it into a perfect menu HTML, best of all by simple changing a couple of lines we could easily turn this into a
<dl/> list or even a set of <span/>.
Thursday, 28 February 2008
Extending XSLT Sort with C#
In serif we do a lot of messing around with XSLT, it's incredibly powerful. From our point of view why create a templating language when there is already a perfectly good (and standard) way of turning data into something else. We'll be talking more about that in the next in the sitemaps and menus series.
Sometimes there is something that we want to do with XSLT that is just plain hard. Some things it's just not so good at, messing with strings for example. There are libraries that extend the abilities of XSLT but they don't always do what you want.
Usefully, there is a mechanism for calling external code from inside the transform, you declare a namespace for it to live in, then when you call the transform you attach the necessary code.
I'm going to go through an example of how you would add the ability to sort based on tag relevance in C#. Pretty specialized I realize but the principals can be used all over.
So, first the obligatory sample data:
<items>
<item tags="one">
<description>Just has one</description>
</item>
<item tags="two,three">
<description>Has tags two and three</description>
</item>
<item tags="three,four">
<description>Has tags three and four</description>
</item>
<item tags="one,two">
<description>Has tags one and two</description>
</item>
</items>Each of the items has a tags attribute associated with it, its comma separated just the way you would want to type it in. We think its by far the easiest way to deal with them unless you have a ridiculous number of documents and tags.So next comes the transform, it has an extra namespace to hold the functions that we want to add. And then the short version is used in front of the function to call it.
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="extensions"
exclude-result-prefixes="ext">
<xsl:output
method="html"
omit-xml-declaration="yes"
indent="yes"/>
<xsl:param name="match" select="'one,two'"/>
<xsl:template match="/items">
<ul>
<xsl:apply-templates select="item">
<xsl:sort
select="ext:TagScore($match,@tags)"
data-type="number"
order="descending"/>
</xsl:apply-templates>
</ul>
</xsl:template>
<xsl:template match="item">
<li>
<xsl:value-of select="description"/>
<xsl:text> - </xsl:text>
<xsl:value-of select="ext:TagScore($match,@tags)"/>
</li>
</xsl:template>
</xsl:stylesheet>The interesting bit of the transform itself is the sort element inside the apply-templates, normally it would be used to sort based in a value from the document that was being transformed, generally inside the nodes being selected. In this case the external function
TagScore is called to sort on. We can pretty much do any sorting that we please from that point on.The function that calculates a score for each item look like this:
public class TagsParser
{
public static ArrayList Parse(string Tags)
{
ArrayList tags = new ArrayList();
string[] tagsArray = Tags.Trim().ToLower(CultureInfo.InvariantCulture).Split(new char[] {','});
foreach (string tag in tagsArray)
{
string tmp = tag.Trim();
if (tmp != "")
tags.Add(tag);
}
return tags;
}
public static double TagScore(string Match, string Tags)
{
ArrayList matchList = Parse(Match);
ArrayList tagsList = Parse(Tags);
double score = 0.0;
foreach (string matchTag in matchList)
if (tagsList.Contains(matchTag))
score += (double)1 / matchList.Count;
return score;
}
}The methods are static because they are used elsewhere for processing text into tags and its the simplest way to get the job done. In this case we actually pass an instance of the class into the transform to to give it access to the methods.Its really simple to tell C# which extension object to use:
XsltArgumentList args = new XsltArgumentList();
args.AddExtensionObject("extensions",new TagsParser());
You just need to make sure that the namespaces match up.The result looks like this:
<ul>
<li>Has tags one and two - 1</li>
<li>Just has one - 0.5</li>
<li>Has tags two and three - 0.5</li>
<li>Has tags three and four - 0</li>
</ul>This example only deals with simple extensions to XSLT, taking two strings and returning a double. It's possible do some really powerful things by passing other types, XML data is passed and returned as an
XPathNodeIterator so you can have loads of fun with that.The most important thing to remember is to maintain the separation between the data and presentation, if you find yourself doing more complex things is might be an idea to move the functionality somewhere else it'll probably make your life easier in the long run.
Wednesday, 20 February 2008
CSS, Understanding the cascade
Serif CMS is a system that allows you to edit your website from inside your web pages. the usual "admin pages" have been replaced with in page tools such as file management, inline text editing and menu editing. There is a fundamental problem with this and that is that unless the site is loaded into a frame every part of the interface is within the document and therefore affected by any CSS style sheets added to a page.
Due to the CSS cascade we decided that basic styles would be added before any user or template style sheets. This means that everything has a sensible default - which includes amongst others basic menu CSS and CSS reset - allowing designers to easily override what is set if desired. For our interface elements that have to be styled in a specific way we didn't want to put the style onto the elements because that would merge the JavaScript and CSS. We decided that as the designers wouldn't have access to our interface HTML elements adding them last would mean that our style sheets would override what the designers had set... or so we thought.
Understanding the complexities of the cascade a months ago seemed to be a mystical art that we had so far not run up against. Obviously with CSS there are several hacks that need to be implemented and could be implemented to make all browsers yield to our creative whims - and within this lay a very small but fundamental flaw in our API reasoning.
let me give you a CSS example;
/* Template Style */
#left a { color:red }
#center a { color:blue }
/* interface override style */
div.editor a {color:green}
In this example the template changed the color of the links depending on which column the link was in, so we needed to ensure that our links didn't. So our extra bit of CSS was supposed to change this to make sure it was the same in either column - But this wasn't happening. Because the template had used an
id selector and we had used a class name selector we we're lower in the cascade even though our element was inside the templates selected element.We couldn't use
id selectors of course because we might be trying to override another template that had completely different id in the HTML. We could have used !important but that just gets ridiculous and causes more problems than it fixes. Our solution was to root every style we had to the root level node and because of our knowledge of CSS hacks we had to use some CSS hacks to do this ourselves.
/* interface override style */
html>body div.editor a, /* overide most modern browsers */
* html body div.editor a, /* overide IE but not IE7 */
*:first-child+html body div.editor a {color:green} /* overide IE7 */
The above method only works because we have selected
<html/;> as our root. This isn't a fool proof method because a template can easily override us still by adding an id to it's body and using a CSS selector on that along with a hack, at that point we say, why?We would be very grateful to here your thoughts on what you would like from a CMS if you designed it and we have created a small form for you to fill out. If you are interested in hearing more about the Serif CMS Join our mailing list for updates and the first beta tickets when they are available.
Monday, 18 February 2008
CSS Toolbox : Menus and Sitemaps, Part 2
If you take out CMS Survey you could win a $50 Amazon voucher
Following on from our previous post we will look at the CSS behind a menu and some examples of different styles that show off what we have done.
First lets look at some base styles to create a horizontal menu;
.menu{
display:table;
margin:0;
padding:0;
list-style-type:none;
white-space:nowrap;
}
* html .menu{
display:inline-block;
width:1px;
}
.menu li{
display:table-cell;
cursor:pointer;
margin:0;
padding:0;
}
* html .menu li{
display:inline;
}
.menu a, .menu a:visited{
display:block;
padding:0 1em;
}
* html .menu a, * html .menu a:visited{
display:inline-block;
}
Here we are using the CSS star-html hack to select IE6 and adjust the style set on our menu in this browser. we use the CSS display style of
table, and table-cell in all browsers except IE6 which uses inline-block and inline.The example webpage shows how we have easily aligned the menus.
We can override our base styles to make the menu vertical by simply adding the following styles to our collection and giving our menu the apropriate class;
.vertical-menu {
text-align:left;
display:block;
width:200px;
}
.vertical-menu li{
display:block;
text-align:left;
}
The example webpage shows this put to use.
By utilizing our
first class we can change the style of the first element to do something like remove it's border so the items are seperated by lines but not on the ends.
.simple-menu li {
border-left:1px solid steelblue;
}
.simple-menu li.first {
border-left-width:0;
}
.simple-menu a, .simple-menu a:visited {
color: steelblue;
padding:2px 1em;
text-decoration:none;
}
.simple-menu a:hover {
color: black;
}
The example webpage shows this put to use.
Friday, 15 February 2008
Html Fixer
If you take our CMS survey you could win a $50 Amazon voucher.
In our CMS we use a Rich Text editor to let the users create content, a lot of web applications do. Some do more and some do less, all of them have to contend with the fact that it's the browser that generates the Html. Also most of them allow the user to fiddle with the Html. Suddenly you start getting things like <i><b>text</b></i> posted back to the server.
In previous versions of our CMS we have treated client Html as a string and just ignored it. Its a bad idea for two reasons, you can't guarantee what you serve will be xhtml and you can't access the content in the same way you would everything else.
Whats the point in having an XML database if your not going to use it.We decided that everything must be valid xml if not xhtml even if that means making some assumptions. So this means fixing things. The main emphasis here was valid xml not necessarily making sense, but it would be nice if we could do that too.
The parser works in a similar way to SAX but with one important difference. It creates a list of events as a whole instead of sending them individually to be processed.
The whole list is then used to build a valid structure. At any point during processing, the code doing the building is free to look into the past or the future to try to figure out what is going on.
So for example an isolated
looks like an element is being opened but never closed. When you stick an element in the output tree you have a look into the future and see if its ever closed, if its not do it now. Its possible to specify what elements to do this with as it's not always appropriate.
You can pass the parser lists of elements and attributes that are allowed so that it can act as a filter as well. If its not on the list it doesn't go in.
There are three types of events that are created open, close and text. The html
<p>some<br/>text</p> would be open:p,text:some,open:br,close:br etc. From this very simple list of events is possible to create valid XML.It must be stressed that this code is proof of concept. There are lots of things that will break it, I have no idea what it will do with comments for example. And I'm pretty sure that a DTD at the top of a file will make it fall over. But, this is a start, it will get more sophisticated as we write more tests. The tests that we have at the moment are included with the code so you will see how simple things are at the moment.
Hope this was all interesting, feel free to have a poke around the code and see what you can do with it.
Anyone who uses Content Management Systems should have a look at our survey, it's very important to us and you might get $50.
if your interested in seeing where this idea goes in the future let us know in the comments and we'll keep you posted.
Friday, 8 February 2008
CSS Toolbox : Menus and Sitemaps, Part 1
After several years of creating websites for different people, for different reasons - and having to translate weird and wonderful designs by graphic designers into usable websites - you start to develop a little black book of snippets to use.
In Part 1 we are going to look at the HTML behind our menus and sitemaps.
Our general problem is that there are a multitude of browsers and versions and if we want to cater for as many as possible we need to do a few things to make things a little easier. so lets start with some example HTML;
<ul class="menu corporate-menu">
<li class="first odd item-link-one"><a href="#"><span>Link One</span></a></li>
<li class="even item-link-two"><a href="#"><span>Link Two</span></a></li>
<li class="odd item-link-three"><a href="#"><span>Link Three</span></a></li>
<li class="last even item-link-four"><a href="#"><span>Link Four</span></a></li>
</ul>This is a nice simple
<ul/> with some <a/> and <span/> inserted, plus a few CSS class names to help us locate them in our stylesheets. Lets just go through what we have done here and why.First we added some
<span/> inside the <a/>. By doing this we can not only make expandable backgrounds but we can actually make our expandable backgrounds react to the a:hover CSS class, which means that IE6 is supported.We have also added some class names that allow us to target our elements in the CSS easily. We have a class added to the
<ul/> which distinguishes this from other <ul/> by noting that it is a "menu", it also has a class telling us which this will be - the "corporate-menu". This has also been done on the <li/> by giving each a class name that indicates which item it is - begining "item-".The last useful class names are pretty self explanatory "odd" and "even" gives us scope to alternate our styles, and "first" and "last" allows us to have each end slightly different to the rest. The other advantage of having these class names is that we can use CSS child selectors to allow us to differentiate some modern browsers from other older ones.
In the next part I'll go through some CSS examples using this HTML so that we can see how this simple bit of HTML markup allows us great scope in our CSS by allowing us to create both vertical and horizontal menus as well as tabs.
why not use a HTML id?
this question should be answered before we finish, and for this there is a simple answer - The cascade or more precisely the selector's specificity.
To make life easy for ourselves we have a base stylesheet that adds a useful set of CSS instructions to our HTML documents meaning that we can then just overload this base stylesheet with another for a particular website and we don't have to keep rememebering how to do things like menus, setting a minimum page width or even reseting all the HTML elements to a single basic style. the problem with using
id is that if we used the CSS selector "#corporate-menu" we would have to use it all the time otherwise the base-style would overide our overloading stylesheets this just wastes time in debug trying to work out why the link you have is still black and isn't red like in your CSS stylesheet.