226

What is the best approach to capitalize words in a string?

Damjan Pavlica
  • 31,277
  • 10
  • 71
  • 76
vsync
  • 118,978
  • 58
  • 307
  • 400
  • 73
    If it's for display, use CSS. `text-transform:capitalize;`. – kennytm Feb 25 '10 at 09:17
  • 4
    this is to be used to set "title" attribute to DOM elements. no CSS :) – vsync Feb 25 '10 at 09:29
  • 1
    Also, I've asked this question, although I know the solution, just because I tried looking for it in this website and couldn't find a decent solution, so added it for the sake of documentation. – vsync Feb 25 '10 at 09:30
  • 2
    @KennyTM: text-transform would not really capitalize form's fieds' values, all values would be presented capitalized, but sent to server as they are. – Marco Demaio Mar 04 '11 at 18:44
  • 8
    @Marco: Yes, that's why I said "If it's for display". – kennytm Mar 04 '11 at 20:03
  • `text-transform` is cool, but check browser compatibility before relying solely on it: [Can I use...](http://caniuse.com/#search=text-transform) – Lars Gyrup Brink Nielsen Mar 25 '14 at 11:37
  • @LayZee - what are you talking about? check your facts bro, it has been supported since the late 90's more or less. and your link doesn't even work, it's not on *caniuse.com* – vsync Sep 23 '14 at 08:26
  • @vsync Obviously the feature was on the older version of Can I use. Surely, it has been supported since CSS Level 1, but in an unpredictable manner (different implementations for each browser). Actually, according to [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/text-transform#Browser_notes), it is not quite right yet and something that is still being refined. – Lars Gyrup Brink Nielsen Sep 24 '14 at 19:59
  • @LayZee - well I say it's fine. been using it for 10 years now. never seen a problem. on any platform or browser. they are probably talking about hindo or other exotic typography which it might break things. in English it's totally fine. – vsync Sep 24 '14 at 20:33
  • @vsync Sure, English will be fine, but it's nice to be aware of potential problems when developing multilingual websites. A lot of European countries have special letters as well. Anyway, thanks for this topic. – Lars Gyrup Brink Nielsen Sep 25 '14 at 22:48
  • If string is already all upper-case, you may need to do `string.toLowerCase()` and then apply `text-transform: capitalize;` – conner.xyz Feb 19 '15 at 03:24
  • @kennytm that's a very nice solution but sadly those of using React Native don't have that CSS property. – cbartondock Apr 26 '17 at 19:47

21 Answers21

328
/**
 * Capitalizes first letters of words in string.
 * @param {string} str String to be modified
 * @param {boolean=false} lower Whether all other letters should be lowercased
 * @return {string}
 * @usage
 *   capitalize('fix this string');     // -> 'Fix This String'
 *   capitalize('javaSCrIPT');          // -> 'JavaSCrIPT'
 *   capitalize('javaSCrIPT', true);    // -> 'Javascript'
 */
const capitalize = (str, lower = false) =>
  (lower ? str.toLowerCase() : str).replace(/(?:^|\s|["'([{])+\S/g, match => match.toUpperCase());
;

  • fixes Marco Demaio's solution where first letter with a space preceding is not capitalized.
capitalize(' javascript'); // -> ' Javascript'
  • can handle national symbols and accented letters.
capitalize('бабушка курит трубку');  // -> 'Бабушка Курит Трубку'
capitalize('località àtilacol')      // -> 'Località Àtilacol'
  • can handle quotes and braces.
capitalize(`"quotes" 'and' (braces) {braces} [braces]`);  // -> "Quotes" 'And' (Braces) {Braces} [Braces]
disfated
  • 10,633
  • 12
  • 39
  • 50
  • +1 cool, and thanks fo the bug fix!!! May I ask why you added the `?:` in order not to capture the match, is it a small speed improvement? – Marco Demaio Oct 01 '11 at 16:49
  • Is `?:` a performance boost or just premature opt? Clearer without it I think. – djechlin May 22 '13 at 18:28
  • 4
    regexp works like "Take all non-whitespace characters (\S) standing right at the begining of string (^) or after any whitespace character (\s) and uppercase them" – disfated May 31 '13 at 20:01
  • 3
    A little enhancement to handle the upper case strings :) ** String.prototype.capitalize = function() { return this.toLowerCase().replace(/(?:^|\s)\S/g, function(a) { return a.toUpperCase(); }); }; ** – SuryaPavan Aug 06 '14 at 07:35
  • Thanks for the great solution. How can we exclude acronyms from this? Any idea, hint will help. Thanks! – userx May 04 '15 at 20:09
  • It fails when we have a single quote inside the string. For example, "abc & 'xyz and pqr' " gives "Abc & 'xyz And Pqr' ". – Rahul Raval Sep 10 '19 at 14:23
  • @RahulRaval, use `/(?:^|["'\s])\S/g` to handle quotes and possible other desired word-separator charaters. – disfated Sep 12 '19 at 09:51
  • awesome solution! but it's not capitalize words after `(` `[` `"` – Systems Rebooter Dec 14 '19 at 13:11
  • 1
    Please don't alter the prototypes of existing objects. – Ascherer Jan 02 '20 at 03:13
  • when string is ALREADY CAPSED, it makes capitals capitalized, but does not make another letters lowercased – Dr.X Jan 14 '20 at 09:17
  • 1
    @Dr.X, see add-on, `'CHECK THIS OUT'.capitalize(true) -> "Check This Out"`. Mind `true` parameter. – disfated Jan 16 '20 at 02:53
  • While this may have been a good solution a decade back, it informs the reader that modifying prototypes is okay and is doable! Please do not modify built in object prototypes. This answer should not be the selected answer in 2020. – SeaWarrior404 Apr 19 '20 at 04:45
  • 1
    @SeaWarrior404, you are right, updated my answer with es6 syntax, added jsdoc and some punctuation treatment – disfated Apr 21 '20 at 01:38
278

The shortest implementation for capitalizing words within a string is the following using ES6's arrow functions:

'your string'.replace(/\b\w/g, l => l.toUpperCase())
// => 'Your String'

ES5 compatible implementation:

'your string'.replace(/\b\w/g, function(l){ return l.toUpperCase() })
// => 'Your String'

The regex basically matches the first letter of each word within the given string and transforms only that letter to uppercase:

  • \b matches a word boundary (the beginning or ending of word);
  • \w matches the following meta-character [a-zA-Z0-9].

For non-ASCII characters refer to this solution instead

'ÿöur striñg'.replace(/(^|\s)\S/g, l => l.toUpperCase())

This regex matches the first letter and every non-whitespace letter preceded by whitespace within the given string and transforms only that letter to uppercase:

  • \s matches a whitespace character
  • \S matches a non-whitespace character
  • (x|y) matches any of the specified alternatives

A non-capturing group could have been used here as follows /(?:^|\s)\S/g though the g flag within our regex wont capture sub-groups by design anyway.

starball
  • 20,030
  • 7
  • 43
  • 238
ivoputzer
  • 6,427
  • 1
  • 25
  • 43
  • 1
    Could you explain in the answer how the regex works? (the meaning of each piece) – vsync Jul 22 '16 at 16:52
  • it basically matches the first letter of each word and transforms it to uppercase. \b matches a word boundary, \w matches the following metacharacter (a-Z0-9) @vsync if u like this solution consider upvoting. thanks – ivoputzer Jul 22 '16 at 17:00
  • 2
    I will select it as the answer if the explanation be inside it and not as a comment one could miss. – vsync Jul 22 '16 at 17:10
  • i added some further description and references to the answer, hope its good enough. thanks @vsync – ivoputzer Jul 22 '16 at 17:31
  • 3
    This doesn't seem to work for nordic characters ä, ö, and å. For example `päijät-häme` becomes `PäIjäT-HäMe` – Markus Meskanen Dec 15 '16 at 12:18
  • 2
    This solution isn't a good one for international content containing diacritic / non-latin characters. `EisbäRen` is one result, for instance. – Daniel B. Jan 10 '17 at 10:22
  • @MarkusMeskanen i just updated the answer to include a working solution for that kind of scenario. – ivoputzer Nov 17 '17 at 15:12
  • 4
    The example from @MarkusMeskanen should change to `Päijät-Häme`, but at least in Chrome whitespace doesn't include the dash (-), so the second part of the name is not capitalized. Can be fixed as `/(^|\s|-)\S/g`. – MiRin Oct 07 '18 at 19:40
  • For the non-ASCII solution, you probably want `toLocaleUpperCase`. Otherwise excellent solution, thanks! – GrandOpener Jun 28 '23 at 16:05
38
function capitalize(s){
    return s.toLowerCase().replace( /\b./g, function(a){ return a.toUpperCase(); } );
};

capitalize('this IS THE wOrst string eVeR');

output: "This Is The Worst String Ever"

Update:

It appears this solution supersedes mine: https://stackoverflow.com/a/7592235/104380

Community
  • 1
  • 1
vsync
  • 118,978
  • 58
  • 307
  • 400
  • 1
    watch out that it seems your function wrongly capitalizes also accented letters, see my answer: http://stackoverflow.com/questions/2332811/capitalize-words-in-string/5678673#5678673 I also protoyped it. – Marco Demaio Apr 15 '11 at 15:05
  • 10
    I don't like prototyping, it has the potential to create collisions is someone else is using the same name to prototype String as well. – vsync Dec 14 '11 at 08:35
16

The answer provided by vsync works as long as you don't have accented letters in the input string.

I don't know the reason, but apparently the \b in regexp matches also accented letters (tested on IE8 and Chrome), so a string like "località" would be wrongly capitalized converted into "LocalitÀ" (the à letter gets capitalized cause the regexp thinks it's a word boundary)

A more general function that works also with accented letters is this one:

String.prototype.toCapitalize = function()
{ 
   return this.toLowerCase().replace(/^.|\s\S/g, function(a) { return a.toUpperCase(); });
}

You can use it like this:

alert( "hello località".toCapitalize() );
Community
  • 1
  • 1
Marco Demaio
  • 33,578
  • 33
  • 128
  • 159
10

A simple, straightforward (non-regex) solution:

const capitalizeFirstLetter = s => 
  s.split(' ').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ')
  1. Break the string into words Array (by space delimiter)
  2. Break each word to first character + rest of characters in the word
  3. The first letter is transformed to uppercase, and the rest remains as-is
  4. Joins back the Array into a string with spaces
vsync
  • 118,978
  • 58
  • 307
  • 400
Otman
  • 111
  • 2
  • 7
  • I think you can avoid the iteration, just do `function capitalize(s){ let _s = s.trim().toLowerCase(); return _s.charAt(0).toUpperCase() + _s.slice(1) }` – miguelps Mar 14 '21 at 16:07
8

Ivo's answer is good, but I prefer to not match on \w because there's no need to capitalize 0-9 and A-Z. We can ignore those and only match on a-z.

'your string'.replace(/\b[a-z]/g, match => match.toUpperCase())
// => 'Your String'

It's the same output, but I think clearer in terms of self-documenting code.

Big Money
  • 9,139
  • 6
  • 26
  • 37
  • 2
    @vsync that seems pretty harsh. it is an optimization to the accepted answer. `/\b\w/g` also fails for non-english letters. Not everyone deals with unicode characters, and this will help out those who want do not. – Big Money Feb 25 '19 at 18:04
5

Since everyone has given you the JavaScript answer you've asked for, I'll throw in that the CSS property text-transform: capitalize will do exactly this.

I realize this might not be what you're asking for - you haven't given us any of the context in which you're running this - but if it's just for presentation, I'd definitely go with the CSS alternative.

David Hedlund
  • 128,221
  • 31
  • 203
  • 222
  • KennyTM beat you to it. Check his comment on the question section. :-) – Buhake Sindi Feb 25 '10 at 09:26
  • Yes, I know this CSS attribute, but I need this for title attribute to dom elements, and it has no CSS what so ever, as you may know. – vsync Feb 25 '10 at 09:28
5

My solution:

String.prototype.toCapital = function () {
    return this.toLowerCase().split(' ').map(function (i) {
        if (i.length > 2) {
            return i.charAt(0).toUpperCase() + i.substr(1);
        }

        return i;
    }).join(' ');
};

Example:

'álL riGht'.toCapital();
// Returns 'Áll Right'
Erick Tatsui
  • 67
  • 1
  • 3
4

Using JavaScript and html

String.prototype.capitalize = function() {
  return this.replace(/(^|\s)([a-z])/g, function(m, p1, p2) {
    return p1 + p2.toUpperCase();
  });
};
<form name="form1" method="post">
  <input name="instring" type="text" value="this is the text string" size="30">
  <input type="button" name="Capitalize" value="Capitalize >>" onclick="form1.outstring.value=form1.instring.value.capitalize();">
  <input name="outstring" type="text" value="" size="30">
</form>

Basically, you can do string.capitalize() and it'll capitalize every 1st letter of each word.

Source: http://www.mediacollege.com/internet/javascript/text/case-capitalize.html

Pugazh
  • 9,453
  • 5
  • 33
  • 54
Buhake Sindi
  • 87,898
  • 29
  • 167
  • 228
  • 1
    I am not a fan of prototyping this way, because my scripts sometimes are 3rd party embeds in other websites, and that can cause trouble messing with global object like "String"...so I prefer to "fucntion" it instead. – vsync Feb 25 '10 at 09:33
  • 1
    That's the beauty of prototype (not the Prototype you download). It's standard in javascript and works in all browsers. – Buhake Sindi Feb 25 '10 at 09:43
  • I suspect it can cause problems if somebody else already prototyped his own String.prototype.capitalize, and I will accidentally override it. – vsync Mar 24 '10 at 08:19
  • 1
    @vsync, you can always check by doing this. `if (object.capitalize) {...} else {String.prototype.capitalize = function()....}` where object is of type `String`. So, it's quite simple really. – Buhake Sindi Mar 24 '10 at 10:36
4

John Resig (of jQuery fame ) ported a perl script, written by John Gruber, to JavaScript. This script capitalizes in a more intelligent way, it doesn't capitalize small words like 'of' and 'and' for example.

You can find it here: Title Capitalization in JavaScript

meouw
  • 41,754
  • 10
  • 52
  • 69
4

If you're using lodash in your JavaScript application, You can use _.capitalize:

console.log( _.capitalize('ÿöur striñg') );
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>
vsync
  • 118,978
  • 58
  • 307
  • 400
vicke4
  • 2,973
  • 1
  • 20
  • 20
2

This should cover most basic use cases.

const capitalize = (str) => {
    if (typeof str !== 'string') {
      throw Error('Feed me string')
    } else if (!str) {
      return ''
    } else {
      return str
        .split(' ')
        .map(s => {
            if (s.length == 1 ) {
                return s.toUpperCase()
            } else {
                const firstLetter = s.split('')[0].toUpperCase()
                const restOfStr = s.substr(1, s.length).toLowerCase()
                return firstLetter + restOfStr
            }     
        })
        .join(' ')
    }
}


capitalize('THIS IS A BOOK') // => This Is A Book
capitalize('this is a book') // => This Is A Book
capitalize('a 2nd 5 hour boOk thIs weEk') // => A 2nd 5 Hour Book This Week

Edit: Improved readability of mapping.

Drops
  • 2,680
  • 18
  • 16
  • Can you please explain why do you think your answer is better than others from many years ago? – vsync Aug 30 '18 at 06:38
  • Can you explain why did you think that I meant that my answer is the best/or better than others? I didn't mentioned that, it's just different. Also I didn't see you leave this comment on other posts, so I really don't get it. But for starters: it uses moderns js features (destructuring, fat arrow, implicit return), it doesn't use regx and it's a more functional approach to the problem. Also it has very basic error handling and returns empty string if you pass it one (to me that was important). – Drops Aug 30 '18 at 11:26
  • 1
    it's ok to be different but it has to be *better* or equal to to other answers, and it appears to be... unreadable and certainly nothing one would put in production code because nobody would be able to understand it – vsync Aug 30 '18 at 11:35
  • Ahhh ok, so 50% of solutions here which monkeypatch String you will actually put in production? Or maybe convoluted regex expressions? Those are much easier to reason with, right? Imho absolutely not! Also saying that nobody will understand this is quite subjective statement. Also [for this](https://johnresig.com/files/titleCaps.js) you said that is shredded piece of code (more features but that's not the case here). How so that that is shredded and my solution nobody will understand? There is no way that you will untangle those regexes without losing hours. – Drops Aug 30 '18 at 11:59
  • That code was written by Mr. Resig himself and should not be questioned. You, on the other hand lack the credibility, due to your anonymity. Regardless, a Regex solution is shorter, runs *much faster* and also easily read by anyone learnt in the basics of Regex. There's hardly much to "untangle" in this: `/\b\w/g` ... – vsync Aug 30 '18 at 12:42
  • First, everything should be questioned. Second, I'ts interesting how you judge code readability by authors credibility, code is either readable or it's not. John also wrote [prettyjs](https://johnresig.com/files/pretty.js) which pushes short circuiting >9000. This code ended in production on many sites. Regardless, I didn't compare my solution to simple regex from top answer but to the link in my previous comment - for which you said that is 'shredded code'. Accepted answer is elegant and simple, no doubt, but I didn't wanted to use regex (be that for fun or some other reason). – Drops Aug 30 '18 at 13:35
  • Ok, cool, I respect and understand that. Do you have a Github perhaps? – vsync Aug 30 '18 at 14:28
  • Yes, but with no interesting public repos, sry. – Drops Aug 31 '18 at 13:35
1

This solution dose not use regex, supports accented characters and also supported by almost every browser.

function capitalizeIt(str) {
    if (str && typeof(str) === "string") {
        str = str.split(" ");    
        for (var i = 0, x = str.length; i < x; i++) {
            if (str[i]) {
                str[i] = str[i][0].toUpperCase() + str[i].substr(1);
            }
        }
        return str.join(" ");
    } else {
        return str;
    }
}    

Usage:

console.log(capitalizeIt('çao 2nd inside Javascript programme'));

Output:

Çao 2nd Inside Javascript Programme

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Nabarag Paul
  • 319
  • 5
  • 19
  • 1
    This way consumes a lot of CPU resources. JavaScript doesn't change primitive values, that implies a creation of a new one each time a operation is performed. It's better use native functions like "replace', exempli gratia. – Daniel Bandeira Feb 22 '20 at 12:36
0

http://www.mediacollege.com/internet/javascript/text/case-capitalize.html is one of many answers out there.

Google can be all you need for such problems.

A naïve approach would be to split the string by whitespace, capitalize the first letter of each element of the resulting array and join it back together. This leaves existing capitalization alone (e.g. HTML stays HTML and doesn't become something silly like Html). If you don't want that affect, turn the entire string into lowercase before splitting it up.

Alan Plum
  • 10,814
  • 4
  • 40
  • 57
0

This code capitalize words after dot:

function capitalizeAfterPeriod(input) { 
    var text = '';
    var str = $(input).val();
    text = convert(str.toLowerCase().split('. ')).join('. ');
    var textoFormatado = convert(text.split('.')).join('.');
    $(input).val(textoFormatado);
}

function convert(str) {
   for(var i = 0; i < str.length; i++){
      str[i] = str[i].split('');
      if (str[i][0] !== undefined) {
         str[i][0] = str[i][0].toUpperCase();
      }
      str[i] = str[i].join('');
   }
   return str;
}
Flavio
  • 9
  • 1
0

I like to go with easy process. First Change string into Array for easy iterating, then using map function change each word as you want it to be.

function capitalizeCase(str) {
    var arr = str.split(' ');
    var t;
    var newt;
    var newarr = arr.map(function(d){
        t = d.split('');
        newt = t.map(function(d, i){
                  if(i === 0) {
                     return d.toUpperCase();
                    }
                 return d.toLowerCase();
               });
        return newt.join('');
      });
    var s = newarr.join(' ');
    return s;
  }
Mritunjay Upadhyay
  • 1,004
  • 1
  • 15
  • 27
0

Jquery or Javascipt doesn't provide a built-in method to achieve this.

CSS test transform (text-transform:capitalize;) doesn't really capitalize the string's data but shows a capitalized rendering on the screen.

If you are looking for a more legit way of achieving this in the data level using plain vanillaJS, use this solution =>

var capitalizeString = function (word) {    
    word = word.toLowerCase();
    if (word.indexOf(" ") != -1) { // passed param contains 1 + words
        word = word.replace(/\s/g, "--");
        var result = $.camelCase("-" + word);
        return result.replace(/-/g, " ");
    } else {
    return $.camelCase("-" + word);
    }
}
siwalikm
  • 1,792
  • 2
  • 16
  • 20
0

Use This:

String.prototype.toTitleCase = function() {
  return this.charAt(0).toUpperCase() + this.slice(1);
}

let str = 'text';
document.querySelector('#demo').innerText = str.toTitleCase();
<div class = "app">
  <p id = "demo"></p>
</div>
Sanjay
  • 540
  • 2
  • 13
  • 29
0

You can use the following to capitalize words in a string:

function capitalizeAll(str){

    var partes = str.split(' ');

    var nuevoStr = ""; 

    for(i=0; i<partes.length; i++){
    nuevoStr += " "+partes[i].toLowerCase().replace(/\b\w/g, l => l.toUpperCase()).trim(); 
    }    

    return nuevoStr;

}
Grant Miller
  • 27,532
  • 16
  • 147
  • 165
0

There's also locutus: https://locutus.io/php/strings/ucwords/ which defines it this way:

function ucwords(str) {
  //  discuss at: http://locutus.io/php/ucwords/
  // original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
  // improved by: Waldo Malqui Silva (http://waldo.malqui.info)
  // improved by: Robin
  // improved by: Kevin van Zonneveld (http://kvz.io)
  // bugfixed by: Onno Marsman (https://twitter.com/onnomarsman)
  // bugfixed by: Cetvertacov Alexandr (https://github.com/cetver)
  //    input by: James (http://www.james-bell.co.uk/)
  //   example 1: ucwords('kevin van  zonneveld')
  //   returns 1: 'Kevin Van  Zonneveld'
  //   example 2: ucwords('HELLO WORLD')
  //   returns 2: 'HELLO WORLD'
  //   example 3: ucwords('у мэри был маленький ягненок и она его очень любила')
  //   returns 3: 'У Мэри Был Маленький Ягненок И Она Его Очень Любила'
  //   example 4: ucwords('τάχιστη αλώπηξ βαφής ψημένη γη, δρασκελίζει υπέρ νωθρού κυνός')
  //   returns 4: 'Τάχιστη Αλώπηξ Βαφής Ψημένη Γη, Δρασκελίζει Υπέρ Νωθρού Κυνός'

  return (str + '').replace(/^(.)|\s+(.)/g, function ($1) {
    return $1.toUpperCase();
  });
};
geoidesic
  • 4,649
  • 3
  • 39
  • 59
0

I would use regex for this purpose:

myString = '  this Is my sTring.  ';
myString.trim().toLowerCase().replace(/\w\S*/g, (w) => (w.replace(/^\w/, (c) => c.toUpperCase())));
Abdulmoiz Ahmer
  • 1,953
  • 17
  • 39