Tag Archive for 'web development'

Ragged CSS: makes life easier

The web community is generally coming (or has come) to accept that ’semantic’ class naming conventions (’old school’ elements with classes describing content not appearance) are preferable to the 'boldGreyLink' type conventions popular around the millennium.

Millenium era HTML & CSS ‘Semantic’ era HTML & CSS
<html>
<head>
<title>'Millenium' era</title>
<style type="text/css">
div.redSubHead {
  color: red;
}
p.greyText {
  color: #666;
}
td.columnHeaderCell {
  font-weight: bold;
}
td.oddRowCell {
  background: #eee;
}
td.evenRowCell {
  background: #ddd;
}
</style>
</head>
<body>

  <div class="redSub">sub 1</div>
  <p class="greyText">blah</p>
  <table>

    <tr>
      <td class="colHeader">A</td>
      <td class="colHeader">B</td>
    </tr>

    <tr>
      <td class="oddRow">1</td>
      <td class="oddRow">2</td>
    </tr>
    <tr>
      <td class="evenRow">3</td>
      <td class="evenRow">4</td>
    </tr>
  </table>

</body>
</html>
<html>
<head>
<title>'Semantic' era</title>
<style type="text/css">
.section h2 {
  color: red;
}
.section p {
  color: #666;
}
.section thead th {
  font-weight: bold;
}
.section td {
  background: #ddd;
}
.section tr.odd td  {
  background: #eee;
}
</style>
</head>
<body>
  <div class="section">
    <h2>sub 1</h2>
    <p>blah</p>
    <table>
      <thead>
        <tr>
          <th>A</th>
          <th>B</th>
        </tr>
      </thead>
      <tr class="odd">
        <td>1</td>
        <td>2</td>
      </tr>
      <tr>
        <td>3</td>
        <td>4</td>
      </tr>
    </table>
  </div>
</body>
</html>
  1. document structure inferred
  2. classes describe appearance (volatile)
  3. direct class application bloats html
  4. changing style properties causes headaches (change all instance names or they’ll be out of sync with appearance).
  1. document structure inherent
  2. classes describe content (stable)
  3. ‘container’ classes give context to descendants
  4. appearance (volatile) is abstracted from structure (stable). Redesign is anticipated & therefore easier

One pillar of the ’semantic’ technique is the sparing application of class attributes, primarily to container elements. Elements are ‘caught’ using CSS ‘descendant’ selectors (multi-part) which target hierarchies rather than using simple class selectors which require a directly applied class attribute. Using descendant selectors respects the hierarchical nature of the DOM but makes writing bulk CSS quite tricky. Why? Mainly because CSS stylesheets (and style blocks) are fundamentally rule lists, but the DOM elements which our descendent selectors target are obviously trees. How do we bridge the gap between these fundamentally different structures?

Enter ‘ragged’ CSS

In 2006 I (then a contracting developer) found myself filling the shoes of a fantastic design contractor whose contract was up but sadly not extended (project managers eternally underfund and misunderstand UI). I was the new ‘CSS guy’ for a project with scores of developers, hundreds of pages and crippling compatibility/accessibility requirements. I wasn’t really qualified for the task, but my predecessor gave me a CSS tip that got me through: “don’t sweat the properties, focus on rule hierarchies”.

This rule-centric approach is most clearly evident in the CSS formatting style I picked up on that project and used ever since; a style I call ‘Ragged CSS‘.

