An exploratory weblog, by

Hypsometry.

XIV.

Symbolic code groups in Ruby.

This came from somewhere, I’m sure of it. I found it, used it, loved it, and here we are, years later, and I don’t have any recollection what that original source was, or who originally coined this simple idiom. Nonetheless, let me present to you a tiny little morsel of Ruby:

class Symbol
  def code(&block)
    block.call
  end
end

Include that in your project, and you can write code that does a better job of self-documenting. For example:

:filter.code do
  def reload_user
    # ..
  end
  
  def verify_humanness
    # ..
  end
end

:form.code do
  def required_status_classname
    # ..
  end
  
  def field_wrapper_classes
    # ..
  end
end

Simple Ruby syntactic sugar, helping you keep things clear and readable. Not only that, but if you’re using a block-folding text editor (such as TextMate), then you can navigate through your code a little bit more easily.

Ashland, Oregon.

XIII.

Goudy on Hypsometry.

Hypsometry has a new design, inspired by the private press movement and its humanist reaction to the industrialization of printing in the nineteenth century.

This design, like my recent work on Hypsography, makes use of Sorts Mill Goudy, Barry Schwartz’s excellent revival of Frederic Goudy’s classic typeface Goudy Old Style. For its titling, it features CastleType’s typeface Goudy Trajan, which is a digital revival of Goudy’s translation of the Roman majuscules found on Trajan’s Column. (Yes, a double revival.)

The layout is built on a simple grid. (Too simple, really, and insufficiently humanist, at this point.) I’ve used, and included, Analog Coop’s #grid script, which means that you can type g and see the grid; type g + h and have the grid stay visible; or type g + f to have the grid displayed on top of the site’s content.

Again following in the traditions of the private presses, Hypsometry now has a printer’s mark, with which I’ve stamped the pages.

More is coming, and I have more to say about all this; but for now, this suffices.

Ashland, Oregon.

XII.

Knuth on digital typography.

I guess I must have ink in my veins: When I first learned about the potential of digital printing technology, I couldn't resist putting the rest of my life on hold while I tried to adapt the typographic wisdom of previous centuries to the possibilities of the present day.

— Donald Knuth,
Digital Typography.

Ashland, Oregon.

XI.

Rubyist static site generators, and a historical aside.

Last fall, after years of creating highly dynamic websites and web applications, I reversed directions. Now I aim for as much static HTML as possible. It’s simpler, faster, cleaner, more elegant, easier to read, and for most projects it’s all you need.

Hypsography and Hypsometry, for example, are both entirely static. Hand written HTML, CSS, and Javascript, served up simple and fast.

This site, the Hypsometry Blog, is built with Jekyll, Tom Preston-Werner’s elegant little Ruby hacker blogging tool. Jekyll takes Liquid templates and fills them with marked-up text, sprinkling a little YAML data over the top, and outputs HTML ready for your server. That works well.

Hypsography, however, is getting to the point where I don’t want to be maintaining all the code by hand (albeit with heavy help from Textmate), but I also don’t want to lose the simplicity and speed of serving static files. There’s no need to migrate to a full-bore content management system, with all the configuration and maintenance hassles that inevitably entails. Jekyll’s wonderful, but it’s not usable on sites that aren’t simple blogs.

Since Jekyll was released, a slew of static site generators written in Ruby have come along (and some have gone right along too). They all have a basic philosophy similar to that originally outlined by Tom Preston-Werner:

They all take templates and content and merge them together, creating static HTML sites ready for deployment. They tend to use YAML for configuration. Most accept multiple markup formats as input. They all can watch your directory for changes in order to rebuild the site dynamically as you work on it.

Their differences are smaller, but important. Each has a slightly different approach to the same problem, and thus each meets a slightly different need.

Having spent the past couple days (for the second time in six months) going through the options and evaluating them, I thought I’d summarize what I’ve found. Let me point out that all the programs discussed below seem excellent and worth investigation. There are other programs out there which seem less excellent, and I’ve ignored those here. Please let me know if I’ve missed anything, of course.

(There is one other useful approach to all this: Writing your own generator using Rake, YAML, and Mustache. This is quite appealing, but not what I’m in the market for today. Chris Wanstrath wrote about his approach last year, if you’re interested.)

Here follows my one-sentence summaries of all the Rubyist static site generators that I’ve looked at recently:

Bonsai.

Beautiful, simple, flexible (uses Tilt for template handling), progressive (HTML5 by default), but the current version doesn’t work out of the box and it’s intended primarily for portfolio sites. (Project site, Github.)

Middleman.

Rails-like (in ways both good and bad), highly configurable and flexible, and includes automatic minification of CSS and Javascript, as well as other useful optimizations. (Introductory post, Github.)

Nanoc.

Extremely powerful and extensible, perhaps too much so, and prefers configuration to convention. (Project site, Github.)

Staticmatic.

Simple, clean, but strangely Haml-dependent. (Ruby Forge, Github.)

Webby.

Simple, flexible, quite Jekyllish. (Ruby Forge, Github.)

Webgen.

Powerful, extensible, slightly rigid in operation. (Ruby Forge, Github.)

Not quite a conclusion.

That’s the list, and those are my notes. You can probably guess which I’m going to try out on Hypsography, but whether or not you can, you’ll be hearing more about the results here.

A historical aside.

Since I wrote once before about static site generation, I’ve taken this opportunity to begin restoring old articles to the Hypsometry Blog. As such, there is now an article zero: Nulla, actually, since the Romans didn’t really have notation for zero.

Nulla serves as a marker. All articles older than it are reprints, numbered negatively (which is also an anachronism, but hey), and probably slightly altered from their original forms. All articles newer are indeed new, part of this latest iteration of the Hypsometry Blog.

As time passes, I’ll continue working my way through the Hypsometry archives, digging out other older articles perhaps worthy of a second look. Or at least worthy of having their links preserved. Don’t take them too seriously – they’re oldies, but not necessarily goodies.

Ashland, Oregon.

X.

Art, not ads.

Art Not Ads
Ashland, Oregon.

IX.

The serfdom of crowds.

Sometime in the mid-nineties, around the time I stopped reading Mondo 2000, Jaron Lanier stopped annoying me. I assumed he was still out there, being all far out and dreaded and inter-disciplinary, but he no longer forced his way into my attention, and was thus out of mind.

Apparently he’s not yet out of sight. He has in the interim, however, become more articulate, more insightful, and more interesting. This past January his newest book, You Are Not a Gadget, was published, and in February Harper’s Magazine published an excerpt called ‘The serfdom of crowds.’

