The text-transform
CSS property is most frequently used to uppercase and lowercase text. According to the CSS 2.1 specification it is also an inherited property, meaning, when no value is specified on a given element, it should inherit its parent’s text-transform
value.
If no parents have a text-transform
property defined, the element will take on the default value of none
.
Where it gets interesting is that all browsers define default text-transform
properties for certain form elements. What does this mean? Let’s say you have the following markup:
<style>
div { text-transform: uppercase; }
</style>
<div>
<input type="text" value="foo" />
<input type="submit" value="bar" />
</div>
Both foo
and bar
will appear lowercased in all major browsers. You can see this for yourself below:
Default text-transform behavior Open in New Window
This happens because all browser vendors include text-transform: none
in their user agent stylesheet for those elements. Therefore the text-transform: uppercase
rule declared on the parent node is not inherited.
Unfortunately, but not surprisingly, browsers are not consistent about their default values for all elements.
What the Browsers Do
The following chart shows popular browser rendering engines and whether their user agent stylesheet includes text-transform: none
for the listed elements.
Rendering Engine | input[type=submit] | input[type=text] | select | textarea | button |
---|---|---|---|---|---|
Trident (Internet Explorer) | Yes | Yes | Yes | Yes | No |
Gecko (Firefox) | Yes | Yes | No | Yes | No |
WebKit (Chrome, Safari, etc...) | Yes | Yes | Yes | Yes | Yes |
Presto (Opera) | Yes | Yes | No | Yes | No |
The rendering engines that have a No for a given element declare no default for text-transform
. Therefore, those elements will inherit the value from their parent.
What Does This Mean?
The browser differences occur on the button
and select
elements. Therefore, if you apply a text-transform
value to a node, AND that node has children button
/ select
nodes, AND you do not apply a text-transform
value to the button
or select
nodes themselves… you’ll get different behavior in different browsers.
For example:
<!DOCTYPE html>
<html>
<head>
<style>
form { text-transform: uppercase; }
</style>
</head>
<body>
<form>
<!-- "foo" will be uppercase in IE, Firefox, and Opera -->
<!-- "foo" will be lowercase in WebKit based browsers -->
<button>foo</button>
<!-- "bar" will be uppercase in Firefox and Opera -->
<!-- "bar" will be lowercase in IE and WebKit based browsers -->
<select>
<option>bar</option>
</select>
</form>
</body>
</html>
Consistency
You could make arguments as to whether the user agent stylesheets should be defaulting the text-transform
of various form elements to none
, but to most people all that matters is that the behavior is consistent. It’s easy enough to override the defaults if you don’t like them.
Therefore to get consistent behavior you would think you would need to set the default value of button
and select
elements to either none
or inherit
.
/* Option 1 - Don't inherit values in all browsers */
button, select { text-transform: none; }
/* Option 2 - Inherit values in all browsers */
button, select { text-transform: inherit; }
But unfortunately for whatever reason Option 2 doesn’t work on the <select>
in IE <= 7, Safari, and most interestingly, doesn’t take effect in Chrome until you click on <select>
. You can verify this behavior for yourself below:
Inherited behavior discrepancies Open in New Window
Fortunately Option 1 does indeed produce the same behavior in IE6+, Firefox, Chrome, Safari, and Opera. Therefore to normalize text-transform
you need to include the following in your stylesheet.
button, select { text-transform: none; }
Update (January 21st, 2013)
A pull request I sent for this change was accepted into normalize.css.