Using HTML Attributes in Generated Content

Generated content using CSS (i.e.: inserting a colon after each label element) can be a great way to ensure that content appears no matter what has been put in the container. However, when dealing with certain types of content and internationalization, this approach is quickly scrapped for a server-side insertion of the content. There may also be cases when you want to access and modify the generated content with Javascript, but cannot figure out an easy way to and, again, scrap the generated content in CSS in favor of generation in Javascript. There is a little known and used way, however, of controlling your generated content from HTML and Javascript.

The W3C spec on generated content, like all other W3C recommendation documents, is a wealth of information provided you don’t fall asleep reading it. I tend to check it every so often when working in CSS to see if there is some easier or more interesting way of doing something I’ve been doing all along. It’s never the easiest reference to learn from, and often has terrible examples, but it will at least get you searching for a better explanation of a particular property or value.

The spec on generated content describes a function you can call within CSS called attr() that, when passed an attribute name, will check the currently scoped element for said attribute and, if it exists, will grab its value and place it in the value of the content property. Using this method, we can set a data attribute to our generated content within HTML or Javascript. You can check out a quick example.

There is also a W3C draft for CSS3 values and units that describes using the attr function for a number of other properties, although currently they’re not supported in any major browser. However, it is exciting to think that one day we’ll be changing background colors of before and after pseudo-elements by simply changing an attribute on its parent.

jQuery RememberState Version 1.1 Released

After seeing a fair amount of traffic on my previous post for my jQuery localStorage plugin I figured I should update it to make it a little easier to use. The rememberState plugin now has options for the localStorage object name, clearing the storage on submit, the ability to send a custom notice block, and a notice selector in the event the notice element already exists in the form. For more info, check out the readme at the plugin’s GitHub page or try the demo form.

Planned future additions include being able to exclude form fields or field types. Let me know if you think it could use anything else.

Making CSS Content Properties Dynamic

One of the obvious issues with text content added to the page via CSS is that it is content stored in the visual presentation layer rather than the content (HTML) layer of the document. Because of this, whenever you need to update this content, you need to change the value of the content property in the CSS file. This is even more of an issue when thinking about internationalization and having to translate the generated content across different languages. Previously to achieve this, you’d have to have override stylesheets for each language and again hard-code the content to be output.

As of CSS3, however, you can generate the content from reading in the value assigned to any attribute on the HTML element that is receiving the generated pseudo-element. This means that not only are you able to keep the content in the right place, but you can change it based on region. Even better, it’s exceedingly easy to change the content using DOM scripting. All you need to do is call the attr() function as the value of the content property, like this:

p:after {
  content: attr(data-after_content); }

On your paragraph element, just add the data-after_content attribute and give it whatever content you’d like output in the after pseudo-element.

When using the content property, though, keep in mind that the content will not be read by search engines or screen readers. Any essential content should still be part of the text content of the page.

A Sass Mixin for Cross-Browser CSS Background Gradients

Yesterday at work, I was referencing the Mozilla article on gradients and noticed a link to Microsoft’s developer docs, mentioning there was a way to do linear gradients with IE as well. I was a bit excited to think that I would no longer have to look at our client projects in IE and think how plain they look. At Hashrocket, we code CSS with graceful degradation in mind. Generally, that means that if there are rounded corners, box shadows or background gradients, we use CSS to create these effects. In particular, that means that the fancy buttons that our designers come up with look like solid color rectangles, possibly with a rectangular border around them. They function fine, but look terrible compared to  what you’re used to looking at by the time you browser test.

I got to thinking about how IE has implemented Web technology advancements first before, but generally they’ve been unused and overlooked. A good example is font-face embedding. I remember being able to do this when I first started into working on the Web, but quickly abandoned it because it didn’t work in the up-and-coming browser, Firefox. You could also change image transparency and style scrollbars, a la MySpace customizations, but those aren’t really good examples.

