Open Source Contributions

By Weston Ruter

One of my favorite things about working at Shepherd Interactive is that I am encouraged to research cutting-edge technologies and experiment with innovative solutions. Often this research is done for client projects, but if I have some down time, I am encouraged to work on projects that interest me. It’s similar to Google’s 20% policy. The end result is that work is more enjoyable, I gain experience with areas that I may not run into on everyday client work, the community benefits from new open source solutions, and Shepherd Interactive benefits from increased exposure.
Read the rest of this entry »

The Four R’s of Electronic Recycling

By Mike Spicer

The rapid pace of high-tech innovation yields an unfortunate byproduct; obsolete high-tech junk that all too often ends up in landfills, where it can leach poisonous lead and other heavy metals into our groundwater. One solution for this problem is electronics recycling.
Read the rest of this entry »

Flash vs. SEO: Can one site have it all?

By Heath Schweitzer

Myth: If you build a site in Flash, search engines can’t see it.
Myth: Sites built in Flash are hard to use because the browser controls don’t work.
Myth: Flash sites are unusable by visitors that need assistive technologies.

One of the many common assumptions of website design is that you can have rich interactivity using Flash or, you can have a site that is easy to use, accessible and also search engine friendly. We’re happy to let you know that this is no longer the case. You can have it all, but you have to plan for it and do some extra work.
Read the rest of this entry »

Winter 2008 • Issue 1

By Mike Spicer

Shepherd Moves to New Digs

Winter 2008 NewsletterExciting changes are afoot for Shepherd Interactive. We’ve moved to a new office space at 5210 Southwest Corbett Avenue, very close to our old home. We grew tired of scraping our knuckles on the ceiling every time we stretched, bumping into each other in the kitchen, and double-booking the conference room.
Read the rest of this entry »

Cross-Browser Web Fonts

By Weston Ruter

There are two general techniques in modern web browsers to display selectable text on a web page in an arbitrary font (and of course the standard technique for displaying non-selectable text is to simply use a raster image). The first technique is to use the CSS @font-face rule, and second is to use Scalable Inman Flash Replacement (sIFR). Used in conjunction, a progressive-enhanced graceful-degrading cross-browser solution becomes possible, as is demonstrated below.

The @font-face Rule

Using the @font-face rule to display a custom font is the preferred solution since it has been standardized since CSS 2; it furthermore works without JavaScript, it is simple to implement, it is lightweight (if the font file is minimized to include only the necessary glyphs), and it is also forward-looking as more and more browsers add support. To be employed, there are two font file formats which must be referenced with the @font-face rule: Microsoft’s Embedded OpenType (EOT) font format must be served to Internet Explorer 4+, but then either TrueType (TTF) or OpenType (OTF) font formats may be served to other browsers (currently only Safari 3.1 and the upcoming Firefox 3.1 and Opera 10).

The easiest way to reference these two separate formats is to employ Internet Explorer’s conditional comments, which requires no server-side configuration. The @font-face rule referencing the EOT font file should be included in a conditional comment in such a way that only IE browsers can see it. For non-IE browsers, a second @font-face rule is then be included which references the TrueType or OpenType font files; this rule should be wrapped in two conditional comments which cause it to be hidden from IE but visible to all other browsers. For example:

<!--[if IE]>
<style type="text/css">
@font-face {
	font-family: "DemoFont1";
	font-style:  normal;
	font-weight: normal;
	src: url("fonts/I-Did-This.eot");
}
</style>
<![endif]-->

<!--[if !IE]>-->
<style type="text/css">
@font-face {
	font-family: "DemoFont1";
	font-style:  normal;
	font-weight: normal;
	src: url("fonts/I-Did-This.ttf");
}
</style>
<!--<![endif]-->

Another way to accomplish this is to recerence a script in the @font-face rule’s src property; this script would then sniff the requesting user agent and then pass-through the EOT font if the browser is IE, and the TTF font if otherwise (remember to include a far-future HTTP Expires header). This @font-face rule can then be placed in the global stylesheet without having to add it to the head element of each page. For example:

