158

Here is my HTML:

<a href="#" class="link">small caps</a> & 
<a href="#" class="link">ALL CAPS</a>

Here is my CSS:

.link {text-transform: capitalize;}

The output is:

Small Caps & ALL CAPS

and I want the output to be:

Small Caps & All Caps

Any ideas?

Volker E.
  • 5,911
  • 11
  • 47
  • 64
Khan
  • 2,912
  • 3
  • 21
  • 21
  • 1
    @Marcel - it doesn't need to be, it is followed by a space, so it is a perfectly valid literal ampersand (unless the document is XHTML, but there is no suggestion it is) – Quentin Aug 12 '10 at 19:36
  • 1
    @David – Oh, I didn't know this was a valid notation, too. Thanks, there's always something new to learn. – Marcel Korpel Aug 12 '10 at 19:42

15 Answers15

231

You can almost do it with:

.link {
  text-transform: lowercase;
}
.link:first-letter,
.link:first-line {
  text-transform: uppercase;
}

It will give you the output:

Small Caps
All Caps
Mario Petrovic
  • 7,500
  • 14
  • 42
  • 62
Philihp Busby
  • 4,389
  • 4
  • 23
  • 19
  • 7
    it works like a charm, thank you!, the order is important, the line with :first-letters has to be after the lowercase line. – Steven Lizarazo Oct 01 '13 at 16:50
  • 12
    This seems to require .link elements are displayed as block elements. (display:inline-block;) http://jsfiddle.net/7y7wqqhb/1/ – Torin Finnemann Sep 29 '14 at 12:55
  • 13
    But it doesn't produce desired result. It capitalize the first letter of element only while question asks to capitalize first letter of each word. It produces 'All caps' but required is 'All Caps' – manpreet Oct 14 '15 at 12:52
  • 2
    @manpreetsingh correct, that is why I said it *almost* works. It may not be exactly what the question asked, but often your spec is flexible and a simpler solution is preferable. – Philihp Busby Mar 07 '16 at 20:09
  • I suppose you convert the string to an array, then wrap it in a span with the classes and the concat it again. But that is tedious – Aaron Matthews Jun 29 '17 at 07:04
  • Perfect! This is actually exactly what I wanted. In the UK we usually refer capitalisation to just the first letter anyway. – Nabil Freeman Nov 26 '19 at 15:50
  • 1
    See [JDuarteDJ's answer below](https://stackoverflow.com/a/54711164/673414), which applies the `::first-line` pseudo-element selector to achieve "All Caps" as desired. – Dave Land Apr 02 '20 at 20:57
  • Use this `.link:first-letter, .link:first-line { text-transform: uppercase; }` – Malik Zahid Dec 14 '20 at 07:09
  • For a single element with multiple words, I used: `.link { text-transform: lowercase } .link:first-line { text-transform: capitalize }` – Omar Shishani Jun 14 '23 at 15:20
62

There is no way to do this with CSS, you could use PHP or Javascript for this.

PHP example:

$text = "ALL CAPS";
$text = ucwords(strtolower($text)); // All Caps

jQuery example (it's a plugin now!):

// Uppercase every first letter of a word
jQuery.fn.ucwords = function() {
  return this.each(function(){
    var val = $(this).text(), newVal = '';
    val = val.split(' ');

    for(var c=0; c < val.length; c++) {
      newVal += val[c].substring(0,1).toUpperCase() + val[c].substring(1,val[c].length) + (c+1==val.length ? '' : ' ');
    }
    $(this).text(newVal);
  });
}

$('a.link').ucwords();​
Harmen
  • 22,092
  • 4
  • 54
  • 76
43

Convert with JavaScript using .toLowerCase() and capitalize would do the rest.

ronnyfm
  • 1,973
  • 25
  • 31
  • 1
    Yep. I iterated the items in the model and converted them toLowerCase, like myArray[i].firstName = myArray[i]firstName.toLowerCase() Then in the css, text-transform: capitalize – pdschuller Mar 14 '16 at 20:08
  • OP doesn't mention JS. – JDuarteDJ Feb 15 '19 at 14:56
  • Thanks for the input, but the question did not limit the approach to CSS only. – ronnyfm Feb 19 '19 at 17:38
  • Can you please remove @JDuarteDJ the down vote? Again, my answer is accordingly to what was questioned. And if you see what was selected as answer also uses JavaScript, even jQuery. Thanks. – ronnyfm Feb 28 '19 at 17:58
26

Interesting question!

capitalize transforms every first letter of a word to uppercase, but it does not transform the other letters to lowercase. Not even the :first-letter pseudo-class will cut it (because it applies to the first letter of each element, not each word), and I can't see a way of combining lowercase and capitalize to get the desired outcome.

So as far as I can see, this is indeed impossible to do with CSS.

@Harmen shows good-looking PHP and jQuery workarounds in his answer.

Pekka
  • 442,112
  • 142
  • 972
  • 1,088
  • 1
    Strange, I expected adding 'a {text-transform:lowercase}' would work. But it doesn't. – Kwebble Aug 12 '10 at 20:00
  • 1
    This answer answers why it's happening. :) That's better than solutions. – Asim K T Jun 15 '16 at 07:23
  • Very good explanation @Pekka 웃 some unexpected behaviour from CSS. Let's hope there is a correction in the pipeline. – Aaron Matthews Jun 29 '17 at 06:59
  • 1
    @Pekka 웃 I provided an answer that does come very close to doing this purely in CSS. There is a once per line limitation but I think it suits most cases. – JDuarteDJ Feb 15 '19 at 17:35
20

I'd like to sugest a pure CSS solution that is more useful than the first letter solution presented but is also very similar.

.link {
  text-transform: lowercase;
display: inline-block;
}

.link::first-line {
  text-transform: capitalize;
}
<div class="link">HELLO WORLD!</div>
<p class="link">HELLO WORLD!</p>
<a href="#" class="link">HELLO WORLD!  ( now working! )</a>

Although this is limited to the first line it may be useful for more use cases than the first letter solution since it applies capitalization to the whole line and not only the first word. (all words in the first line) In the OP's specific case this could have solved it.

Notes: As mentioned in the first letter solution comments, the order of the CSS rules is important! Also note that I changed the <a> tag for a <div> tag because for some reason the pseudo-element ::first-line doesn't work with <a> tags natively but either <div> or <p> are fine. EDIT: the <a> element will work if display: inline-block; is added to the .link class. Thanks to Dave Land for spotting that!

New Note: if the text wraps it will loose the capitalization because it is now in fact on the second line (first line is still ok).

JDuarteDJ
  • 1,073
  • 12
  • 25
6

JavaScript:

var links = document.getElementsByClassName("link");
for (var i = 0; i < links.length; i++) {
  links[i].innerHTML = links[i].innerHTML.toLowerCase();
}

CSS:

.link { text-transform: capitalize; }

What Khan "ended up doing" (which is cleaner and worked for me) is down in the comments of the post marked as the answer.

ryanttb
  • 1,278
  • 13
  • 20
5

captialize only effects the first letter of the word. http://www.w3.org/TR/CSS21/text.html#propdef-text-transform

prodigitalson
  • 60,050
  • 10
  • 100
  • 114
  • 1
    This answer is not constructive in spite the fact that is provides an explanation towards why the OP is having the issue. – JDuarteDJ Feb 15 '19 at 17:33
  • @JDuarteDJ I think it is important to know the source problem, which is the case. captialize do not normalize strings, but only gets the first item ánd transforms it in a uppercase letter. I found this information indeed useful – Rodrigo Borba Mar 06 '20 at 19:45
4

You can do it with css first-letter! eg I wanted it for the Menu:

a {display:inline-block; text-transorm:uppercase;}
a::first-letter {font-size:50px;}

It only runs with block elements - therefore the inline-block!

René Höhle
  • 26,716
  • 22
  • 73
  • 82
Johannes
  • 49
  • 1
3

May be useful for java and jstl.

  1. Initialize variable with localized message.
  2. After that it is possible to use it in jstl toLowerCase function.
  3. Transform with CSS.

In JSP

1.

<fmt:message key="some.key" var="item"/>

2.

<div class="content">
  <a href="#">${fn:toLowerCase(item)}</a>
</div>

In CSS

3.

.content {
  text-transform:capitalize;
}
ekar
  • 137
  • 4
2

If the data is coming from a database, as in my case, you can lower it before sending it to a select list/drop down list. Shame you can't do it in CSS.

JohnnyBizzle
  • 971
  • 3
  • 17
  • 31
1

After researching a lot I found jquery function/expression to change text in first letter in uppercase only, I modify that code accordingly to make it workable for input field. When you will write something in input field and then move to another filed or element, the text of that field will change with 1st-letter capitalization only. No matter user type text in complete lower or upper case capitalization:

Follow this code:

Step-1: Call jquery library in html head:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>

Step-2: Write code to change text of input fields:

<script>
$(document).ready(function(){
$("#edit-submitted-first-name,#edit-submitted-last-name,#edit-submitted-company-name, #edit-submitted-city").focusout(function(){
var str=$(this).val();
str = str.toLowerCase().replace(/\b[a-z]/g, function(letter) {
    return letter.toUpperCase();
});
$(this).val(str);
 });});

 </script>

Step-3: Create HTML input fields with same id's you use in jquery code like:

<input type="text" id="edit-submitted-first-name" name="field name">

The id of this input field is: edit-submitted-first-name (It using in jquery code in step-2)

**Result: Make sure the text will change after you move your focus from that input field at another element. Because we using focus out event of jquery here. Result should like this: User Type: "thank you" it will change with "Thank You". **

Best of luck

A.Aleem11
  • 1,844
  • 17
  • 12
0

The PHP solution, in backend:

$string = 'UPPERCASE';
$lowercase = strtolower($string);
echo ucwords($lowercase);
Fellipe Sanches
  • 7,395
  • 4
  • 32
  • 33
-1

I know this is a late response but if you want to compare the performance of various solutions I have a jsPerf that I created.

Regex solutions are the fastest for sure.

Here is the jsPerf: https://jsperf.com/capitalize-jwaz

There are 2 regex solutions.

The first one uses/\b[a-z]/g. Word boundary will capital words such as non-disclosure to Non-Disclosure.

If you only want to capitalize letters that are preceded by a space then use the second regex

/(^[a-z]|\s[a-z])/g
Zerry Hogan
  • 183
  • 2
  • 14
-1

if you are using jQuery; this is one a way to do it:

$('.link').each(function() {
    $(this).css('text-transform','capitalize').text($(this).text().toLowerCase());
});

Here is an easier to read version doing the same thing:

//Iterate all the elements in jQuery object
$('.link').each(function() {

    //get text from element and make it lower-case
    var string = $(this).text().toLowerCase();

    //set element text to the new string that is lower-case
    $(this).text(string);

    //set the css to capitalize
    $(this).css('text-transform','capitalize');
});

Demo

fooaldrin
  • 1
  • 2
-6

all wrong it does exist --> font-variant: small-caps;

text-transform:capitalize; just the first letter cap

Orlando
  • 9
  • 1
  • 4
  • That is not at all what the OP wanted. He expects the output to only have the first letters of the words capitalized; not the whole string. – Andrew Barber Feb 07 '13 at 19:32
  • There's a nuance in the question you are not perceiving: `text-transform: capitalize;` does not alter text that is already all caps. See the question again: The user already tried that. – Andrew Barber Feb 08 '13 at 16:43
  • then can use span tag to breakup which words they want all caps and small caps. – Orlando Feb 08 '13 at 16:57