It turns out that gradients are as old as the formerly mentioned tricks, so I’m thinking nearly 100% of your IE audience will be able to see these gradients (support begins at version 5.5). There are a few limitations, however. First, you can only paint gradients horizontally or vertically. I haven’t looked into it yet, but I think that you can paint them in either direction across each axis by setting the writing mode. In almost every case, though, you won’t want to change that because you’ll have text within the container you’re setting it on. Second, there are no color stops, simply an even linear gradient from one edge to the other; from one color to the other. From what I’ve coded recently, though, this technique covers most of the times I’m adding a background gradient, and the times I’m doing something different aren’t going to detract from the design as significantly if they’re not present.

Before getting into the Sass mixin, here’s an example of the code that makes this gradient possible:

filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#ffffff, endColorstr=#ececec)

The first argument to the gradient method is the type. This is a misnomer, as the “type” is linear in either setting. Instead, it affects the direction. 0 is vertical and 1 is horizontal. startColorstr and endColorstr are self-explanatory, although there’s a little added functionality that may come in handy. You can give each an 8 digit hex value rather than 6 to adjust the alpha channel. Why this is represented in a scale from 0 to 255 is beyond me, but at least you have a way of doing so. The weird thing about it is that these two digits come at the beginning of the number, so if we were to rewrite the hex values to include alpha they would look like #ffffffff and #ffececec. This isn’t at all helpful in our mixin as you’ll soon see, but you could still use this without a mixin. There’s also an argument called “enabled” that is optionally your first argument. This defaults to true, but setting it to false causes the gradient to not be painted. This is really only useful for DOM scripting, so I’ll leave you to read up on that if necessary at the MSDN reference.

Now that we know how the MS gradients work, we can build a cross-browser compatible linear gradient mixin in Sass. If you’re unfamiliar with Sass and/or mixins, check out their site for a quick demo and reference. It’s an amazing CSS extension that I can no longer work without. If you look at its examples and don’t understand why, then you’ll want to bookmark it and come back in a few months after you’ve got more CSS experience. Hashrocket prefers the older Sass syntax rather than the Scss syntax, so I’ll show you that particular syntax. You can easily change it to fit the new syntax if that’s what you’re into. Since we support all major desktop browsers from IE7 and up (note: Opera is not supported), we’ll add in the Mozilla and Webkit CSS properties, like so:

= gradient-bg($color1, $color2)
  background-color: $color1
  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#{$color1}, endColorstr=#{$color2})
  background-image: -moz-linear-gradient(center top, $color1, $color2)
  background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from($color1), to($color2))

This mixin covers any case when we want to paint a linear gradient from top to bottom, starting with color 1 and ending with color 2. The first color is set as the background color for those browsers without gradient support. Next, we set IE’s property. One important thing to note is the use of string interpolation. I’m not quite certain why putting the variables on their own in this code doesn’t work, but I’m thinking it has to do with Sass parsing the property incorrectly because of the second colon after progid. Then we have the Mozilla and Webkit vendor-prefixed properties that look relatively similar. You’d then use this mixin in your sass like so:

