Monthly Archives: March 2007

Form field hints with CSS and JavaScript

My co-workers pointed out a nice effect on the Vox registration form. As you tab through each input field, some helper text appears in box out to the right. Try it out. Update (4/20/2007): It has been pointed out that Vox has changed their form, and it no longer uses this effect.

Vox Registration Form
Vox Registration Form

It’s a basic example of how helpful a little JavaScript and CSS can be in a form. Instead of the input hints always showing and potentionally cluttering a very simple form, only the hint for the currently focused input will show. This article will show a way to do this.

The HTML

We’ll start with a simple form. Vox’s form used a definition list to mark up the form, and I’ll be doing the same. I place the label in the <dt> tag, and the field in the <dd> tag, like so:

<dl>
  <dt>
    <label for="firstname">First Name:</label>
  </dt>
  <dd>
    <input
      name="firstname"
      id="firstname"
      type="text" />
  </dd>
  ...
  more <dt>'s and <dd>'s
  ...
</dl>

Immediately after each input field, add a span with a class of hint and create a hint for each input, like so:

<dl>
  <dt>
    <label for="firstname">First Name:</label>
  </dt>
  <dd>
    <input
      name="firstname"
      id="firstname"
      type="text" />
    <span class="hint">Use your real name!</span>
  </dd>
  ...
  more <dt>'s and <dd>'s
  ...
</dl>

View what we have so far – an unstyled form.

Some CSS

Let’s give this form some style. Assign our form-encompassing <dl> a fixed width and a position of relative. (This is important because our hints will be absolutely positioned relative to the containing <dl> rather than the <body>). Additionally, we’ll style the <dt> and <dd> so that the form takes some shape.

 
dl {
  position: relative;
  width: 350px;
}
dt {
  clear: both;
  float:left;
  width: 130px;
  padding: 4px 0 2px 0;
  text-align: left;
}
dd {
  float: left;
  width: 200px;
  margin: 0 0 8px 0;
  padding-left: 6px;
}

It’s coming along. It’s time to style the hints. Let’s add the following to the CSS.

.hint {
  position: absolute;
  right: -250px;
  width: 200px;
  margin-top: -4px;
  border: 1px solid #c93;
  padding: 10px 12px;
  background-color: #ffc;
}

See how it looks. All the hints are absolutely positioned, and their padding and containing content cause each of them to overlap a little. That’s ok, because we’ll only be showing one at a time. Add “display:none;” to the CSS.

.hint {
  display:none;
  position: absolute;
  right: -250px;
  width: 200px;
  margin-top: -4px;
  border: 1px solid #c93;
  padding: 10px 12px;
  background-color: #ffc;
}

Now that our form is styled and our hints are hidden, it’s time for JavaScript.

The JavaScript

I am going to prepare the input fields so that as focus is put on them, their corresponding hint appears. I do this preparation on page load, using “addLoadEvent”, because that’s how I roll.

function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      oldonload();
      func();
    }
  }
}
 
function prepareInputsForHints() {
  var inputs = document.getElementsByTagName("input");
  for (var i=0; i<inputs.length; i++){
    inputs[i].onfocus = function () {
      this.parentNode.getElementsByTagName("span")[0].style.display = "inline";
    }
    inputs[i].onblur = function () {
      this.parentNode.getElementsByTagName("span")[0].style.display = "none";
    }
  }
}
addLoadEvent(prepareInputsForHints);

The function prepareInputsForHints looks for all <input> tags and cycles through them. When there is focus on that input field, we grab the first span tag in the <dd> in which the <input> resides, and we change it’s display to inline so that it’ll show up.

To keep things simple, I’ve assumed that there is only one <span> tag next to each <input> tag.

What about <select>‘s? We need to duplicate the logic we applied to the <input>‘s so that it will work with <select>’s, too.

function prepareInputsForHints() {
  var inputs = document.getElementsByTagName("input");
  for (var i=0; i<inputs.length; i++){
    inputs[i].onfocus = function () {
      this.parentNode.getElementsByTagName("span")[0].style.display = "inline";
    }
    inputs[i].onblur = function () {
      this.parentNode.getElementsByTagName("span")[0].style.display = "none";
    }
  }
  var selects = document.getElementsByTagName("select");
  for (var k=0; k<selects.length; k++){
    selects[k].onfocus = function () {
      this.parentNode.getElementsByTagName("span")[0].style.display = "inline";
    }
    selects[k].onblur = function () {
      this.parentNode.getElementsByTagName("span")[0].style.display = "none";
    }
  }
}
addLoadEvent(prepareInputsForHints);

