text-transform in CSS: uppercase, lowercase and capitalize
The CSS text-transform property changes how text is drawn without changing the text itself. Four values do almost all the work: uppercase, lowercase, capitalize and none. The source stays exactly as you wrote it, which is both the property’s greatest strength and the reason it is so often the wrong tool.
Type in the box below and the same string is rendered with each value, live, using real CSS rather than a simulation.
Need to change the text, not just its appearance? The upper lower case converter changes the actual characters, with acronym protection and twelve styles. Free, no sign-up.
The values
| Value | Effect on the HTML guide | Support |
|---|---|---|
none | the HTML guide | Universal, the default |
uppercase | THE HTML GUIDE | Universal |
lowercase | the html guide | Universal |
capitalize | The HTML Guide | Universal |
full-width | Monospaced CJK forms | Good, used for Japanese layout |
math-auto | Italic single letters in MathML | Newer, limited |
Note the capitalize row. It uppercases the first letter of each word and leaves the rest alone, so HTML survives, unlike the Excel PROPER function or Python’s title(), which lowercase the tail. That makes CSS capitalize better behaved than most of its equivalents, and it is still not Title Case, because it capitalizes of and the. The distinction is set out in Capitalize Each Word versus Title Case.
The four things text-transform does not do
- It does not change the text. Copy an uppercased heading and you paste the original. Read the element with JavaScript and you get the original. Only the pixels change.
- It cannot do sentence case. There is no value for it, because CSS has no concept of a sentence.
::first-lettercapitalizes the first letter of a block, which is close but not the same. - It cannot do real Title Case. That needs a list of function words. CSS has no dictionary.
- It does not undo itself.
text-transform: lowercaseon text that is genuinely in capitals renders it lowercase, but the capitals are still in your HTML, and every tool that reads the page still sees them.
The copy-paste test. Select an uppercased heading on any site and paste it into a text field. If it pastes in mixed case, the site is using text-transform. If it pastes in capitals, the capitals are in the HTML. That one test tells you which problem you are looking at, and therefore whether CSS or a converter is the fix.
Accessibility: what a screen reader hears
This is the part that decides whether text-transform: uppercase is safe or harmful, and the answer depends on the reader.
Because the property changes only presentation, a screen reader receives the original text and usually announces it normally. That is the good news, and it is the main argument for using CSS rather than typing a heading in capitals. Some screen reader and browser combinations, however, read the transformed text, and a short all-capital string can then be announced letter by letter because the software takes it for an acronym. A navigation item styled MENU can be read as M, E, N, U.
| Approach | Screen reader | Copy and paste | Verdict |
|---|---|---|---|
| Capitals typed in the HTML | May spell short words out | Pastes in capitals | Avoid |
text-transform: uppercase | Usually correct | Pastes in the original case | Preferred |
font-variant: small-caps | Correct | Original case | Good for a subtle effect |
The practical rule: never type a heading in capitals. Write it in sentence case and let CSS uppercase it. If the design changes later, one line of CSS changes with it and no content has to be rewritten. The reading-speed cost of capitals is real either way, and it is explained in uppercase vs lowercase.
text-transform and search engines
Google reads the HTML, not the rendered capitals. A title tag written in sentence case and displayed in capitals by CSS is indexed in sentence case, and it appears in search results in sentence case, because the results page uses your markup rather than your stylesheet.
This surprises people who style an H1 with text-transform: uppercase and then wonder why the search snippet does not match the page. Nothing is wrong: the snippet is showing the real text. Capitalization is not a ranking factor in either direction, so the only thing at stake is how the result reads to a human, which is discussed in should all letters in a title be capitalized.
Where each approach belongs
| Situation | Use |
|---|---|
| A heading the design wants in capitals | text-transform: uppercase |
| Button labels in capitals | text-transform: uppercase |
| A table header row | text-transform: uppercase plus letter-spacing |
| Normalizing user input before saving | JavaScript, not CSS |
| Cleaning a database column | SQL or a converter |
| Fixing a document typed in caps | A converter; the data must change |
| A slug or URL | Lowercase at the source |
Rows one to three are presentation and belong in the stylesheet. Rows four to seven are data and must not be solved with CSS, because the underlying value is what gets saved, compared, exported and indexed.
Two related properties worth knowing
font-variant-caps: small-capsrenders lowercase letters as small capitals while leaving real capitals full height. It is a typographic effect rather than a case change, and in a font with true small caps it looks considerably better than shrinking capitals by hand.::first-letterstyles the first letter of a block, which is how drop caps are made. Combined withtext-transform: uppercaseon that pseudo-element, it capitalizes the opening letter of a paragraph without touching the text.
Neither changes the characters either. If you need the stored value to change, the work happens in JavaScript, in the database, or in a converter before the text is saved. The JavaScript equivalents are toUpperCase() and toLowerCase(), with the locale caveats described in the lowercase converter guide.
CSS for the look, a converter for the data. Use text-transform in the stylesheet, and the upper lower case converter when the characters themselves have to change. Twelve styles, acronym protection, live count.
Five patterns from real stylesheets
| Pattern | CSS | Why |
|---|---|---|
| Eyebrow label above a heading | text-transform:uppercase;letter-spacing:.08em;font-size:12px | Capitals need extra letter spacing to stay readable at small sizes |
| Table header row | text-transform:uppercase;font-weight:700 | Short labels, so the reading cost is low |
| Button text | text-transform:uppercase | Common in older design systems; modern ones prefer sentence case |
| Normalizing a tag list | text-transform:lowercase | Tags entered by users arrive in mixed case |
| Abbreviation with small caps | font-variant-caps:small-caps | Keeps capitals from shouting inside a paragraph |
The first row is the one people get wrong. Capital letters set at a small size with default spacing are noticeably harder to read, because the letterforms are all the same height and sit tightly together. Adding letter-spacing of about 0.05 to 0.1em fixes most of it, and it is the reason well-made eyebrow labels look calm while quick ones look cramped. The underlying readability question is covered in the art of uppercase and lowercase writing.
Inheritance, and turning it off
text-transform is inherited, so setting it on a container applies it to every descendant. That is usually what you want on a heading and rarely what you want on a card.
To exempt a child, set text-transform: none on it. This is how you keep a product code in its original case inside an uppercased block, or stop a nested input from displaying its value in capitals.
Never uppercase a form field. Applying text-transform: uppercase to an input makes the typing look uppercase while the value submitted stays exactly as typed. Users believe they entered capitals, the server receives lowercase, and the mismatch only surfaces later. If the value must be uppercase, transform it in JavaScript on submit or normalize it on the server.
Four bugs worth knowing
- capitalize acts on every word, including after a hyphen. state-of-the-art renders as State-Of-The-Art. There is no way to stop that in CSS.
- capitalize does not fix mid-word capitals. iPhone stays IPhone only if you typed it that way; the property capitalizes the first letter and leaves the rest, so what you typed is what you see from the second character on.
- uppercase can break a layout. Capital letters are wider. A navigation bar that fits in lowercase can wrap once uppercased, and the effect is worse in languages with longer words.
- Transformed text is still searchable in its original form. A browser find on the page matches the source text, not what is painted, which surprises people testing an uppercased heading.
Language matters
Uppercasing and lowercasing are not the same operation in every language, and the browser follows the lang attribute of the element.
| Text | lang | text-transform: uppercase |
|---|---|---|
| istanbul | en | ISTANBUL |
| istanbul | tr | The dotted i maps to the dotted capital |
| strasse with an eszett | de | The eszett becomes SS |
| A Greek word with a final sigma | el | Accents are dropped, as Greek typography requires |
Setting lang correctly on the html element is what makes these work. It costs one attribute and it is the difference between a correctly uppercased German or Turkish page and a subtly wrong one. The same trap appears in code, where an invariant lowercase is needed for comparisons; that is explained in the lowercase converter guide, and the Greek letter pairs are listed in upper and lower case Greek letters.
CSS or a converter: the decision
One question settles it: does the stored text need to change?
If the answer is no, and you only want the page to look different, use CSS. It is reversible, it costs one line, and the content stays readable for search engines, screen readers and anyone who copies it. If the answer is yes, because the value will be saved, exported, compared or sent somewhere, CSS is the wrong tool and a case converter is the right one. The same logic decides between Capitalize Each Word and real Title Case for headings, and between styling and rewriting a document in Google Docs.
Frequently asked questions
What does text-transform do in CSS?
It changes how text is displayed without changing the text itself. The values uppercase, lowercase and capitalize control the rendering; the HTML source and anything that reads it stay unchanged.
Does text-transform change the actual text?
No. Copying an uppercased heading gives you the original capitalization, and JavaScript reading the element gets the original too. Only the painted pixels change.
How do I capitalize the first letter of each word in CSS?
Use text-transform: capitalize. Unlike Excel PROPER or Python title(), it leaves the rest of each word alone, so HTML stays HTML.
Can CSS do sentence case?
No. There is no sentence case value because CSS has no concept of a sentence. The closest is the ::first-letter pseudo-element, which styles only the first letter of a block.
Is text-transform uppercase bad for accessibility?
It is safer than typing capitals in the HTML, because a screen reader normally receives the original text. Some combinations read the transformed text and may spell short all-capital words letter by letter.
Does text-transform affect SEO?
No. Google reads the HTML rather than the rendered result, so a title styled in capitals is still indexed in its source capitalization and appears that way in search results.
What is the difference between text-transform uppercase and small-caps?
Uppercase makes every letter a full-size capital. font-variant-caps: small-caps renders lowercase letters as small capitals and leaves real capitals full height, which is a typographic effect rather than a case change.
How do I remove text-transform?
Set text-transform: none on the element. That returns it to the text as written in the HTML.
The short version
text-transform changes appearance, never data. Use uppercase, lowercase and capitalize for headings, buttons and table headers, and write the underlying text in sentence case so it stays readable everywhere else. CSS cannot do sentence case or real Title Case, and it will not fix a document that was typed in capitals, because the capitals are still there. For that, change the characters with a converter.