#container
  +gradient-bg(#ffffff, #ececec)

And there you have it! A great way to use relatively new technology without having to remember all these different syntaxes. You get the added benefit of being able to quickly change the syntax if the browser vendors change it or remove the vendor prefixed properties in favor of a supported native CSS property. You could just as easily make a horizontal gradient mixin as well by modifying the direction each property paints.

Pure CSS Isometric Bar Chart

Earlier this week, I was given a design to cut up that included an isometric bar chart (or is it graph?). When the design was in process, one of our developers saw it and thought it wouldn’t be possible in CSS alone like the other charts we have done for the same project. Myself and Cameron, one of Hashrocket’s designers, took that as a challenge and came up with a way to create it. As a disclaimer, though, this is not how I would prefer to visualize this manner of data. You’ll see why shortly.

First off, here’s a screenshot of the design I’m talking about:

Example design of an isometric bar graph

As you can see, the labels are listed from bottom up, and opposite the usual direction you would see the data ordered if you had just spit out a list in HTML. There’s tricky ways of reversing the order with CSS, but it’s incredibly brittle and requires specific CSS for each bar. With the data set we were using, this wasn’t a problem since it made as much sense going in the other direction.

The problem I have with coding a chart in this way is that you can’t just measure heights in percentages; you have to convert them to pixel heights. This means that you can’t just change the dimensions of the container and have the bars resize to match. To make a large version of this chart, you’d have to cut a larger background image as well as adjust a number of pixel dimensions.

The first step is to determine how the HTML will be structured. I went with an article containing an unordered list because of the fact that they were listed in reverse, and didn’t want to put a reverse order on them improperly. I added the bar containers as divs and the labels as paragraphs. Our basic HTML for this graph looks like this:

  <article>
    <ul>
      <li>
        <div class=”bar”>100%</div>
        <p>August</p>
      </li>
      <li>
        <div class=”bar”>55%</div>
        <p>July</p>
      </li>
      …
    </ul>
  </article>

If you’ve created CSS charts before, this should look familiar. If this were a flat bar chart, the bar divs would have a width or height of the same percentage depending on whether the chart’s orientation is vertical or horizontal. I won’t get in to detail on how those types of charts are marked up, but if you want a good example, check out the A List Apart article on the subject.

Focusing on the bars themselves, we have what looks like three parts to them: the top, repeating middle, and bottom. However, to make sure our bar works even if it is a height of 0, we need to use two parts. If we used three, the top and bottom pieces would be a fixed height, and would end up overlapping and ruining the illusion if the size of the bar was too small. Since we’re only using two elements, we need two background images. The first is just the top diamond, the second is the bar with the bottom. If you’re familiar with the sliding doors technique, you’ll see where I’m going with this. I cut the bar image with the bottom at a height greater than the maximum height of each bar, ensuring that there’s always enough background to cover the bar. The addition of the top element is simple enough. I added a top div within the bars and wrapped the measurement in a paragraph, so the bar HTML now looks like this:

  <div class=”bar”>
    <div class=”top”></div>
    <p>100%</p>
  </div>

You could substitute adding the top div with an :after pseudo-element, but I was coding this to provide the same visual in IE7 and :after isn’t going to work.

Now it’s down to the fun stuff. To start, I’ve set the maximum height of each bar to be 150px. Since the top piece is a height of 35px and we want to ensure it’s always visible, the minimum  height cannot be less than 17px. This will become evident once you see the way the top piece is positioned. With this in mind, to have a maximum height of 150px you need to add 17px to the calculated height, making the actual height measurement 167px. For example, if our bar is 87% of the total, you would take the decimal representation of the percentage (.87) and calculate the height like this:

  <div class=”bar” style=”height: #{.87 * 150 + 17}px”>

Styling the CSS bars involves positioning the bar from the bottom of the list item, and letting it expand upwards. We also need to position it off the left edge of the list item by half of the width of the bar to prevent the list item’s background color from bleeding through to the left half of the base. The top element is positioned relatively within the bar, poking out above it by half the height of the top piece. In this case, it’s 17px. You then have the CSS for your bar! The hardest part is over.

article li .bar {
  position: absolute;
  left: -30px;
  bottom: 0;
  z-index: 1;
  width: 60px;
  background: transparent url(“bg_iso-graph_bottom.png”) 0 100% no-repeat; }

  article li .bar .top {
    position: relative;
    top: -18px;
    height: 35px;
    background: transparent url(“bg_iso-graph_top.png”) 0 0 no-repeat; }

Now to style the list items. This is pretty straightforward with the exception of the fact that each needs a fixed width in order to position the bars while also preventing the background color from bleeding through to the left half of the bottom of each bar. For the demo, I used :nth-of-type pseudo-classes to add a fixed width to each list item, but if you’re going to support most modern browsers you’ll probably need classes to do this.

article li {
  position: relative;
  clear: both;
  float: right;
  padding: 2px 20px 2px 0;
  margin: 0 0 2px 0;
  text-align: right;
  text-transform: uppercase;
  list-style: none;
  text-shadow: 0 1px 1px rgba(0, 0, 0, .2);
  background: #888888; }

article li:nth-of-type(1) { width: 149px; }
article li:nth-of-type(2) { width: 183px; }
article li:nth-of-type(3) { width: 217px; }
article li:nth-of-type(4) { width: 251px; }
article li:nth-of-type(5) { width: 285px; }
article li:nth-of-type(6) { width: 319px; }
article li:nth-of-type(7) { width: 353px; }
article li:nth-of-type(8) { width: 387px; }

If you’re using SASS to generate your CSS, you can use a loop to spit these widths out, but that’s beyond the scope of this article. If you’re interested, the SASS reference has a thorough explanation of how to do this.

The last bit is optional, but I think it adds a nice finishing touch. Remember the paragraph containing the measurement of each bar? Normally, you’d just hide that and have it around for accessibility’s sake, but why not display it when you mouse over the bar? A quick positioning of the paragraphs and hiding them initially will do the trick.

article li .bar p {
  display: none;
  position: absolute;
  left: 110%;
  bottom: 2px;
  z-index: 2;
  text-align: left; }

article li .bar:hover p { display: block; }

Other than some padding and margin resets, that’s all you need to make this style of isometric graph. You can check out the finished product here. Some suggestions on customizing it would be to adjust the sizes, use different colors for each bar, have more than one bar per item for a stacked bar chart, or even write some JavaScript to pull out the percentage values and translate that to each bar’s height.

Saving Form State with jQuery and localStorage

Recently I was working on a project that had a lot of forms each with a large number of inputs, and I was thinking how frustrated a user must feel when they’ve filled out some of a form and for whatever reason they lose that filled in data. Maybe they accidentally clicked a link in the sidebar, or closed the tab, or Firefox died for the twentieth time that day. Whatever the reason, the user then has to navigate back to that page and re-enter the information. I wondered if there was a solution for this using Javascript, and thought localStorage would be a good candidate. Most modern browsers now have a localStorage object, so unless your users are using an old version of Firefox or using IE7, they should all have support for it.

The idea I had involves using jQuery to attach an unload event to the window and store the targeted form’s contents in a JSON object. If you don’t know how localStorage works, check out this article on the Mozilla Developer blog about how it works and its major shortcomings. In short, the only type you can store and retrieve is a string, which doesn’t make a whole lot of sense. That means that integers, floats, regexps, arrays, and objects need some pre-treatment before being stored in localStorage. In the instance of my plugin idea, ideally I would serialize the form and save it to localStorage. To do this, we can use the built in JSON.stringify and JSON.parse methods to convert the serialized object to a string and save it as a localStorage property, then convert it back to an object in order to loop through it. The only gotcha is when you want to store a function expression, you’re (almost) out of luck. JSON.stringify will strip them out, presumably because of potential security issues with parsing the then-stringified Javascript code. But in this context, we’re not doing anything of the sort so we’re good.

I put together a quick plugin that will store this information under whatever property name you give, or if none is given, by the form’s ID. I’ve tested it to work with the most common input types, but have not tested types such as file, range, number, etc. Most of the HTML5 input types should work fine, but for now I’ll only guarantee that it will work with text, hidden, checkbox, radio, select, and textarea form fields. I’ve also written it to prompt the user before it fills in the saved data, so if multiple people are using the same computer or if you really did intend to destroy the partially filled form, you don’t have to restore the form’s state.

You can check out a demo page, download the uncompressed source or grab a packed version for use on your own forms. You can also grab the uncompressed source along with the qUnit tests on GitHub.

When You Should Use jQuery’s Live and Delegate Methods

Recently, I was working on a project at Hashrocket that involved many different types of elements being introduced into the DOM after it was loaded, and most of those elements needed Javascript events to be attached to them when they were written. Since the release of jQuery version 1.3, everyone has heard of and used the .live() method for attaching these elements whenever possible. Live works great if you’re attaching behavior to an element that may show up pretty much anywhere in the DOM tree. However, most times the events being attached are for an element that only appears within a certain context.

"Well, hey, since these list items are only going to need this click event attached if they show up in my #xmas_list ul, why not reduce the scope by using a selector like $(‘#xmas_list li’)? That will speed things up, right?"

Well, that’s better. But reading through the API docs on .live(), we see this:

The handler passed to .live() is never bound to an element; instead, .live() binds a special handler to the root of the DOM tree.

Oh my. So when you write a live event binding like $(“a[rel=external]”).live(newWindow), you’re really attaching an event to the document and triggering this event when the element’s event “bubbles up” the DOM tree to the document. So here’s the basics of what transpires when this link is clicked:

  1. User clicks the link
  2. The click event fires on any parent elements and parents of those elements until we finally arrive at…
  3. the document. An event attached to the document that fires whenever a click event occurs (even on elements that do not fit the live binding selector criteria), a function is called that tests the event’s current target to see if it matches a selector that jQuery is currently keeping track of with a live event binding.
  4. If a match is found, the corresponding event is called with that element as its context.

Wow. Every click event that bubbles up to the document gets checked? That seems a bit inefficient. Even with the id prepended to the selector chain, this process occurs. How do we get the intended behavior of only listening up to a specified parent node instead? Depending on the version of jQuery you’re using, there’s one or two ways.

The first, which works in version 1.3 and later, is the .delegate() method. This allows you to start at a certain context and live bind events to any newly introduced descendants to that context. The syntax is very similar, with only a minor change to where the target element is specified. Following our Xmas list example, here’s how we’d bind a click event on any list items within it:

$(“ul#xmas_list”).delegate(“li”, “click”, function() { /* do stuff */ });

This ensures that the listener created to check whether or not a list item within the Xmas list was clicked bubbles up only to the Xmas list ul, and not all the way out to the document. A far more efficient way to “live bind” events.

The other way, which I think may be counter to the way many are used to reading jQuery selectors, is calling .live() with the specified context. According to the documentation, this method of passing in a context works with version 1.4 and later. Here’s what the same event binding method would look like using .live() instead:

$(“li”, $(“ul#xmas_list”)[0]).live(“click”, function() { /* do stuff */ });

For those who are wondering what the [0] is for after the Xmas list selector, this is referencing an individual DOM element rather than a jQuery object (or collection of objects). This means that if you had more than one Xmas list on a page (using a class selector in that instance, of course), you would have to switch back to the delegate syntax of live binding anyways. Personally, I think the selector reads wrong, since jQuery selectors are supposed to mimic the way CSS selector chains work. In CSS, you wouldn’t write “li, ul#xmas_list” to style any lis in that particular ul. You’d go from the outside in. Delegate has the same feel.

Now if anyone’s really interested in how .delegate() works under the hood, a great resource to check out is jQuery Deconstructed. Any time you want to see the underlying Javascript behind the methods and properties in jQuery, check out this resource. The specific area we’re going to look at is the delegate function. Expand that accordion and you’ll see this:

delegate: function( selector, types, data, fn ) {
    return this.live( types, data, fn, selector );
},

What this shows us is that the .live() method is doing the work all along! In fact, if you check out other jQuery methods like .first() and .size(), you’ll see that many methods are either simple aliases or alternate method calls with additional parameters sent in (see: .detach()). What they are there for is to improve readability. If someone new to jQuery saw .first() being called on a set of elements, it would be pretty obvious what the return would be. However, seeing .eq(0) might not be as apparent.

So when you’re writing your live events using jQuery, always think about whether you should specify a context or not. In theory, your page interactions will be a little bit snappier, especially when you have a large amount of event-driven code.