Grow your CSS skills. Land your dream job.

Improved Current Field Highlighting in Forms

Published by Chris Coyier

currentfield

VIEW DEMO

As a matter of usability and aesthetics, it is a good thing to add some kind of visual feedback on web forms to indicate the currently active (or "focused") field. Some browsers (Safari/Opera) have decided that is so important, that it take matters into it's own hands and applies a glowy blue border around active form elements:

safari-search

For non-Safari/Opera browsers, CSS offers some help through the :focus pseudo-classes. You can declare your own focus styles like this:

input:focus {
      background: #fc9fff;   /* sexy hot pink */
}

That's a good start, but it has some unfortunate weaknesses:

  • It doesn't work in some browsers (IE)
  • It only highlights the field itself, and does nothing for its corresponding label

We are going to tackle both of these weaknesses, improving our current field highlighting, using jQuery. Our form HTML will look just like any other form markup, except that each label/input group will be wrapped in a DIV:

<form>
	<div class="single-field">
		<label for="Name">Name:</label>
		<input name="Name" type="text"></input>
	</div>
	<div class="single-field">
		<label for="Email">Email:</label>
		<input name="Email" type="text"></input>
	</div>
</form>

Using jQuery, we can watch for an event where an input form comes into focus:

$(document).ready(function(){
	$("input").focus(function() {
		....do something....
	});
});

This is where we can do something cool that CSS alone can't do, we can jump up to the parent element of that input element, and affect that. In our case, the parent element is that div wrapper we put around each label/input pair. What we would like to do is apply a unique class to that div when the input comes in focus.

$(document).ready(function(){
	$("input").focus(function() {
		$(this).parent().addClass("curFocus");
	});
});

With CSS, we can style up that unique class however we would like!

div.curFocus {
	background: #fdecb2;
}

This works great, but if we just left this how it is, each field would have this class applied when it came into focus and it would never be removed. The whole point here is that this "current field highlighting" is only applied to the "current field". Fortunately, jQuery gives us a "blur" event, which is the opposite of focus. Let's put in code for that:

$(document).ready(function(){
	$("input").focus(function() {
		$(this).parent().addClass("curFocus")
	});
	$("input").blur(function() {
		$(this).parent().removeClass("curFocus")
	});
});

We wouldn't necessarily need to to specify "curFocus" on the removeClass function, since leaving that blank will remove all classes, but just in case we have multiple classes let's leave it at that.

But wait! Your example has super-cool rounded corners on the active fields! Haha, it does! I'll never tell! Er. Ehm. OK I will.

Each of the four corners is a little div that needs to go inside of each of our field wrapper divs. Since they are all exactly the same and need to be inside each wrapper div, let's apply them through jQuery and save ourselves unnecessary repeated markup.

...there is something deeply satisfying about having semantic markup dynamically generated by JavaScript. From: Learning JQuery by Karl Swedberg & Jonathan Chaffer

I agree. We can make any HTML snippet into an jQuery object. Then we'll use the "appendTo" function to slip it inside each div. Check it out:

$('<div class="tl"></div><div class="tr"></div><div class="bl"></div><div class="br"></div>').appendTo("div.single-field");

In our CSS, we'll style them up but leave their display values to "none" so they don't show up until we want them.

.tl {
	position: absolute;
	top: 0;
	left: 0;
	width: 10px;
	height: 10px;
	background: url(images/corner-topleft.jpg);
	display: none;
}
.tr {
	position: absolute;
	top: 0;
	right: 0;
	width: 10px;
	height: 10px;
	background: url(images/corner-topright.jpg);
	display: none;
}
.bl {
	position: absolute;
	bottom: 0;
	left: 0;
	width: 10px;
	height: 10px;
	background: url(images/corner-bottomleft.jpg);
	display: none;
}
.br {
	position: absolute;
	bottom: 0;
	right: 0;
	width: 10px;
	height: 10px;
	background: url(images/corner-bottomright.jpg);
	display: none;
}

We'll use jQuery to toggle the visibility of all those divs on and off when we need them. Here is the final javascript:

<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript">
	$(document).ready(function(){
		$("input").focus(function() {
			$(this)
				.parent()
					.addClass("curFocus")
				.children("div")
					.toggle();
		});
		$("input").blur(function() {
			$(this)
				.parent()
					.removeClass("curFocus")
				.children("div")
					.toggle();
		});
		$('<div class="tl"></div><div class="tr"></div><div class="bl"></div><div class="br"></div>').appendTo("div.single-field");
	});
</script>

VIEW DEMO

Comments

  1. Permalink to comment#

    That’s realy a good example where jQuery comes in handy.
    I’ve used “plain javascript” for such things but in future I’ll use jQuery since it’s realy easy and very effective.

  2. Permalink to comment#

    Its Really Good But Not Work Good In ie So I cant Use It :( Sorry But Thanks :)

  3. Permalink to comment#

    @Ayush:
    It is working with IE (at least with IE6) – if you just copied the sourcecode of the example it will probably not work (no styles & a tag to much).

  4. Axel
    Permalink to comment#

    Hi and thanks for this great article!I tryed to change the color of the label text by adding a new class to the label element which is removed in jQuery at active state; so I put in the following line:

    $("label").removeClass("textcolor");

    works nice, but on focus both fields are changed, does anyone know how to remove the class only from the activ field?

    Thank you, I appreciate it.

  5. Axel
    Permalink to comment#

    With some sweat and tears I found out ;-)

    $(this).parent().children('label').addClass("textcolor");
    
    Working now fine for me!
  6. Haha, love it when Firefox crashed. Firebug consumes a lot of memory, and is very process intensive, so Firebug probably had something to do with it.

  7. After an hour i discovered you can turn off Safari and Opera’s blue outline using

    input, textarea {outline-style:none;}

    All most lost my mind!

  8. Permalink to comment#

    Incredibly useful – thanks.
    Although, common practice is to place form inputs inside list elements, so there’s no need to create a seperate div for each item.

  9. Permalink to comment#

    Simply great. It really simplifies things.

  10. handoyo
    Permalink to comment#

    Thanks for the share..But i’ve tested it on ie 6.It doesn’t work perfectly..Does someone has able to make it work for ie??Please share the codes please..Thanks a lot…

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".