‘tall’ CSS ‘ragged’ CSS
.section h2 {
  color: red;
}
.section p {
  color: #666;
}
.section thead th {
  font-weight: bold;
}
.section td {
  background: #ddd;
}
.section tr.odd td  {
  background: #eee;
}
.section { }
  .section h2 { color: red; }
  .section p { color: #666; }
  .section table { }
    .section thead th { font-weight: bold; }
    .section td { background: #ddd; }
      .section tr.odd td { background: #eee; }

It differs from the common ‘tall’ CSS formatting style in only a few (primarily cosmetic) ways:

  1. One line per rule, one rule per lineThere may be hundreds of rules, but each will only have a handful of properties.
  2. Indent CSS rules to represent target element hierarchyA block of markup (e.g. a calendar) will typically involve several rules (perhaps dozens). Indenting rules more clearly indicates how their properties will cascade.

  3. Make rules for ‘landmark’ elements (empty rules if necessary)Adding an empty rule for element’s whose classes are used in subsequent selectors makes indentation hierarchy far clearer (improves readability).
  4. ‘namespace’ your rules to avoid conflictClass names may be repeated on large projects unintentionally. Target ‘abc’ class elements inside ‘xyz’ class elements using a ‘.xyz .abc’ selector rather than a global ‘.abc’ selector to avoid tainting someone else’s unrelated ‘abc’ class.
  5. Avoid element prefixes sparingly in your selectorsDon’t use a 'span.content' selector where a plain '.content' selector will do. Dogmatic prefixing (i.e. increasing specificity unnecessarily) makes your rules unnecessarily vulnerable to otherwise inconsequential markup changes (changing the span to a div for instance).

I’ve been using this formatting style for a few years now and it’s made complex CSS development a snap (browser quirks aside). If you’re writing ‘tall’ CSS (or using a tool which generates it), give ragged CSS a go on your next project. Your future self (and/or your successor) will thank you for it!

dpreview.com lens review widget sallies forth

Today’s a big day at dpreview.com as it sees the launch of the first dpreview.com lens reviews. I’m excited as it also sees the launch of my latest and greatest project, the humbly-titled lens review widget (or see it embedded in a lens review).

Screen shot of the lens review widget in sharpness mode

The lens review widget is a flash component embedded into our lens reviews responsible for presenting the results of our studio tests. The challenge of the project is that the lens review studio test output is intricate, multi-dimensional and in acute danger of misinterpretation.

The widget’s goal is to provide users with a constructive mental model of this dataset and an intuitive/responsive/encouraging interface with which to navigate it.

The broad data categories initially displayed are:

  • sharpness demonstrationSharpness is the top of the list for most lens geeks. Not all lenses are created equal, especially considering the difference in the ’sharpness’ of the image they produce. A single lens can vary greatly between different focal length/aperture combinations and even varies (non-linearly) from centre to corner within a single shot!
  • chromatic aberration demonstrationChromatic aberration is the colour ‘fringing’ you see around light-on-dark or dark-on-light objects in your photographs. Generally purple or green (but occasionally blue/yellow) this effect varies with focal length/aperture and distance from centre.
  • distortion demonstrationDistortion is what causes real world straight lines to appear curved in your photographs. Zoom lenses in particular are prone to distorting ‘inwards’ (pincushion) at one extreme and ‘outwards’ (barrel) at the other. Distortion varies by focal length.
  • falloff demonstrationFalloff is the phenomenon whereby the corners of the frame appear ‘darker’ than the centre (i.e. the light ‘falls off’ from centre to edge). Though often used as an intentional effect, falloff is generally avoided if possible and varies with focal length, aperture and obviously, distance from centre.

In practice these 4 effects are all present (to some extent) in every shot you take, so representing their individual effects is more complicated than simply displaying the raw images (which we also do).

Designing the user interface

With so much data to navigate and several dimensions to deal with (angle from centre, distance from centre, focal length and aperture) the process of designing a useful and intuitive UI was difficult. Eventually a standard hierarchy emerged:

  1. Lens review. It may seem the obvious choice, but I’ve included it on this list as (if allowed in configuration) the user is able to change the review data being viewed within the widget.
  2. Visualization. Sharpness & Chromatic Aberration, Distortion or Fall-off.
  3. Focal Length. Or ‘zoom’ to non-photographers, is generally marked on lenses in arbitrary integer values (generally 4 - 7 per lens).
  4. Aperture. The variable size of the ‘hole’ which regulates the amount of light entering the camera body. Stated in f numbers, an approximately logarithmic semi-standardized decimal value. The aperture values available for a lens depend on the focal length chosen.
  5. Comparison lens review. Users reading reviews are constantly making comparative decisions, so the widget allows users to compare two lens reviews (or two data-points within the same review) cheek-by-jowl, hopefully improving comprehension. Of course, this requires user interface chrome to allow the user to choose.

picker picker controlThere was much internal debate (which still rages) about this UI element which allows users to change/compare reviews, but the eventual decision was to filter reviews by system, lens and finally camera body. Note: Our lens tests are performed on a camera body (instead of an optical test bench) which has relevance upon the results.

The ’slider’

The real challenge from a UI perspective was creating a UI element which allowed users to change focal length / aperture in an intuitive way, was brand-neutral and could cope with the intricacies of the focal length /aperture systems and their inter-relationship. After initially experimenting with flash’s slider component, I decided to abandon it and start from scratch (before you shout Not Invented Here, be aware that flash’s slider is a major usability dud).

GrabSlider demo animation

Trim

Some neat little features that I pushed into the widget (usually late at night):

  • Full screen mode: At any time a user can click the full screen button at the bottom of the widget to view in a new window/tab (selected reviews, visualization, focal length & aperture are retained).
  • Permalinking: At any point, users can obtain a permalink to the current state of the widget to bookmark and/or link to (again the selected reviews, visualization, focal length & aperture are retained).
  • Keyboard controls: A bit of a power-user feature requested by the guys in the office, the keyboard arrow keys can be used to control focal length and aperture. If multiple reviews are visible, they will all receive the inputs, allowing users to change the visualizations in unison (not currently possible via the sliders).

Though a few minor issues persist, I’m very happy with the current implementation. I feel it strikes the right balance between aesthetics, usability, accuracy, brand-neutrality and ‘fun’.

Time (and the forums) will ultimately tell.

I’ve joined the dpreview.com team

I’ve had a quiet blogging spell lately due to the general upheaval of changing jobs, countries and continents.

jaysen dpreview & amazon

I’ve said goodbye to the consulting world and taken a position working with the gang at dpreview.com as a full-time public-facing web-developer. It’s a huge, popular and well-established site (at 9 years old it can be considered the gray lady of digital photography) recently acquired by amazon. I now find myself working in central London (frequently cursing the tube) with a young and enthusiastic team covering an equally dynamic industry.

Note: I’m retiring my rule regarding blogging about my day-job, mainly because my role has changed (more public development) and I’m keen to get more involved in the development community.

With so much going on in digital photography and the web-savvy nature of our readership, there’s plenty of exciting stuff we can (and will) do. Some of the smaller stuff I’ve been working on has already started to appear on the site, more details to follow.

QuintonMarais.com launched tonight

After several weeks’ work, quintonmarais.com launched this evening.

Hi-lights include

  1. .Net 1.1 to .Net 2.0 upgrade (long live the MasterPage)
  2. Amazon S3 for all image storage (dramatically reduced bandwidth and hosting costs)
  3. Google map-based location search.
  4. Creation of “Pusher”, a fire-and-forget image watermarking, batch uploading and data-entry smart client app (to create the 12+ thumbnail and preview versions of each image).
  5. Creation of “S3 Viewer”, a smart client app for viewing/maintaining the thousands of S3 items and buckets which support the site.
  6. ‘New Images’ atom feed (surprisingly easy to get going).
  7. SQL Server 2000 to SQL Server 2005 upgrade (Common Table Expressions are the goods).
  8. GeoRSS feed to (hopefully) ensure photographs appear in search results as geo-tagged objects.
  9. Tag-clouds for hierarchical image categories.
  10. Colour search (still beta, currently rewriting the search algorithm to favour colour coverage rather than colour fidelity).
  11. Cleaner UI design.
  12. Xhtml transitional doc type with vastly improved markup validity (flash still causing some issues here). Some tables remain, to be slowly phased out when I have time.
  13. Flash 9 homepage scroller (flash cs3 didn’t play nice with my old flash 6 swfs).
  14. Self installed and configured SSL.
  15. New hosting provider (discountasp.net, very impressed so far)

All told the upgrade took about 3 months’ worth of train trips, nights and weekends (around my day job). It’s meant an overall reduction in sleep, but ultimately worth it. Now I have just to force myself to stop tinkering with it.