Check out what we have. It’s functioning, for all inputs and selects, and it’s looking pretty good. There are still a couple of things we can do to help it, though.

Minor Tweaking

Right now the hint is just in a box. Notice how in Vox’s example, their hint box has a little arrow attached to it. Let’s add that pointer in there. We want an image that has the same border and fill as the hint box, with the exception of the left border, which we don’t want to exist. I’m going to use the same one Vox uses – a simple triangle.

pointer

This image will be added as a background image with the help of an additional span, which we need to insert within the hint in the HTML, and give a class of hint-pointer.

<span class="hint">Use your real name!
  <span class="hint-pointer">&nbsp;</span>
  </span>

Let’s style it so that it looks like it’s part of the hint box.

.hint .hint-pointer {
    position: absolute;
    left: -10px;
    top: 5px;
    width: 10px;
    height: 19px;
    background: url(pointer.gif) left top no-repeat;
}

That’s better.

Also, up to this point, we’ve assumed that every <input> will have a corresponding hint. What if we don’t need hints for some of those inputs? Who needs a hint for a field like “First Name”? We also don’t want to show hints with submit buttons (remember, they are <input>’s, too!)? As of now, if there is a missing hint, a JavaScript error is returned.

There is more than one way to account for this. Here’s one. Let’s add some logic to the JavaScript that checks to see if a span exists before trying to change the style of that span.

function prepareInputsForHints() {
  var inputs = document.getElementsByTagName("input");
  for (var i=0; i<inputs.length; i++){
    if (inputs[i].parentNode.getElementsByTagName("span")[0]) {
      inputs[i].onfocus = function () {
        this.parentNode.getElementsByTagName("span")[0].style.display = "inline";
      }
      inputs[i].onblur = function () {
        this.parentNode.getElementsByTagName("span")[0].style.display = "none";
      }
    }
  }
  var selects = document.getElementsByTagName("select");
  for (var k=0; k<selects.length; k++){
    if (selects[k].parentNode.getElementsByTagName("span")[0]) {
      selects[k].onfocus = function () {
        this.parentNode.getElementsByTagName("span")[0].style.display = "inline";
      }
      selects[k].onblur = function () {
        this.parentNode.getElementsByTagName("span")[0].style.display = "none";
      }
    }
  }
}
addLoadEvent(prepareInputsForHints);

I’d love to see other examples of similar effects. Let me know of any you like.

April 3, 2007: textarea example provided

April 3, 2007: Fixed IE6 bug.

It was pointed out that IE6 was showing some buggy behavior the first instance of showing the hints. The border wasn’t completely being drawn around the span. I was going to pass it off as “buggy IE6”, because I couldn’t find a fix, but thanks to David Carriger in the comments, I think we found something.

In the .hint CSS, we have been giving span.hint a background color using “background-color:#ffc”, but if we go ahead and give it a background image, too, IE6 will render span.hint properly.

.hint {
  display:none;
  position: absolute;
  right: -250px;
  width: 200px;
  margin-top: -4px;
  border: 1px solid #c93;
  padding: 10px 12px;
  background: #ffc url(pointer.gif) no-repeat -100px -100px;
}

Note that I gave it the same background image as the .hint-pointer span (less overhead that way), and positioned it with a negative margin so that it doesn’t actually show up. This is now fixed in the final example and downloadable zip.

See final example, which only shows hints for username and password (and fixes the IE6 bug!).

April 20, 2007): Vox.com, the site whose registration form this article is based on, has changed that form, and it no longer uses the effect.

May 14, 2007): If you like this post, you might also appreciate validation hints.


This post was ported from an old host and CMS, so many comments were lost. Below are the comments that I found were most helpful regarding this post that I salvaged. Some links or attributions may not be working correctly.