(The complete article is only available online to Harper’s subscribers, but there is an illicit version available on Scribd, in beautiful HTML5. That said, I recommend that you go to your local library and read the damn thing in print.)

Let me quote from it at length, to give you something of its full flavor. Here is Lanier discussing the collapse of the financial markets in 2008 and how that related to, and derived from, the essential inequality of the current structure of the web:

True believers in the hive mind seem to think that no number of layers of abstraction in a financial system can dull the system’s efficacy. The crowd works for free, and statistical algorithms supposedly take the risk out of making bets if you are a lord of the cloud. But who is that lord who owns the cloud that connects the crowd? Not just anybody. A lucky few (for luck is all that can possibly be involved) will own it. Entitlement has achieved its singularity and become infinite.

What has allowed this infinite entitlement, this neo-feudalism? We have, in a thousand little ways:

People degrade themselves all the time in order to make machines seem smart. We have repeatedly demonstrated our species’s bottomless ability to lower our standards to make information technology good.

I would amend the last sentence to refer more generally to ‘technology’, rather than just to ‘information technology,’ for this lowering of standards is wide-spread. For example, it is precisely what allows us to claim that items fabricated from synthetic chemicals and compounds and shaped roughly into the appearance of traditional foodstuffs are, in any way, actually food.

Lanier is focused here specifically on the web side of this argument, not on the general case; but many of the things he writes apply more generally. For example:

Enlightened designers leave open the possibility of metaphysical specialness either in humans or in the potential for for unforeseen creative processes that we can’t yet capture in software systems. That kind of modesty is the signature quality of being human-centered.

To return to my example, this is the difference between manufacturing bread in factories and baking loaves in a wood-fired oven. (Brief aside: When did we begin using ‘manufactured’ to mean ‘not manufactured?’)

The former method asserts that there is nothing special about having a human bake bread; everything involved can be simplified down such that mechanical and software systems can handle it. The latter method, on the other hand, recognizes that there is potential inherent in the baking process that only a baker can explore. Choosing the first method devalues the second – devalues the method, devalues the bread, and devalues both the baker and the eater.

To return to Lanier, on this devaluation and its causes:

What computerized analysis of all the country’s school tests has done to education is exactly what Facebook has done to friendships. In both cases, life is turned into a database. Both degradations are based on the same philosophical mistake, which is the belief that computers can presently represent human thought or human relationships. These are things computers cannot currently do.

And on the resultant effects of this devaluation, this forced technological simplification, this database as life:

When technologists deploy a computer model of something like learning or friendship in a way that has an effect on real lives, they are relying on faith. When they ask people to live their lives through their models, they are potentially reducing life itself.

Ashland, Oregon.

VIII.

HTML5 and Safari Reader.

As you know, Safari 5 came out last week. Two of its best features are the Safari Reader and much improved support for HTML5.

Reader you know about. You might not know, however, that Safari 5 now outscores all other browsers on the HTML5 test. That’s exciting. It’s not complete support, but it’s a lot of the essentials. And, after all, the spec itself isn’t even complete yet.

Another thing you might not know is that I’m working almost exclusively in HTML5 these days. If there’s a reason not to use it, I’m not; but it’s my default and my preference. That means that my photography portfolio site – Hypsography – is all HTML5 under the surface. And that, in turn, means that the news articles I write for Hypsography make appropriate use of the article element, along with many other semantic elements. One <article> equals one article. Simple and clear.

Let’s review what Apple says about Safari Reader:

As you browse the web, Safari detects if you’re on a web page with an article. Click the Reader icon in the Smart Address Field, and the article appears instantly in one continuous, clutter-free view. You see every page of the article — whether two or twenty.

Totally. And it works really well, at least when you’re reading the Times. When you’re reading Hypsography, however, it works a little less well:

That’s not ideal. The ice photograph that’s intruding in the middle of the text is enclosed in an aside, which should be considered “tangentially related to the content around” it, but Safari apparently doesn’t get that. But at least it’s readable, somewhat. And, looking under the surface with the Web Inspector, this misinterpretation looks fixable via CSS.

What’s worse is what happens when you scroll to the end of the article:

Safari has decided that the article ends there. Arbitrarily decided, it seems, since the article does not end there. In fact, of the five sections into which that article – An end of the year review, inspired by Mr. Dalton Rooney – is divided, Safari has chosen to include only two of them. The first and the third sections. Naturally.

Let me clarify this a smidge more: The five sections into which this article is divided are delineated by section tags, all of which are contained with the one parent article. This is semantic, this is simple, and this is clear. You might figure it’d be easy too.

Oh well.

If anybody out there has an understanding of what precisely Safari Reader looks for in an article, please let me know. Thanks, and good luck.

Ashland, Oregon.

VII.

Hypsometry's simple portfolio.

After a diapause of several years, Hypsometry again has a portfolio section.

Ashland, Oregon.

VI.

True small capitals with @font-face.

One small, but quite good, reason to rejoice at the coming of a widely useable @font-face: True small capitals are now possible on the web.

Small capitals are, as Alec Julien put it, “upper case glyphs drawn at a lower case scale.” They are not, however, simply regular capitals shrunk down; they are properly their own font, with their own characteristics, designed to work with both regular capital and lower case letters.

To be more precise: 1. The cap height of a small capital is the same as, or just slightly larger than, the x-height of the typeface’s lower case letters. 2. The weight of the strokes of a small capital are comparable, visually speaking, to the weight of the strokes of the typeface in general, at the size being used. 3. The proportions of a small capital are also comparable, visually speaking, to the proportions of the characters of the typeface in general, at the size being used.

Two implications of the latter two points are that the strokes and proportions of a given small capital letter will be heavier and more spread out than the strokes and proportions of the same letter upper cased, at the same point size. This is because small capitals have the form of regular capital letters, but the characteristics of the lower case.

Unfortunately, true small capitals are hard to come by these days. Computer software, as a rule, uses fake small capitals, created simply by scaling down upper case letters so that they are smaller than the originals, but larger than the associated lower case. This is true of web browsers as well as word processors, desktop publishing applications, and vector editors.

For instance, the second line above should look about like this, using true, properly designed small capitals: But, had I not @font-face to rely on, your web browser’s fake small capitals would make it look more like this: Not at all the same thing, clearly. The proportions of the second example are all wrong – simultaneously too big and too thin, tracked too tightly, and rather difficult to read. The first example is balanced, strong, eminently legible.

Using true small capitals on the web was not possible until recently, at least not with type that is actually type. Let’s look at how it works, and also, along the way, at several ways to fake small capitals. Comparing them all side by side will make even clearer the import of the differences I described above.

1. Setting the font-variant property to small-caps.

