In the tutorial today, we’re going to be building the following search field while sticking to POSH (Plain Old Semantic HTML) principles:
If you’re using a decent browser the our final version above looks great; it’s got a text field with a magnifying glass icon and a button all “contained” within a rounded rectangle border. If you’re unfortunate enough to be forced to use Internet Explorer, or happen to be an Opera fan you won’t see the rounded corners. But this is also part of the point of this tutorial: using progressive enhancement, we’ll construct this field so that it’ll look good and work well on all browsers (even ones with CSS turned off).
But wait! I thought you said we’re using semantic HTML?
That’s right, semantic HTML practices and progressive enhancement are like two peas in a pod. If you’re still wondering what I mean by these two terms, I won’t explain them much in this tutorial, but you can read about them in these great articles:
The Markup
Just like the good progressive enhancement-subscribing web developers we are, we’ll start by writing our markup and then move on to styling it with CSS. Here’s what the HTML for our <form> will look like:
<form action="http://google.com/search" method="get" class="search">
<input type="text" name="q" size="27"/>
<button type="submit">Search</button>
</form>
As you can see, the code is really straight forward. We’ve got a <form> element that’s pointed at Google’s search URL (http://google.com/search) using the GET http method. Inside of the <form> are two elements: a text <input> field and a <button>.
What’s so semantic about this?
This markup is semantic in that it’s structure and makeup tell us something about what it means. A form with an input field and a button, whose class is “search”, makes it pretty obvious that it’s describing a search field. We also don’t have lots of messy <div> tags cluttering up the code (or worse: a <table>), it’s nice and clean.
This cleanliness also lends nicely to progressive enhancement. As you can see below, when rendered as-is without styling, it still looks fine and makes perfect sense:

Check it out yourself here.
The CSS
Now that we’ve got our markup, it’s time to make the search field look great. We’ve already assigned the class attribute of our form to search, so let’s go ahead and create a couple of styles: one for the input field and the other for the button. I’ve taken the liberty of introducing some preliminary styles here too (to give us a nice background color and border, as well as a bit of padding).
.search input {
padding: 5px;
border: 1px #acddff solid;
background-color: #ecf8f6;
}
.search button {
padding: 1px;
border: 1px #acddff solid;
background-color: #fffdfa;
}

See the improvements live, here.
Now that we’ve got the skeleton for our styles, we can really start to get down to business. Probably the most obvious difference between the above screenshot and our goal at the top of the tutorial is the fact that the search button hasn’t yet been ‘wrapped’ by the search field. We need to somehow shift the button to the left.
Let’s use the technique of “negative margins” to pull our button over the input field. To know the exact value we want to use for our negative left margin we need to specify a width for our button.
.search button {
padding: 1px;
border: 1px #acddff solid;
background-color: #fffdfa;
margin: 0 5px 0 -75px;
width: 65px;
}
By pulling the button onto the search box, we’ve created a new problem: if you type too many characters into the input field they will slip behind the button. We need to set some padding on the field itself to create a bit of a buffer:
.search input {
padding: 5px 70px 5px 5px;
border: 1px #acddff solid;
background-color: #ecf8f6;
}
Reminder: The order of the four pixel values for margin, padding, and border styles are: top, right, bottom, and left (clockwise from the top).
We’re getting closer! Now let’s change the styling on the <input> element again, this time we’ll add a background image (a magifying glass icon from FamFamFam’s Silk icon collection):
.search input {
padding: 5px 70px 5px 5px;
border: 1px #acddff solid;
background-color: #ecf8f6;
background-image: url(../icons/magnifier.png);
background-position: 3px 3px;
background-repeat: no-repeat;
background-color: #ecf8f6;
outline: none; /* So safari doesn't use the annoying blue rectangle */
}
This works well, we’re setting the background-image to our hosted version of the magnifier, forcing it to not tile itself by setting background-repeat to no-repeat, and shifting it three pixels from the top and left of the field’s corner. There’s one catch. If we type in the field, our text goes right over the magnifying glass image and makes it stand out as a background, instead of as a major feature. We need to add some more padding:
.search input {
padding: 5px 70px 5px 22px;
border: 1px #acddff solid;
background-color: #ecf8f6;
background-image: url(../icons/magnifier.png);
background-position: 3px 3px;
background-repeat: no-repeat;
background-color: #ecf8f6;
}
Check it out:
Rounded corners, with CSS 3
The new version of CSS, CSS 3, gives us the ability to specify a radius to use when rounding an element’s corners. Unfortunately CSS 3 isn’t completely adopted by any major browser at the time of writing, but Gecko (the engine behind Firefox) and WebKit (the engine behind Safari and Chrome) both provide provisional style properties for rounded corners: -moz-border-radius and -webkit-border-radius.
Let’s add these properties to the styles for both the text field and the button:
.search input {
padding: 5px 70px 5px 22px;
border: 1px #acddff solid;
background-color: #ecf8f6;
background-image: url(../icons/magnifier.png);
background-position: 3px 3px;
background-repeat: no-repeat;
background-color: #ecf8f6;
outline: none;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
}
.search button {
padding: 1px;
border: 1px #acddff solid;
background-color: #fffdfa;
margin: 0 5px 0 -75px;
width: 65px;
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
}
Notice how we used a slightly smaller radius for the button as opposed to the input field, this was because we want the curved corners to “fit” inside each other well. We’re done! Take a look at the final results (look familiar?):

You can also see a live version and inspect its code, here.
We’ve created a beautiful search field using clean semantic HTML, and styled it with some very effective CSS. Also, it’s progressively enhanced; which means it’ll still look and work fine even on browsers that don’t support CSS!