It could be easily done using :focus and the adjacent sibling selector. Something along the lines of:
span { display: none; }
input:focus + span { display: inline; }
of course this will only work in browsers that understand the pseudo selector ‘:focus’ and the adjacent sibling selector ‘+’ (tested and works in FF2)

Bill asks the CSS Guy if there is a way to use variables within CSS

Bill writes:

One thing I am not certain how to do, or if it is even possible is to define some sort of pseudo-variable that can be used in the CSS definitions. For example, I am working on a page that the owners want a specific color scheme used throughout the site. Each page has five colors (they all share the same set of colors). CSS has made my life sooo much easier to make changes they want (they are making several changes a day trying to “fine tune” the exact shades they want.

Anyway, it would be nice if I could do something like this:

#Red1 { color: #400000 }
#Cream1 { color: #F0E68C }
#Cream2 { color: #FAFAD2 }
#Blue1 { color: #00008B}

and then further in the CSS file uses these names like:

body {
  color: Blue1;
}
 
a {
  color: Red1;
}
 
a.footer {
  color: Cream2;
}

Bill, the short answer is no. CSS isn’t built for that. Your editor’s find and replace is your surest bet.

However, there is a longer answer, too. Many people have wanted this feature, and have found a way to make it happen using server-side scripting.

Please see this entry on 24ways.org for a well-written and relatively recent article on your options to achieve this. The comments themselves are enlightening as well. The last comment on that article has a link to a post that is particularly helpful in understanding why this feature wasn’t included in CSS to begin with.

My advice is to stick to find and replace.


This post was ported from an old host and CMS, so many comments were lost. Below are the comments that I found were most helpful regarding this post that I salvaged. Some links or attributions may not be working correctly.


pahtrick said:
http://www.designrefugee.com/design-blog/css-variables.html
for a comprehensive tutorial on PHP parsing & variables in CSS

I read Bulletproof Ajax

I and many others were excited by reading DOM Scripting by Jeremy Keith. That book can take a CSS designer with no prior JavaScript experience, and equip that reader with some easy but powerful dom-manipulating know-how, all the while reinforcing the standardista’s mantra of separation of structure, presentation, and behavior. A JavaScript beginner who reads this book can feel empowered. I read it twice, the second time with a highlighter, both times in my bed late at night with flashlight and a wife that wished I would just go to sleep and save my geekiness for the daylight hours. It was like reading a page-turning Grisham novel, except instead of a lawyer running from the mob, it was nerdy nuggets of code making html snippets move and change. With every chapter, I could not wait to get back to my computer and recreate these dynamic examples. The book is that good. Keith makes learning JavaScript that easy. The examples are real and are easily implementable to almost any site.

Jeremy Keith's books

So when Keith wrote Bulletproof Ajax, which he calls “the sequel to DOM Scripting“, you can imagine with what level of anticipation it was met, by not just myself, but many others who were also inspired by Keith’s first book. Ajax was just a casual mention in the back of DOM Scripting. With his new book, I wondered if I were going to feel that sense of empowerment again, by getting to know and understand this elusive and oft-misunderstood technology. I can’t speak for others when I talk about Bulletproof Ajax, but I’d like to give my impressions. Because the author refers to it as “sequel to DOM Scripting,” much of my review will reference both books.

The first thing I noticed was that the book was thin – less than 200 pages of content (compared to DOM Scripting‘s 300+ pages of content). That could mean one of two things – either Ajax will be much easier than I thought, or this book is not going to be as thorough as anticipated.

The first two chapters are simply introductory. Chapter one explains what Ajax is and gives alternatives to achieving similar results. Chapter 2 gives a concise summary of JavaScript that was covered in greater detail in DOM Scripting – including properties, objects, operators, etc.

Chapter 3 is where the real meat begins – an introduction to the XMLHttpRequest object. Keith walks the reader through what goes on with the XMLHttpRequest between the server and client. It’s informative and clear, though I am hardheaded enough that I will probably have to give it a third and fourth read.

Chapter 4 is another nice, meaty chapter – an explanation of the different data formats that Ajax can use, including pros and cons of each. The reader can look over these options and view which options are more suitable for their tasks. I was certain that Keith would advocate XML over the other formats (after all, it was originally the “x” in Ajax), but he doesn’t. I was partly disappointed with his explanation with the data format he chose to use for the duration of the book. He uses HTML with the innerHTML property rather than XML. innerHTML is quicker and requires less code than formatting XML. However, after having read DOM Scripting, I had been under the impression that I should probably shy away from it, since the browser is blind to the elements of code entered using innerHTML. From DOM Scripting:

… innerHTML is a proprietary method, not a web standard. I think it’s a good idea to avoid any kind of proprietary JavaScript, so that we don’t repeat the bad old days of the browser wars. … As it turns out, innerHTML is well supported. Nonetheless, its future existence is far from certain.

… the standardized DOM can be used instead of innerHTML. It may take slightly more code to achieve the same results but, as you’ll see, it offers more precision and power.

I guess “power” is relative to what your book is about. In Bulletproof Ajax, Keith repeats his concerns about innerHTML, warns against careless usage, and states he will use it anyway for the sake of brevity. It’s understandable, but I would’ve enjoyed more examples that follow in the footsteps of DOM Scripting. What if I wanted to do more DOM manipulation on the snippets of code that are injected into our AJAX examples? With innerHTML, the DOM is blind to the code within that mark-up.

Keith starts the book with a primer on JavaScript. By the time I reach the chapter on his building a full-blown Ajax application, I found myself wondering why there wasn’t a primer on PHP as well. All of the examples use it. Keith states,

Don’t worry if you don’t understand PHP. Understanding the language I’m using isn’t as important as following the underlying concepts.

But doggone it, I want both: the concepts and some understanding of the PHP code. (If I only needed the concepts, then why is there an entire chapter on JavaScript fundamentals?) Granted, many people who are familiar with PHP won’t have this complaint, but my familiarity with PHP ends at “Hello World”. If I’m going to put Ajax to work, I need to have some level of comprehension of a server-side programming language, and I think this should’ve been mentioned in the introduction, which currently states the following:

If you’re a front-end developer, this is the book for you. You’re probably well-versed in Web Standards. I trust you’re using semantic markup and CSS, perhaps even some rudimentary DOM Scripting. If so, read on.

As stated, I would add to that list that any potential reader should also have some basic-to-intermediate PHP knowledge especially if you’re wanting to implement the examples. Be capable of writing a form in PHP that has server-side field validation to get the most from this book. Chances are if you know how to do that, you can implement the rest of the examples and be ready to cater them to your own site. Ajax can be applied to any server-side language, not just PHP, but I think it would be helpful when following his examples if the reader could grasp PHP syntax.

The server-side code isn’t completely left unexplained, and code for all examples are found on the web site for reference, but the level of detail is not as equal to that for the JavaScript.

That said, having to cover JavaScript, CSS, HTML, and PHP (especially when PHP may not be the reader’s server-side language of choice) is a daunting task for an author, and Keith manages to convey the concepts with relative ease, even if there isn’t a full explanation of the code.

Bulletproof Ajax excels at covering the accessibility challenges of Ajax. Web Standards are upheld and encouraged throughout the book. Keith constantly asks, “Is Ajax the best way to do this?”. He recognizes how enthusiastic designers can get at the mention of this buzzword, and he feels responsible enough to keep the reader’s excitement in check, and remind them that Ajax is just one tool out of many that can be used to enhance web sites without sacrificing accessibility.

As for Ajax concepts in the world of Web Standards, Bulletproof Ajax is an essential read. However, rather than refer to it as “the sequel to DOM Scripting“, I would instead think of it as the third book in the following trilogy:

  1. DOM Scripting
  2. Some server-side language beginner book, PHP preferred
  3. Bulletproof Ajax

Andre asks the CSS Guy how to center an image in a div

Andre writes:

how do you center images inside a div with css?

Andre, here’s one way. If your html looks like this:

<div>
   <img src="elephant_ball.jpg" alt="" />
</div>

Apply display:block; to the image, and also make sure it’s left and right margins are set to “auto”, like so:

<style type="text/css">
div img {
   display:block;
   margin:auto;
}
</style>

That should do it. View the example.

I hope you didn’t mean “vertical” centering…

…because right now, there’s no elegant and easy way to do it that’s acceptable to all browsers. Below are some possible options to look into – pick your poison.