This is what should work. The W3C CSS standard tells us that font-variant: small-caps will instruct the browser to do the right thing. “A value of ‘small-caps’ selects a small-caps font”, it says.

This is how your browser interprets font-variant: small-caps:

Giambattista Bodoni: February 16, 1740 in Saluzzo – November 29, 1813 in Parma.

That looks okay, I guess. In comparison to the small capitals, the upper case letters and numerals look overly heavy. Some of the small capital letters – the t and the m, for instance – have strokes that are so thin as to almost vanish.

Let’s look at a second example, to make the differences clearer:

A a a — M m m — X x x

Now you can see quite clearly that the cap height of the small capitals is substantially larger than the x-height of the lower case letters, to say nothing of the overshoot of letters like a and m. Also, you can see how the proportions and weights of these fake small capitals match neither the upper case nor the lower case. All in all, this style of fake small capitals works quite poorly.

But why is this? The typeface in which this page is set – IM Fell Great Primer – has a small capitals variant, so why do the browsers not use it? After all, the CSS standard says that they should when font-variant: small-caps is used.

Sadly, no browser has actually implemented this. Instead of looking to see whether true small capitals are available, they all jump to the next portion of the standard:

It is acceptable (but not required) if the small-caps font is a created by taking a normal font and replacing the lower case letters by scaled upper case characters.

I’m not sure who, precisely, thinks that that is acceptable, but even if it were, it is surely not acceptable to ignore existing small capital fonts created by proper methods in favor of bogus ones created on the fly.

2. The Joe Clark method.

Faced with the problems above, Joe Clark suggested a simple alternative: Convert the text to capitals and reduce its size. This is, of course, exactly what the browsers do when you specify font-variant: small-caps. The slight theoretical advantage provided by Joe Clark’s method is that you can more precisely and carefully control how much the fake small capitals are scaled down, leading, perhaps to better matching of heights, proportions, and weights. A simple example:

Giambattista Bodoni: February 16, 1740 in Saluzzo – November 29, 1813 in Parma.

Of course, applied like that, Joe Clark’s method forces all letters and numerals to small capitals, even if that’s not what you desired. A slightly more sophisticated version of his method would apply the technique selectively – say, to letters that are already lower cased. Let’s assume that you have an automatic way to do so – a CMS plugin, for example, or a clever piece of Javascript:

Giambattista Bodoni: February 16, 1740 in Saluzzo – November 29, 1813 in Parma.

This, of course, is a total pain in the ass, and it makes a bit of a hash of the text’s HTML. On the other hand, it does allow for more precise control of the size of the fake small capitals, which might be helpful.

To see that more clearly, here is a third example – the same as the one in §1:

A a a — M m m — X x x

You see the same problems as in §1: The Joe Clark small capitals are too big and their proportions are wrong. The weights, however, are not quite as bad. Let’s look at a fourth example, comparing the font-variant method and the Joe Clark method, in that order, to see how the two compare:

a am mx x

The proportions and weights of Joe Clark’s fake small capitals are better than those of the font-variant method, but only because the letters themselves are even larger. Hard to call that an improvement.

3. The Nick Shinn method.

This problem of how to fake small capitals when no proper ones exist, or the software will not let you access them, is not unique to the web. Nick Shinn has suggested that, in addition to capitalizing and reducing the size of the text, you should increase its weight. This allows for making the small capitals a little smaller – a little closer to the actual x-height of the typeface – while better preserving their weights and proportions.

A simple example:

Giambattista Bodoni: February 16, 1740 in Saluzzo – November 29, 1813 in Parma.

A more sophisticated example, again – as in §2 – imagining some sort of automated helper, and ignoring the complexity of the technique and the hash it makes of the HTML:

Giambattista Bodoni: February 16, 1740 in Saluzzo – November 29, 1813 in Parma.

This looks better in some ways, and worse in others. It is still basically unacceptable. Perhaps in some contexts, with some combinations of typeface and size, this might work well. Here, despite the improvement in small capital size, the overly heavy weight is too much. Of course, the typeface you see here has no true bold weight, so your browser is faking it; perhaps it is too much to hope that a faked heavy weight could help us, in turn, fake small capitals.

Let’s compare upper case, lower case, and Nick Shinn small capitals:

A a a — M m m — X x x

Correct height and proportions with excessively heavy weight is no better than incorrect height. And it turns out that the x-heights are not in fact correct: They only appear correct at this size of type. Try resizing the text in your browser window, and you’ll see that the evenness is limited to the sizes I’ve set here.

A fourth example, this time comparing the font-variant method, the Joe Clark method, and the Nick Shinn method, presented in that order:

a a am m mx x x

Of these three, the browser scaling method seems the best, despite is many flaws. None produce good results, and it’s far and away the simplest.

4. Using @font-face.

There is an additional problem here, besides the technical failings of the browsers and the limits of what you can express using CSS: Proper small capital fonts are a rarity. Type designers design them, foundries sell them, but few non–professionals have them on their computers.

The typeface in which the Hypsometry Blog is set is IM Fell Great Primer, a beautiful typeface first cut by Peter de Walpergen, acquired by John Fell in the late 1680s, and digitally revived by Igino Marini. In its original metal, IM Fell Great Primer consisted of romans, italics, and small capitals. Sr Marini has created OpenType versions of all three, and made them freely available. As such, I can use @font-face to specify the use of the small capitals variant.

An example:

Giambattista Bodoni: February 16, 1740 in Saluzzo – November 29, 1813 in Parma.

And, again, a comparison with the upper and lower cases:

A a a — M m m — X x x

Glorious. The cap height of the small capital x is precisely the same as the x-height of the lower case x – and this holds true even if you resize the text away from how I’ve set it here. The cap heights of the small capitals a and m are smaller than the overshoot of the lowercase a and m. The visual weight and proportions of the small capitals are all quite similar to those of the lower case letters, even while the forms of the small capitals remain true to the appearance of the upper case.

Just to be absolutely clear, let’s see all four methods lined up side by side – font-variant: small-caps on the left, followed by the Joe Clark method, the Nick Shinn method, and the true small capitals of @font-face:

a a a am m m mx x x x

The @font-face method is far and away the best. Unfortunately, it is the best in appearance and the worst to use.

The biggest problem, as mentioned above, is that few typefaces have proper small capital variants. Of those that do, some include them within the regular roman file, which puts them off limits to web use. Unicode currently does not define a place for small capitals, which means that browser cannot access them.

For example, you’re likely to have the typeface Didot on your computer. The roman of that Didot includes small capitals, but as glyphs 264–389, located in the Unicode range called “Glyph Variants”, which you cannot access within a browser.

