TJ VanToll

Default Browser Handling of the CSS text-transform Property

| Comments

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:

    div { text-transform: uppercase; }

    <input type="text" value="foo" />
    <input type="submit" value="bar" />

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>
            form { text-transform: uppercase; }
            <!-- "foo" will be uppercase in IE, Firefox, and Opera -->
            <!-- "foo" will be lowercase in WebKit based browsers -->

            <!-- "bar" will be uppercase in Firefox and Opera -->
            <!-- "bar" will be lowercase in IE and WebKit based browsers -->


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.