Text Inputs on Safari

A lot of people have been asking how I style my input tags in Safari (see the Search input above). Apple’s browser does not give you a whole lot of control over how form elements are displayed so when I design a form I figure out what I can do in Safari and then make other browsers emulate it.

First, borders are a no-go. We are stuck with OS X’s default recessed input. If we want a border we need a wrapper element. But before we even get to that point we need to get other browsers inline with Safari. Let’s start with a simple <input type="text" />. Grab a screenshot, open up in Photoshop and zoom in. Three colors are used for the borders:

input
{
    margin: 0;
    border: 1px solid #C3C3C3;
    border-top-color: #7C7C7C;
    border-bottom-color: #DDD;
}

When I’m feeling particularly pixel-retentive I’ll create a 1×1 #C3C3C3 gif to use as a repeating background image in the input to emulate that subtle drop-shadow.

input
{
    border: 1px solid #C3C3C3;
    border-top-color: #7C7C7C;
    border-bottom-color: #DDD;
    background: url(bg-input.gif) 0 0 repeat-x;
}

I like to add a little contrast to my inputs. I feel it helps delimit the input from the surrounding page and reinforces its role as receptacle. To do so we need a wrapper element. My default is the humble <span>. The span also acts as a style hook to prevent any old input (like a submit button or a checkbox) from inheriting these styles

I prefer the double border bevel treatment so I set a background color, a single pixel of padding and a border.

span
{
    display: block;
    background-color: #FFF;
    padding: 1px;
    border: 1px solid #1B1B1B;
}

span input
{
    width: 100%;
    border: 1px solid #C3C3C3;
    border-top-color: #7C7C7C;
    border-bottom-color: #DDD;
    background: url(bg-input.gif) 0 0 repeat-x;
}

For the span border color I usually use the background color plus 10% black for added contrast. The span is set to display: block; so that it fills the table cell that we will eventually drop it into. The input in turn fills the span because of the width: 100%;.

Now, rather than waste time micromanaging every detail of each individual form on a site, we can drop our nested inputs into table cells. Each input and its bevelled border will expand to fill the available space. After adding some padding to the table cells or some margin to the span itself we have simple drop-in form styling.

We’ve embraced Safari’s input styling limitation and established a consistent, cross-browser presentation (barring some adjustments for IE PC of course).

Previous
TextMate: now with more cobwebs!
Next
MacBook Pro MagSafe Power Adapters fraying/melting?
Author
Shaun Inman
Posted
November 2nd, 2006 at 2:44 am
Categories
The Site
Apple
CSS
Design
FAQs
Comments
021 (Now closed)

021 Comments

001

You could use the button element instead of input. That gives you complete control over the look and feel of “buttons”/input in Safari and Camino, including the ability to change the text size (in Safari, something you can not do with input)

The downside is IE, with button type submit it submits the innerHTML not the value you assigned. Which means extremely careful use. Though if you use javascript, button type button works fine.

Also IE adds some screwy padding (roughly 5% to the top, 10% padding to the bottom and 20 to 25% to the left and right) you can not remove (except through negative margin in a targeted attack).

Author
nick cowie
Posted
Nov 2nd, 2006 4:06 am
002

Table cell? Shurely shome mishtake… ;)

Author
Matthew Pennell
Posted
Nov 2nd, 2006 4:10 am
003

Why would you want to use a table for forms? A list is a better (and more semantic!) approach.

Author
Fredrik Wärnsberg
Posted
Nov 2nd, 2006 5:39 am
004

Thanks for posting this, Shaun. A great honour, actually, to see this new post today after e-mailing you about the topic only yesterday!

Two questions if I may:

  1. How do you achieve the rollover effect on your input buttons? I see that you use images on the input button via src, and as the images you’re using are PNGs, it looks like it’s not them rolling over - it’s the background-colour behind the PNGs that’s changing. Very nice touch indeed - but where is this change of background-colour in the CSS? It’s obvious how it’s happening on the buttons that are actually in a tags but not on the buttons that use input.

  2. Not that it matters, but just out of personal curiosity, why did you choose to wrap the input button in the deprecated u tag rather using span (given that both options are essentially meaningless, semantically)?

Many thanks!

~ Elliot

Author
Elliot Jay Stocks
Posted
Nov 2nd, 2006 6:17 am
005

Nick & Elliot: this article is focused on styling text inputs. I’ll explain the button treatments in a follow-up article.

Matt & Fredrick: Sorry, I’m not going to get into an argument over semantic markup. Use which ever you think is best.

Author
Shaun Inman
Posted
Nov 2nd, 2006 9:21 am
006

You may not want to get into a semantic argument, Shaun, but I certainly shall :)