Assuming that you’re using a typeface that includes proper small capitals, and that those small capitals are included as their own distinct font file, then you must declare a @font-face rule that makes use of them. In theory, you would do have already defined your romans and italics something like this:

@font-face {
  font-family: "IM Fell Great Primer";
  src: local("IM FELL Great Primer");
}

@font-face {
  font-family: "IM Fell Great Primer";
  font-style: italic;
  src: local("IM FELL Great Primer Italic");
}

In other words, we’re defining a font family named IM Fell Great Primer, the roman of which can be found locally as “IM FELL Great Primer”, and the italic of which as “IM FELL Great Primer Italic.” The browser loads both of those fonts, and when a reference to font-family: IM Fell Great Primer is found it uses the former when font-style is normal, and the latter when italic.

According to the W3C standard, there should be no difference when defining a small capitals variant:

@font-face {
  font-family: "IM Fell Great Primer";
  font-variant: small-caps;
  src: local("IM FELL Great Primer SC");
}

In other words, the font referred to by this @font-face rule is the small capitals variant of the IM Fell Great Primer family, and can be found locally under the name “IM FELL Great Primer SC.” When the browser encounters a reference to font-family: IM Fell Great Primer with font-variant: small-caps, it should then go ahead and use the font referenced above. An example of such a reference:

p strong {
  font-variant: small-caps;
}

However, the browsers do not yet understand this. Firefox, for instance, only understands font-weight and font-style within @font-face rules. That means that you cannot rely on the browsers to automatically use the proper small capitals variant, even when you have explicitly told them the necessary details. Instead, you must define a redundant rule like this:

@font-face {
  font-family: "IM Fell Great Primer SC";
  src: local("IM FELL Great Primer SC");
}

And then use it like this:

p strong {
  font-family: "IM Fell Great Primer SC";
}

That way you have explicitly told your browser where to find the small capitals variant and when to use it. And, when forced in this fashion, the browsers do finally get things right.

5. Other details.

It’s a bit convoluted, all this, and I haven’t even touched on how to properly prepare your font files for browser use, or how to really make use of @font-face. To summarize, use the Font Squirrel.

To see the CSS for all the methods discussed above, take a look at my Hypsometric CSS project. If you have any questions or suggestions, do let me know.

Ashland, Oregon.

V.

Hypsography News.

Over at Hypsography my work is continuing apace, and that pace is increasing. I’m continuing my explorations of humane typography there. The site is now set in Sorts Mill Goudy, an excellent revival of Frederic Goudy’s incomparable Goudy Old Style.

If you view the site using a recent version of Firefox, you’ll even see that the f and i of field are joined into one ligature – as they should be. Firefox is currently the only browser that supports serious OpenType typographic enhancements. Where by serious I mean kerning and ligatures. Yes, 460 years have passed since Gutenberg began printing with moveable type, and we are just now returning to those basic capabilities.

At any rate, Sorts Mill Goudy is a beautifully rendered typeface. Barry Schwartz is its author, and he has made it available under both the Open Font License and the MIT License: OFL Sorts Mill Goudy and MIT Sorts Mill Goudy. You can also find it in the Typedia, along with another excellent, though less completely realized, Goudy revival by Mr Schwartz: Goudy Bookletter 1911.

I used the Font Squirrel’s @font-face generator to prepare the files for Hypsography, and I highly recommend it. To make the process even simpler, the Font Squirrel already has OFL Sorts Mill Goudy in its archive, along with a pre-generated @font-face kit. Or, if you prefer, both Kernest and Typekit also include Mr Schwartz’s Goudy revival.

From the information available on the project site, Sorts Mill Goudy appears to be a work in progress. Nonetheless, it seems quite ready for use right now. Using Tim Brown’s web font specimen, I’ve put up a demonstration page for Sorts Mill Goudy on Hypsography, for your further inspection.

To return to my initial point: Hypsography has a new look, a new section for news and other ephemera, and a newly added tetraptych. Enjoy.

Ashland, Oregon.

IV.

Wildcat Strike.

Wildcat strike.
Ashland, Oregon.

III.

HTML5 Default Styles.

While updating my reset stylesheet last week, I realized that if I wanted to reset the new HTML5 elements I would have to determine precisely how they were supposed to be styled. Which proved to be a challenge, since no browser yet supports anything like the full array of new elements and styles.

Luckily, the current HTML5 specification contains extremely detailed descriptions of how browsers should render HTML documents. These are not requirements, of course, but rather “a set of suggestions.” These descriptions, found in §11 Rendering, are of reasonable expectations; and thus it seems reasonable, in turn, that I base my expectations for the future behavior of browsers on them. (Realizing full well how deeply foolhardy that might be.)

Within the many suggestions listed in §11 – and they are many and detailed – there is one in particular that is relevant here: §11.2 The CSS user agent style sheet and presentational hints. This section walks through the varieties of default styles and describes how each HTML element is to be handled. Specific CSS is provided, and additional instructions and suggestions are noted. From time to time, the additional notes refer to styles best handled by CSS, though for the most part they don’t.

Regarding the new HTML5 elements, my goals are to:

  1. Set up the appropriate display properties, so that blocks display as blocks by default.
  2. Make sure that any elements that shouldn’t be visible are not.
  3. Counteract, in a speculative, preventative manner, any styling that browsers are likely to apply.

§11 contains all the information I need to meet these goals. It describes the display types of the elements, including their visibility, and it describes all the other styling that should be applied by the browsers, once they support HTML5 more completely.

Therefore I compiled all the recommended CSS into one stylesheet. In doing so, I realized that the styles recommended are entirely too comprehensive. Styles for deprecated elements and elements modified by deprecated attributes are listed, so I removed them from my stylesheet. CSS bindings for each element are listed in §11.4 – but only Gecko supports that functionality, and it currently only supports it in a proprietary way; so I left out the bindings styles too.

In other ways, the recommended CSS does not go far enough. Two sets of styles, describing the appearance of h1 elements nested within the new semantic content elements, are so complicated that the draft standard only summarizes how they are supposed to work. Both §11.2.3 and §11.2.5 note that the styling of an h1 element varies depending on its context. Of course, h1 has its own default styling – font-size: 2.00em, for instance. But when you have an h1 nested within a section elementsection h1, that is – it should receive font-size: 1.50em. And if you have another heading, nested even further - article section aside h1, for example – that should have font-size: 1.00em applied. This is important, since HTML5 has radically redefined how we are supposed to use headings.