@font-face {
	font-family: "DemoFont2";
	font-style:  normal;
	font-weight: normal;
	src: url("fonts/choose-font.php?I-Did-This");
}

And the choose-font.php script could be something like:

<?php
$basename = basename($_SERVER['QUERY_STRING']); //make sure that no one is trying to be malicious
$filename = null;
if(strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false){
	if(!file_exists("$basename.eot")){
		header("HTTP/1.0 404 Not Found");
		echo "$basename.eot does not exist";
		exit;
	}
	header("Content-Type: application/vnd.bw-fontobject");
	$filename = "$basename.eot";
	$f = fopen($filename, 'rb');
}
else {
	if(file_exists("$basename.ttf")){
		header("Content-Type: application/x-font-ttf"); //MIME type not standardized?
		$filename = "$basename.ttf";
		$f = fopen($filename, 'rb');
	}
	else if(file_exists("$basename.otf")){
		header("Content-Type: application/font-opentype"); //MIME type not standardized
		$filename = "$basename.otf";
		$f = fopen($filename, 'rb');
	}
	else {
		header("HTTP/1.0 404 Not Found");
		echo "Neither $basename.ttf nor $basename.otf exist";
		exit;
	}
}

header("Expires: " . str_replace('+0000', 'GMT', gmdate('r', time()+315569260))); //time plus 10 years
fpassthru($f);
fclose($f);
?>

An alternate server-side solution is to employ content negotiation using mod_rewrite.

Beware of a bug in WebKit we found: if there is a Flash piece on one page but no text in the font defined by the @font-face rule–upon navigating from such a page to one which has text in that font, a crash occurs (the workaround is to make sure that some text, even whitespace, on every page uses the font specified by the @font-face rule).

Scalable Inman Flash Replacement (sIFR)

For other browsers which do not support the @font-face rule, then Scalable Inman Flash Replacement (sIFR) is a fallback method for displaying the desired font (see the sIFR project page to learn how to generate the SWF font objects). To ensure that the sIFR script doesn’t clobber text in a @font-face-supporting browser, a font detection algorithm can be employed in sifr-config.js. If the algorithm detects at page-load that no font has been applied to the text in question, then it applies the corresponding sIFR font to the text. On subsequent page views, the algorithm doesn’t need to wait until page-load because it keeps a history of the detected fonts in a cookie so it can take any necessary action as soon as the DOM loads. It is therefore important to note that the text may appear momentarily in the next available font (e.g. sans-serif) until the page completes loading; however, upon subsequent page views it should appear in the proper font immediately. If JavaScript is turned off or Flash is not installed then the next available font will always be displayed.

The sifr-config.js requires a couple properties to be set on the sIFR object in order to be able to find the elements which have special fonts, and in order to tell sIFR where to find the SWF files that correspond to the special fonts defined. The elements are found by adding to each a specific class name to each element, and this desired class name can be stored in sIFR.webFontsClassName; alternatively, the elements may be specified with CSS selectors by setting sIFR.webFontSelector. Secondly, the locations of the sIFR SWF font files is stored in sIFR.webFonts, which is an Object containing keys which correspond to the font-family properties defined in the @font-face rules, and values which consist of yet another Object which consists of one src property whose value is the location SWF file. For example:

sIFR.webFontsClassName = 'demo';
sIFR.webFontSelector = "h1, h2, h3";
sIFR.webFonts = {
	"DemoFont1" : {
		src:'./fonts/I-Did-This.swf'
	},
	"DemoFont2" : {
		src:'./fonts/A-Charming-Font-Expanded.swf'
	},
	"DemoFont3" : {
		src:'./fonts/Y2K-PopMuzik-Outline-AOE.swf'
	}
};

Examples

Here are a couple sites we’ve done employing custom web fonts:

  1. Center for Career and Academic Advancement (CCAA)
  2. Continū Data Services