…Comment thread hack in progress….

A list is more semantic than a table for form layout?

How in the world does a UL have more semantic meaning than a table when it comes to form elements? Neither of them have any semantic value whatsoever when it comes to forms.

A better, more semantic way of handling forms is with the label tag.

Something like this will give you much better control and still have semantic meaning:

< label for = “name” > Input 1 < /label >

< input type = “text” />< br / > (this br is important)

Now the styling:

label, input{ float:left; display:block; width: 150px; margin: 10px; } input{..style how you like…}

br{ clear:left; / * makes sure your forms dont wrap * / }

There you go, now you have a semantic, CSS based solution that makes your forms behave as if they are in tables.

…Okay Shaun, you can have the comments back :) …

Author
Nate Cavanaugh
Posted
Nov 2nd, 2006 12:12 pm
007

I’m a fan of Definition Lists for marking up forms, in conjunction with labels. Maybe its a bit of extra code, but a lot of times I find a simple Label/Input pair isn’t enough and I have to end up wrapping a div or something around them anyway.

Author
Greg
Posted
Nov 2nd, 2006 2:33 pm
008

This all becomes null in the next release of Safari. You’ll be able to style inputs all fancy like everywhere else. Check out the WebKit nightlies.

Author
Thomas Aylott
Posted
Nov 2nd, 2006 3:31 pm
009

Thanks! I just ran into this issues of styling for Safari this morning! Well now I know, and knowing is half the battle!

Author
Seth
Posted
Nov 2nd, 2006 8:55 pm
010

Sorry, I have been reading too many posts on the button element and input type submit. I do like your buttons, even if they are input type=”image” ;-) even if it is now the best crossbrowser solution, especially when FF & Safari get page zoom.

I have not spent enough time looking at input type=”text”, but this post has sparked my interest.

And yes I am very jealous of what you have done with the form elements here.

Author
nick cowie
Posted
Nov 2nd, 2006 9:46 pm
011

Surely you’ve noticed that width: 100% plus border-width: 1px gives you a calculated width 2px greater than desired. This can be fixed by changing the padding rule on the <span> to padding: 1px 3px 1px 1px;.

As for tables, I really don’t think they’re necessary, especially for something as simple as a search form. To retain semantics and at the same time trim redundant elements, I recommend wrapping form inputs with <label> elements (minus their for attribute), a handy technique I learnt from Dave Shea.

Author
Scott
Posted
Nov 3rd, 2006 8:27 am
012

Who knows when it will be out, but when the next version of Safari uses the latest WebKit, it will support styling of most form elements. See webkit bug 9348

Author
John Lascurettes
Posted
Nov 3rd, 2006 3:11 pm
013

I totally want a t-shirt that says “pixel-retentive.”

Author
Krystyn
Posted
Nov 4th, 2006 9:31 pm
014

Very cool, thanks, Shaun. (:

Author
.sara
Posted
Nov 8th, 2006 2:48 am
015

The <label> technique is good, but the best practice is to use ids for the labels, and to wrap the <input> within the label tag. Like so:

<label for="clickme">  
  <input id="clickme" ... />  
  Label Text  
</label>

But you offer some great advice nonetheless. Thank you!

Author
Down10
Posted
Nov 8th, 2006 4:59 am
016

Shaun: Interesting technique. I’ll have to try it sometime. But how did you get the background so gray?

Author
Arden
Posted
Nov 8th, 2006 9:31 am
017

Nightly builds of Safari properly support styled form elements. No idea when this will be rolled out (Leopard, and only Leopard perhaps). Kinda jarring to see non-Apple Aqua controls in web pages when using the nightlies after years of Aqua-ness.

Author
Neo
Posted
Nov 8th, 2006 9:36 am
018

Great tips. Thanks!

btw: Your site looks awesome!

Author
Brutal
Posted
Nov 8th, 2006 2:11 pm
019

Great article Shawn. I had given up on styling Safari’s inputs as a lost cause.

Author
Gordon Brander
Posted
Nov 9th, 2006 12:21 am
020

You can eschew tables for very simple forms, yes. But once you get into complex forms with multiple inputs per line and multiple columns and appearing/disappearing components, tables are still the way to go…

Notice the table in Shaun’s (seemingly simple) comment form, for example :-O

Author
Mike H
Posted
Nov 9th, 2006 11:14 pm
021

Great way to make sure that text fields look great in most modern browsers but I’m really here to answer someone’s question

Elliot - to achieve the background color change when you’re typing in that particular field, you use input:focus, for example:

input { background-color: #EEE; }

input:focus { background-color: #FFF; }

Author
Martin Hipp
Posted
Nov 30th, 2006 10:25 pm