Sadly, the draft standard authors have left it as an exercise to the reader to actually write the relevant styles, for all the nesting depths. I have done so, though I’m not entirely sure I’ve done so correctly. The permutations involved are reasonably complicated, particularly since section elements can nest within each other, though none of the others can.

There is only one additional change that I’ve made, a quite small one, but potentially useful. §11.2.2 Display types describes how each element should be displayed by default – head is hidden, blockquote is a block, table is a table, ruby elements are displayed like ruby characters, et cetera. The list of block level elements, however, does not include the details element.

An element new to HTML5, “the details element represents a disclosure widget from which the user can obtain additional information or controls”, according to §4.11.1. It is what the standard calls an interactive element, and is meant to act as a wrapper for other content which may be displayed or hidden as the reader prefers. The usage example provided – as well as the description of how to use the details element – suggests wrapping it around a dt and a dd, as if it were a special type of definition list. As such, it seems appropriate to style the details element as a block, and I’ve done so.

You can see the stylesheet that resulted from my compilation and editing on GitHub, along with some notes. You’re free to use it as you like. As always, please do let me know if you notice any problems or have any suggestions.

Ashland, Oregon.

II.

Reset Stylesheets and HTML5.

There are two important reset stylesheets out there, on the loose: Eric Meyer’s reset.css and YUI’s CSS Reset. Both are highly useful, though they differ slightly in the details of their approach and implementation. Eric intends for you to take his CSS and alter it to your needs, creating a reset stylesheet that works for your own projects. He describes it as:

The reset styles given here are intentionally very generic.… In other words, this is a starting point, not a self-contained black box of no-touchiness.

Yahoo, on the other hand, is aiming for a more complete resetting. They write:

The foundational CSS Reset removes the inconsistent styling of HTML elements provided by browsers. This creates a dependably flat foundation to built upon.

For a couple of years now, since Eric first described his ideas, I’ve used my own reset.css. A combination of Eric’s original code and YUI’s more comprehensive styles, modified here and there as needed. It has served well on many projects.

Now that HTML5 is at last upon us, my reset.css no longer quite fits the bill. For one thing, there are new elements that bring with them new default styles, which of course need resetting. For a second, other elements have been deprecated, and so I no longer need to worry about them. (Of course, you might, since your project might be different.) And for a third, and possibly most important, few of the new elements are supported sufficiently by the browsers.

Given all this, I’ve updated my reset stylesheet. It ignores deprecated elements, and gives the new ones display styles as needed. This also is not a self-contained box of resetting, but I do find it quite useful. You can find it on GitHub, along with some additional notes. You’re free to use it as you like. As always, please do let me know if you notice any problems or have any suggestions.

Ashland, Oregon.

I.

Ashland, McCarthy, and the Field Guide.

It’s not yet a new year, but I have a new home, this blog has a new life, and I’ve begun work on a new — though long overdue — project. The project is the realization of Hypsography, my field guide. This blog was given new form based on the beautiful typography of Cities of the Plain. And I’ve moved back across the country, to a valley limited by the Cascade and Siskiyou mountain ranges.

Let’s begin with the mountains. They call this valley the Rogue, but the Rogue River is north of here. The Klamath is to the south. Both rivers run from the Cascades to the Pacific, along vaguely parallel courses. Between the two lies a range of mountains called the Siskiyous, which are the northernmost of the Klamath ranges. The Klamath ranges extend inland from the Coast, covering the territory of what are — to the north and south, that is — the Coast ranges, though they are not two parts of the same system of mountains in geological or historical terms. Just south of here, around the border, the Siskiyous finish their eastern push where they collide with the Cascades. Ashland, the town where I now live, sits in the valley of a creek that flows into the Rogue, just north of that Siskiyou-Cascade intersection.

Hand drawn map of the Siskiyou and Cascade mountains, in Oregon.

And, as you can see, the Hypsometry blog is back, for yet another go round. I’ve lost count of what incarnation this is — perhaps the sixth? The driving force here, this time, is simplicity.

The design was inspired by the gorgeous work done on Cormac McCarthy’s border trilogy; in particular, the title page of the first edition of Cities of the Plain, the concluding volume of the three.

In technical terms also, this site is as simple as it has ever been. Since I began designing and building websites — five years ago now — I’ve worked with a wide array of techniques for producing blogs. None has ever been quite right for my needs, so I’m trying yet another. With luck, this new system will have a little more sticking power. Whether it does or does not, expect my notes on the subject sometime soon.

Hypsography is my newest project, though I’ve been planning it for a couple years now. I have a hard time summarizing exactly what it is that I’m working on, in part because there’s so much to come and — so far — so little to show. I’ve written a few words about it on the site itself. But really, it’d be better if you just took a look yourself.

Excerpt from a pair of photographs published on Hypsography.
Ashland, Oregon.

Nulla.

This article serves an imaginary purpose: Dividing the old Hypsometry from the new. All articles older than this one are on their second or third go round the course; all articles newer are fresh, on their first legs.

Thus, do not take the old ones too seriously. They are preserved here, in internautical amber, for reference, for humor, and to help keep the links alive.

Ashland, Oregon.

-I.

On passwords, forgetfulness, and ease of use.

A problem.

Every site that allows password sign in has a little link on its sign in page. Sometimes it reads as a question: Forgot your password? Sometimes a first person statement: I forgot my password. Sometimes it’s just a terse fragment: Forgot password.

You click it and are taken to another page, where you can ask for a new password to be emailed to you. On the forgot-my-password page you have to enter your email address. Typically the form on that page is extremely simple: Some explanatory text, a text input field, and a submit button.

When the web application receives the submitted form, it checks its database to find the submitted email address. Assuming it finds the address, the application updates the user’s password and emails them a notice about it. If it doesn’t find the address, it returns the user to the same page and complains about the failure.

All of which is simple, straightforward, well established custom. Almost every web application has this feature, and this feature works in almost exactly the same manner across the board.

But there’s one problem here. It’s not uncommon for a user, hoping to sign in to a site, to enter his email address and then realize that he’s forgotten his password. In other words, it’s not uncommon for a user to realize that he’s only got half of the needed data after having already entered the first half.

What happens then? He finds the expected Forgot password link, clicks it, and is whisked off to the forgot-my-password page. And then has to enter his email address again.

This certainly isn’t a large problem. People type their email addresses into forms all day, every day. Lots of people use form managers to do it for them. (Though the form managers probably remember their passwords too, so they’re not in this bind in the first place.) How long does it take? A few seconds, at most. How much trouble is it? Not much.

But why cause your users any trouble at all? Even a little trouble is more than necessary.

A solution.

The solution I’m using on our new site is simple. The short explanation: The forgot-my-password link uses Javascript to grab the value of the email address already entered, then appends it, as a query parameter, to the forgot-my-password URL.

