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).
021 Comments
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).
Table cell? Shurely shome mishtake… ;)
Why would you want to use a table for forms? A list is a better (and more semantic!) approach.
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:
How do you achieve the rollover effect on your
input
buttons? I see that you use images on theinput
button viasrc
, and as the images you’re using are PNGs, it looks like it’s not them rolling over - it’s thebackground-colour
behind the PNGs that’s changing. Very nice touch indeed - but where is this change ofbackground-colour
in the CSS? It’s obvious how it’s happening on the buttons that are actually ina
tags but not on the buttons that useinput
.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 usingspan
(given that both options are essentially meaningless, semantically)?Many thanks!
~ Elliot
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.
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 :) …
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.
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.
Thanks! I just ran into this issues of styling for Safari this morning! Well now I know, and knowing is half the battle!
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.
Surely you’ve noticed that
width: 100%
plusborder-width: 1px
gives you a calculated width 2px greater than desired. This can be fixed by changing the padding rule on the<span>
topadding: 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 theirfor
attribute), a handy technique I learnt from Dave Shea.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
I totally want a t-shirt that says “pixel-retentive.”
Very cool, thanks, Shaun. (:
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:But you offer some great advice nonetheless. Thank you!
Shaun: Interesting technique. I’ll have to try it sometime. But how did you get the background so gray?
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.
Great tips. Thanks!
btw: Your site looks awesome!
Great article Shawn. I had given up on styling Safari’s inputs as a lost cause.
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
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; }