The forgot-my-password link looks like this:

<a href="/account/forgot_password" class="forgot_password">
  Forgot password
</a>

We’ve rolled our own unobtrusive JavaScript library, but it functions in many ways like Dan Webb’s Low Pro. Using that, I registered a behavior handler for the forgot-my-password link:

Event.addBehavior({
  "a.forgot_password":
    Account.Behavior.forgotPasswordBehavior
});

In other words, all links with a class of forgot_password get extended with the behaviors defined in Account.Behavior.forgotPasswordBehavior. That behavior is simple:

Account.Behavior = {
  forgotPasswordBehavior: {
    onclick: function() {
      if ($F("email") != "") {
        this.href = this.href + "?" +
          $("email").serialize();
      }
    }
  }
}

In other words, forgotPasswordBehavior defines an onclick handler that rewrites the relevant element’s href to append whatever the user has entered in the email field. It uses Prototype to get the value of the field and rewrite it in name=value format, so that it can be passed as a URL query parameter. And it only does its work if the user has actually entered something in the email field. No point in adding the useless ?email= to the URL.

Then, in the forgot_password.rhtml view, the email field is generated like this:

<%= form.text_field(:email,
  :value => h(params[:email])) %>

Which generates the appropriate field using the email passed as a URL parameter as its value, if one exists.

Any user who has forgotten his password and wants to request a new one has implicitly declared his desire to use your site, and to use it now. Seems like anything you can do to help him with that is a good thing.

San Francisco, California.

-II.

On hunches, Ruby, Rails, why the lucky stiff, numbers, their absence, the absence of objects, nothingness, and nihilism.

Today I was working on a view helper that creates a link to show a list. Something like the following:

def list_control(options = {})
  options = do_stuff_with_the_parameters(options)
  render(:partial => "link/list_control", :locals => options)
end

One option you can pass in is new_count, which is the number of new items in the list. The new_count parameter, however, is optional, since only some lists care about the newness of their items. If there’s no new_count, then the list control doesn’t talk about it at all. And new_count can, of course, be 0, and when it’s 0 the list control notes that in the title attribute but nowhere else. (So that the information is still there, and you can access it if you care, but it’s invisible most of the time.) Only if new_count exists and is greater than 0 do we display it in the link’s name.

Since Ruby lets you check to see if an object is nil?, or if it’s zero?, or if it’s empty? (Array, Hash, and String, among many others), I figured there’d be some easy way of checking to see if new_count’s either nil or 0.

Well, to save you some Pickaxe thumbing and some Googling, there ain’t.

Way back in 2005, why the lucky stiff suggested that Ruby be extended to include Object#blank?. (The actual Ruby change request has vanished from the RCRchive, so why’s write-up of it seems to be the only extant discussion.) He proposed the following:

class Object
  def blank?
    if respond_to? :empty?
      empty?
    elsif respond_to? :zero?
      zero?
    else
      !self
    end
  end
end

In other words, why’s Object#blank? looks to see if an object can be empty, and if so checks whether it is, in fact, empty. If the object can’t be empty but can be zero, then Object#blank? checks whether it is, in fact, zero. If the object can’t be empty or zero, then Object#blank? returns the negation of the object, which will be true if the object is nil or false, and false otherwise.

In other other words, why’s Object#blank? checks an object for all the ways in which it can be nothing, and returns true if any of them return true.

In other other other words, why’s Object#blank? is exactly what I wanted.

No wonder he said “I use this code in nearly all of my web application projects.”

So I went ahead and used count.blank?, then waited for the tests to start screaming at me. Strangely, they didn’t.

Back to Mister Google. Turns out that the clever buggers on Rails core had already added support for blank?. That’s nice, I thought; they’re a step ahead of me.

So I went ahead and wrote the code that does one thing if new_count doesn’t exist, another if it exists and is 0, and another if it exists and is not 0. And the code failed.

Back to the Rails Trac. Turns out that when the clever buggers on Rails core implemented why’s idea they left out the bit where 0 indicates blankness. empty? means blank, nil means blank, false means blank, but 0 means not blank.

Okay. That’s legitimate. Not what I need, but legitimate.

In the comments on why’s post, people thought of a lot of alternate names for blank?. I thought about it for a second, and realized that nihil? struck my fancy. Thus, Object#nihil?:

class Object
  def nihil?
    if respond_to?(:empty?)
      empty?
    elsif respond_to?(:zero?)
      zero?
    else
      not self
    end
  end
end

I threw it into /lib/nihil.rb and added require 'nihil' to the app’s initializer, and that was that. Onward.

San Francisco, California.

-III.

On repetition, YAML, errors, and yelling.

On our new project we’re relying heavily on YAML. Not for internationalization purposes (though that’s one possible benefit of our approach), but rather to keep things like class names and IDs consistent throughout the various views and controllers, and throughout the HTML, CSS, and Javascript. (More on that later.)

One thing that’s been annoying me, however, is how much I need to repeat myself in the strings.yaml file. For instance, I find myself writing things like:

friends_classname: "friends"
friends_behavior: "friends"
friends_id: "friends"

It turns out that YAML can easily handle this. As the spec puts it:

Repeated nodes are first identified by an anchor (marked with the ampersand – “&”), and are then aliased (referenced with an asterisk – “*”) thereafter.

So the above YAML can be written like this:

friends_classname: &friends "friends"
friends_behavior: *friends
friends_id: *friends

And both will work exactly the same.

I realize, of course, that the second example is actually more verbose than the first. But I’m not trying to avoid repetition to reduce the number of characters used; I’m trying to decrease the likelihood of subtle errors, and thereby decrease the difficulty of debugging.

In the first case, if I made a typo like friends_id: freinds, friends_id would be wrong, and things would fail silently. In the second case, a similar typo, like friends_id: *freinds, would fail completely. YAML will give a BadAlias error, and my app will break, and Rails will yell at me.

I like loud errors: they save time.

San Francisco, California.

-IV.

On Rails defaults, asset timestamping, and debugging dynamically generated Javascript.

Hard to believe I’ve got to write about this again. Remember when I last talked about Rails and caching and asset timestamping? Well, here we are a year and a half later, and there’s more to say.

Working on our new project at Infoteria, we’ve got a lot of Javascript going on. We’re generating some of that dynamically (using ERB templates and some custom fanciness). And, of course, we’re using the unbeatable Firebug JS debugger.

Unfortunately, the default Rails behavior (as described in my earlier article) is to force a crude sort of asset timestamping by appending a query string to each asset’s filename. So every time we make a change to one of these dynamic Javascript files, Rails sees that a change has been made and appends a new query string. Which has the result of making it look like a new file, to the browser and to Firebug. Which, in turn, means that any breakpoints we’ve set in the last version of the file get ignored in the new version. Which makes debugging impossible.

Luckily, Rails has improved since I wrote that earlier article. You can now set RAILS_ASSET_ID to whatever you want, and if you set it to an empty string Rails will not append a query string at all.

In other words, to turn off Rails asset timestamping entirely, add the following to your environment.rb:

ENV["RAILS_ASSET_ID"] = ""

Or put it in the appropriate initializer, if you’re using Rails 2.

PS: I’ve actually got a ton more to say on this subject. The asset timestamping that Rails uses is ineffective, and their newfangled asset caching stuff is inadequate. We did a lot of work coming up with a better solution for Lingr, and we’ve done even more work on our new project. All in all, our current solution is pretty nice, allowing for dynamic CSS and JS generation, mashing up of files, caching, asset timestamping, all with a solid framework that understands quite complex combinations of page location, rendering device, and user status. More on that when I get a chance.

PPS: Apparently I used to spell geez “jeez”. Interesting.

San Francisco, California.

-V.

On WebKit fanciness.

WebKit is kicking ass. It’s getting more use: First the iPhone, and now Android. More attention from the bloggers. Amazing downloadable font support. Futuristic HTML5 features: Clientside database storage, along with a slick query browser, as well as sophisticated media embedding and controlling.

But what’s got me most excited is how the WebKit team is pushing CSS out of its rut. In the past few weeks they’ve implemented a group of related features allowing for powerful CSS-based display manipulation.

Before I get into any details, just take a look at the following examples. (Of course, to see them properly, you’ll need a recent WebKit nightly build.) And be sure you hover over the paragraphs.

Testing this newfangled fanciness.

This one is scaled by 2.

This one is translated by 5em.

This one is rotated by 45°.

This one is skewed by 0, -45°.

In case you can’t see what’s going on here – and you really should check this out; it’s only a download away – all but the first paragraph are transformed, in the manners described. But the best part is that when you hover over a paragraph the transformation is removed, in a 1 second long animation. (The colors reverse too, just for kicks.)

This is accomplished through two extensions to CSS: -webkit-transform and -webkit-transition. The -webkit-transform property allows you to transform your objects, and -webkit-transition allows you to animate any CSS display property. Dave Hyatt described it thus:

The simplest kind of animation that we’ve added support for is called a transition. Normally when the value of a CSS property changes, the rendered result is instantly updated, with the element in question changing immediately from the old property value to the new property value. Transitions describe how to instead execute an animation from the old state to the new state over time.

That’s hot.

-webkit-transform takes a type of transformation – scale, rotate, translate, or skew – and a value, in parentheses. scale takes a unit-less value, like -webkit-transform: scale(2); rotate takes one CSS angle, and skew takes two, like -webkit-transform: rotate(45deg); and translate takes a length or percentage, like -webkit-transform: translate(5em).

(There’s also matrix, which allows you to “specify a full affine transform matrix”, and takes six values. I’ll be damned if I can get it to work though. So perhaps more on that another time.)

-webkit-transition allows you to specify a property, a duration, and a timing function. The property can be none, all, or the name of a specific property, like color, position, or -webkit-transform. The duration is a time in seconds, like 2s. The timing function can be the default, linear, ease-in, ease-out, ease-in-out, or your can specify your own cubic bezier function with cubic-bezier(x1, y1, x2, y2). In the examples above, I’ve specified -webkit-transition: all 1s ease-in-out.

There are clearly some kinks to be worked out. Just in the super simple examples above you can see that I had to set a different opacity value for the translated paragraph, and that the side borders of the rotated paragraph seem to have vanished. But it’s a hell of a start.

And it seems that these simple transforms and transitions are only the first of a range of visual effects that WebKit is adding to CSS. I’m looking forward to seeing what else they implement.

For more information, check out Hyatt’s two posts on Surfing Safari: CSS Transforms and CSS Animation.

San Francisco, California.

-VI.

Rendering a collection of things, and how it can fail.

In Rails you can iterate through a collection of stuff, rendering one partial per thing, using:

render(:partial => 'special_thing',
  :collection => a_bunch_of_things)

Which makes life much easier.

However, it turns out there’s this poorly documented requirement for the collection you pass in: It can’t contain hashes. You’d think – which is to say, I thought – that any enumerable would work just fine, since all Rails is doing is iterating through the collection and rendering the partial once per item.

In fact, if you take a look at the documentation for the Rails partial code, you’ll see that the examples they give clearly imply that using :collection is just shorthand for iterating through an enumerable. (Though the verbose, non-collection example uses for, which probably should be a good enough sign that something’s wrong.)

But there’s a note:

Due to backwards compatibility concerns, the collection can‘t be one of hashes. Normally you‘d also just keep domain objects, like Active Records, in there.

Why not? I'm not sure.

What happens when you try? Funny you should ask. Say you’ve got a collection that looks like:

teams = [
  { :elephant => ryan, :soft_shelled_turtle => mary },
  { :elephant => katherine, :soft_shelled_turtle => jay }
]

And you call:

render(:partial => 'team', :collection => teams)

Rails will iterate through the collection, and for each array in teams it will assume that you want to use the value associated with the key identified by your partial’s name. (And you know what they say about assuming.) In this case, the partial is named team, so Rails will try to render _team.rhtml using teams[0][:team] and teams[1][:team]. And, since the default value of a hash is nil, your partial get passed a series of nils and will probably fail to render. Not exactly what you might hope.

On another hand, if you’re using the same collection but instead call:

render(:partial => 'elephant', :collection => teams)

you might have better luck, since Rails will pass teams[0][:elephant] and teams[1][:elephant] to your partial, and at least those aren’t nil. Though are they what you want? Probably not.

Okay, now that I’ve explained the problem, here’s the good news: This will not be a problem in Rails 2. Ticket #8958 removed the deprecated cruft from ActionView, and, in so doing, freed us up to use collections of hashes in our partial rendering.

Aren’t you excited? Thought so.

San Francisco, California.

-VII.

On browser caching, asset timestamping, and Rails.

On browser caching.

Browsers cache files: Javascript, images, CSS, etc. That’s simple enough, and makes good sense. Why download a file twice when once will do?

Some browsers aren’t very good at it, though. No name calling here, but things don’t always work as they should.

For the most part, that’s not a problem. Asset files are cached precisely because they tend not to change too often. But when they are changing often – during the testing phases of a project – is precisely when you want the fewest unpredictable problems possible, and is precisely when you’re using the older and uglier browsers that have more problems.

So there are ways around the problem. You can force most browsers to reload everything, ignoring what’s in the cache. You can disable the browser’s cache. CamiTools, for Camino, allows you to turn it off; the Web Developer Extension allows you to do the same thing for Firefox, Flock, Mozilla, and SeaMonkey. (An aside: SeaMonkey? When did that happen? Why does Mozilla have so many damn projects? Why do they keep changing names? Jeez. Focus people; come on now.) And so on.

But these are brute-force solutions.

On asset timestamping.

A while back, Tim Lucas released an asset timestamping plugin for Rails that solved this problem.

The way it works is simple: With the plugin installed, every call to generate a path to a static asset returns a path with the modification timestamp of that file appended to it, as a query string.

So, instead of getting back an image tag like

<img src="/images/tim_lucas_rules.gif" alt="" />

you’d get something like

<img src="/images/tim_lucas_rules.gif?1147898838" alt="" />

Which is to say, your <img /> tag is now asking specifically for the version of tim_lucas_rules.gif that was last modified 1147898838 seconds after January 1, 1970.

One important point to note here is that the timestamp query string only changes when the file changes. If that’s the version of the GIF that the browser has in its cache, then great – you get it. If not, then it asks the server for a new copy. Since this behavior is tied to the asset file’s modification time, you’re always guaranteed to get the right version of the file, browser caching problems notwithstanding.

Another important point is that the timestamp query string actually does not affect what file the server serves up. You will always get whatever version of the file is currently available, not matter what. The point of all this is to force the browser to keep up-to-date. (Tim Bray isn’t sure this behavior is appropriate.)

On asset timestamping and Rails.

As of Rails 1.12.1 (or April 6th 2006) Rails now uses this scheme by default. Now, when you call a method that generates a path for a static asset file – like image_tag or stylesheet_path – you’ll get back a path that includes a query string with the asset file’s modification timestamp appended.

The way this works is basically the same as how Tim Lucas’s plugin. compute_public_path – the method that’s called to figure out where an asset file is located – now calls a new method rails_asset_id, once it’s figured out the real path. Then rails_asset_id checks the file’s modification timestamp and returns it to compute_public_path, which appends it as a query string. (All this is documented in the Rails API.)

Simple enough, and good news. Except that hideous URLs are generated.

There’s also a new configuration variable, RAILS_ASSET_ID, that can be added to any of an application’s environment files. If that’s set, the rails_asset_id method returns its value instead of the timestamp. The idea being that you can use that as a version stamp, which might be more useful in some contexts. (And certainly makes for less heinous URLs.)

And, of course, you can also override either rails_asset_id or compute_public_path to provide different behavior. Possibly removing the asset timestamping feature altogether, if you’re wicked keen on clean URLs.

Norwich, Vermont.

-VIII.

Three things about Pivot.

Since last summer I’ve been working with Xenium Group’s excellent PivotCMS. At the time I started using it, my only real CMS experience was with TextPattern – a CMS of a fundamentally different design.

TextPattern is one of the new breed of small CMSes: very dynamic, conditionally structured, blog-oriented (which is to say: chronologically-oriented). Pivot, on the other hand, has been around as long as Blogger, and seemed more static and stodgy, overly concerned with things like security and documents.

In hindsight, I realize that Pivot’s intended audience is not that of TextPattern’s. As Xenium Group puts it: Pivot’s “targeted feature set is not all things to all people.”

Since last summer I’ve continued to build sites with TextPattern and Pivot, and have become quite familiar with ExpressionEngine and Typo. Doing so has made three of Pivot’s best features stand out clearly.

Pivot is a hosted CMS.

Being hosted means no installation, no need to familiarize myself with a client’s hosting arrangement, no need to talk to tech support, no dealing with .htaccess files, et cetera – all of which means less time spent by me and less money spent by my client.

That also means that Xenium Group provides support for Pivot’s operation, as part of the package, which means that my clients don’t have to wait for a hole in my schedule to get help – they can just go straight to the source.

Pivot publishes sites via FTP.

At first I hated this idea: Why not generate the site dynamically? That’s the slick way to do it. Creating the site in one place, then pushing it to another via FTP seemed unnecessarily complicated and needlessly time-consuming.

Now I get it.

When I redesign a site using ExpressionEngine, I build the new version on a staging server of my own. Then, when it comes time to launch, I have to do a multi-part dance:

  1. The customized installation of EE needs to be moved to the client’s server, though without disturbing the old site that’s already in place;
  2. That installation needs to be tweaked to match the client’s server’s setup, which always differs from mine; and
  3. The old site needs to be turned off, and the new site turned on, simultaneously, and without interfering with each other.

That operation can go well, or it can go poorly; but it’s never simple. There’s always too much room for error.

When I redesign a site that uses Pivot, I can mess about with things on the CMS side to my heart’s content. Then, when everything’s ready to go live, I just click the Publish button and the new version gets sent out, via FTP. Simple as can be.

Pivot offers real previews.

Every CMS lets you preview articles; that’s a given. But Pivot’s the only one I’ve seen that lets you see a preview that actually shows what the final web page will look like.

Again, this is because Pivot is hosted and publishes its sites statically, via FTP. When you’re working with Pivot, you’re working on a Xenium Group server. You make changes to a document and click Preview, and Pivot generates a new version of that document from the appropriate templates, including all images and stylesheets, and serves it up for your previewing pleasure.

Makes sense, right? On the other small CMSes I have to jump through hoops to accomplish the same thing.

In conclusion.

Pivot isn’t right for every project, but then it isn’t meant to be. For sites that are suited for Pivot, it offers a solid array of features, plus a few stand-outs. It’s worth a look.

Norwich, Vermont.

-IX.

A brief parable.

On Matt Bucy’s recommendation, I’ve been reading Jonathan Hale’s The Old Way of Seeing. Which is excellent.

In a chapter on paradigms, he points out that in the early 1930s the shape of cars changed radically:

In Raymond Loewy’s 1933 illustration of car evolution, it seemed almost as if the previous concepts had been peeled away to reveal the obvious fact of the modern car. [..] In cars, elements that had formerly been discrete – headlights, fenders, grilles – were absorbed into the overall shape. Function was not the motive; the newly integrated body panels and fenders and headlights were actually more difficult to repair. [..] Looks were the point.

So that’s what we’re left with: Cars whose structure has been designed to facilitate style, but whose style has been forgotten. Cars where one type of quality – ease of repair, longevity, efficiency, strength, stability – has been traded for another – superficial beauty, changing fashion – but the latter has failed, and we’re left with neither.