828

Is there a simple way to convert a string to Title Case? E.g. john smith becomes John Smith. I'm not looking for something complicated like John Resig's solution, just (hopefully) some kind of one- or two-liner.

5
  • 1
    There are various methods, do we have some performance stats? Commented Oct 2, 2016 at 12:18
  • 1
    @theAnubhav yes we do have a benchmark now Commented Nov 19, 2020 at 10:57
  • 3
    It's the year 2022, and browsers still do not have a native function to do this. Commented Jun 30, 2022 at 3:23
  • 1
    Casing like this is 100% language/location/culture dependent. Commented Aug 10, 2022 at 20:54
  • 3
    I want one of the test cases for the solution to be "Comhrá i mBÁC le Seán Nguyen" - good luck with that one! Basically, the idea that there's something called "title casing" that a computer can do is probably hopeless, even given vast amounts of machine-learning resources. Commented Aug 10, 2022 at 21:11

70 Answers 70

1023

Use:

function toTitleCase(str) {
  return str.replace(
    /\w\S*/g,
    text => text.charAt(0).toUpperCase() + text.substring(1).toLowerCase()
  );
}

const example = 'john smith';
console.log(`"${example}" becomes "${toTitleCase(example)}"`);

Interactive example:

const input = document.querySelector('[name="input"]');
const output = document.querySelector('[name="output"]');

input.addEventListener('change', () => {
  output.value = toTitleCase(input.value);
});

input.addEventListener('keyup', () => {
  output.value = toTitleCase(input.value);
});

output.addEventListener('click', () => output.select());

function toTitleCase(str) {
  return str.replace(
    /\w\S*/g,
    text => text.charAt(0).toUpperCase() + text.substring(1).toLowerCase()
  );
}
<form>
  Input: <br/>
  <textarea name="input"></textarea>

  <br/>

  Output: <br/>
  <textarea name="output" readonly></textarea>
</form>

Sign up to request clarification or add additional context in comments.

25 Comments

Could anyone please explain, why \w\S* is used, instead of \w+ or \w* for example? I don't know, why you would want to include anything but spaces and therefore change Jim-Bob to Jim-bob.
@martinCzerwi the \w\S* also caused the Jim-bob problem on our end. Using \w* solved this.
/([^\W_]+[^\s-]*) */g solves the Jim-Bob problem, ie: jim-bob --> Jim-Bob
If the jim-bob --> Jim-Bob is your desire, you should probably do /\b\w+/g. Example: str.replace(/\b\w+/g,function(s){return s.charAt(0).toUpperCase() + s.substr(1).toLowerCase();});
\w\S* is used instead of \w+ or \w* so that words like Don't don't get modified to Don'T, but as others have pointed out \w\S* causes issues with hyphenated words.
|
360

If a CSS solution meets your needs, you can apply the text-transform CSS style to your controls:

text-transform: capitalize;

Just be aware that this will transform:
hello world to Hello World
HELLO WORLD to HELLO WORLD (no change)
emily-jane o'brien to Emily-jane O'brien (incorrect)
Maria von Trapp to Maria Von Trapp (incorrect)

13 Comments

-1. This css works, but doesn't work as most people expect because if the text starts out as all caps, there is no effect. webmasterworld.com/forum83/7506.htm
@Akshar : A lowercase rule would be replaced by a title case rule. Since css doesn't modify the source content, the effect is that the lowercase rule is removed (leaving the source content in all caps) and then the titlecase rule would be applied (doing nothing).
JS is used outside browsers.
The question was: "Is there a simple way to convert a string to title case?". This answer does not convert a string. This is a style applied atop a string.
+1 The question is vague and doesn't explain the use case. Maybe they had in mind converting the string with JS, but actually CSS works better for them, as is my case.
|
238

A slightly more elegant way, adapting Greg Dean's function:

String.prototype.toProperCase = function () {
    return this.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
};

Call it like:

"pascal".toProperCase();

9 Comments

Keep in mind if you have a user with a dash in their name and they enter Jo-Ann Smith, this code will convert them to Jo-ann Smith (note the lowercase a in Ann).
@daniellmb Why should he not alter the String prototype? I think it is a good solution. Think of ruby open classes, it is perfectly valid to add functions to existing classes and it is widely accepted.
@marco-fiset Because it doesn't play well with others! Bad things happen when you have 2 libraries that are both trying to modify native JavaScript objects with incompatible changes. Imagine if jQuery and Google Maps followed this design pattern, you couldn't have both on the same page.
@daniellmb An excellent point. Prefixing the method name should help avoid this, as will making the method non-enumerable.
I feel like the "don't modify native JavaScript objects" statement is just like "never use goto" or "eval is evil". There are plenty of cases where it is ok. If you have complete control over your project and of course don't plan on releasing it as a library, I see no problems with this method.
|
193

Here's my version, IMO it's easy to understand and elegant too.

const str = "foo bar baz";
const newStr = str.split(' ')
   .map(w => w[0].toUpperCase() + w.substring(1).toLowerCase())
   .join(' ');
console.log(newStr);

10 Comments

Alternatively, you can lowercase the substring in the mapping: str.split(' ').map(i => i[0].toUpperCase() + i.substring(1).toLowerCase()).join(' ')
I disagree with calling .toLowerCase(). Names such as "McDonald" or acronyms like "ASAP" should retain their uppercase characters. If someone actually passed in a string like "heLLO", the application shouldn't assume the uppercase letters are incorrect.
@ThomasHigginbotham How about this? String.prototype.toTitleCase = function (blnForceLower) { var strReturn; (blnForceLower ? strReturn = this.toLowerCase() : strReturn = this); return strReturn .split(' ') .map(i => i[0].toUpperCase() + i.substr(1)) .join(' '); }
This will break if str is a single character.
This looks like this is the fastest solution :)
|
124

Here’s my function that converts to title case but also preserves defined acronyms as uppercase and minor words as lowercase:

String.prototype.toTitleCase = function() {
  var i, j, str, lowers, uppers;
  str = this.replace(/([^\W_]+[^\s-]*) */g, function(txt) {
    return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
  });

  // Certain minor words should be left lowercase unless 
  // they are the first or last words in the string
  lowers = ['A', 'An', 'The', 'And', 'But', 'Or', 'For', 'Nor', 'As', 'At', 
  'By', 'For', 'From', 'In', 'Into', 'Near', 'Of', 'On', 'Onto', 'To', 'With'];
  for (i = 0, j = lowers.length; i < j; i++)
    str = str.replace(new RegExp('\\s' + lowers[i] + '\\s', 'g'), 
      function(txt) {
        return txt.toLowerCase();
      });

  // Certain words such as initialisms or acronyms should be left uppercase
  uppers = ['Id', 'Tv'];
  for (i = 0, j = uppers.length; i < j; i++)
    str = str.replace(new RegExp('\\b' + uppers[i] + '\\b', 'g'), 
      uppers[i].toUpperCase());

  return str;
}

For example:

"TO LOGIN TO THIS SITE and watch tv, please enter a valid id:".toTitleCase();
// Returns: "To Login to This Site and Watch TV, Please Enter a Valid ID:"

11 Comments

I liked yours, I also encounter problems when dealing with roman numbers... just patched it with I, II, III, IV, etc.
Fixed. The regex in the third line has been changed from /\w\S*/g to /([^\W_]+[^\s-]*) */g per @awashburn's comment above to address this.
Is there an advantage to be gained by using your regex pattern over /\b\w+/g, which I find to be more quickly comprehensible?
Not that I can see, I was simply taking another commenter’s suggestion to solve the hyphenated-word problem; but your regex appears to do just as well, and simplicity is always better. For posterity and future visitors to this post, I just changed the regex in the third line from /([^\W_]+[^\s-]*) */g to /\b\w+/g per @Michael’s comment; please comment if you find a case where the more-complicated regex is necessary.
I changed the 3rd line regex to /\b[\w-\']+/g in order to allow hyphenated words and apostrophe in words.
|
69

You could immediately toLowerCase the string, and then just toUpperCase the first letter of each word. Becomes a very simple 1 liner:

function titleCase(str) {
  return str.toLowerCase().replace(/\b\w/g, s => s.toUpperCase());
}

console.log(titleCase('iron man'));
console.log(titleCase('iNcrEdible hulK'));

8 Comments

@Waz, thanks for the ideas! Just wanted to clarify on the =>, that is a native arrow function (ES6), the link jumps to the Mozillla Docs on them which also provides a support table.
string => string.toLowerCase().replace(/\b\w/g, word_head => word_head.toUpperCase());. No need to group the \w; what is being replaced is a \b\w where \b is not a string.
as @КонстантинВан remarked, without group the solution is much faster
@КонстантинВан, and dovid, thanks for the feedback! I've implemented your suggestion. I took a look at some benchmarks for the difference, and you're correct, it is much faster.
I'm not an expert on this, but there is also s.toLocaleUpperCase() which may produce better results in other languages.
|
62

I prefer the following over the other answers. It matches only the first letter of each word and capitalises it. Simpler code, easier to read and less bytes. It preserves existing capital letters to prevent distorting acronyms. However you can always call toLowerCase() on your string first.

function title(str) {
  return str.replace(/(^|\s)\S/g, function(t) { return t.toUpperCase() });
}

You can add this to your string prototype which will allow you to 'my string'.toTitle() as follows:

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

Example:

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

console.log('all lower case ->','all lower case'.toTitle());
console.log('ALL UPPER CASE ->','ALL UPPER CASE'.toTitle());
console.log("I'm a little teapot ->","I'm a little teapot".toTitle());

10 Comments

It's even nicer as a lambda const titleCase = (str) => str.replace(/\b\S/g, t => t.toUpperCase());
I didn't want to break IE, but yeah if the application is not legacy browser sensitive it could be shorter.
This is only a partial solution - op asked for how to convert a string to title case. This answer doesn't accomplish that for inputs like NoT qUiITe.
@Madbreaks The question did not stipulate that mixed case inputs should be converted. However, i have updated the answer mentioning toLowerCase. Just be aware that it would break acronyms. an HTML document: An HTML Document vs An Html Document
@Madbreaks While your initial example was contrived, you make a good point in stating that the output would be unchanged if the input were capitalised. That being said, I feel the answer as-is (with the edit suggesting toLowerCase) is more flexible/useful than one which assumes the developers intentions. This method also reflects the functionality of similar built-in methods of other languages such as PHP (ucwords) and Golang (strings.Title). .NET (TextInfo.ToTitleCase) interestingly works for mixed case, but would also leave fully capitalised strings unchanged.
|
42

Benchmark

TL;DR

The winner of this benchmark is the plain old for loop:

function titleize(str) {
    let upper = true
    let newStr = ""
    for (let i = 0, l = str.length; i < l; i++) {
        // Note that you can also check for all kinds of spaces  with
        // str[i].match(/\s/)
        if (str[i] == " ") {
            upper = true
            newStr += str[i]
            continue
        }
        newStr += upper ? str[i].toUpperCase() : str[i].toLowerCase()
        upper = false
    }
    return newStr
}
// NOTE: you could beat that using charcode and string builder I guess.

Details

I've taken the most popular and distinct answers and made a benchmark with those.

Here's the result on my MacBook pro:

enter image description here

And for completeness, here are the functions used:

str = "the QUICK BrOWn Fox jUMPS oVeR the LAzy doG";
function regex(str) {
  return str.replace(
    /\w\S*/g,
    function(txt) {
      return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
    }
  );
}

function split(str) {
  return str.
    split(' ').
    map(w => w[0].toUpperCase() + w.substr(1).toLowerCase()).
    join(' ');
}

function complete(str) {
  var i, j, str, lowers, uppers;
  str = str.replace(/([^\W_]+[^\s-]*) */g, function(txt) {
    return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
  });

  // Certain minor words should be left lowercase unless 
  // they are the first or last words in the string
  lowers = ['A', 'An', 'The', 'And', 'But', 'Or', 'For', 'Nor', 'As', 'At', 
  'By', 'For', 'From', 'In', 'Into', 'Near', 'Of', 'On', 'Onto', 'To', 'With'];
  for (i = 0, j = lowers.length; i < j; i++)
    str = str.replace(new RegExp('\\s' + lowers[i] + '\\s', 'g'), 
      function(txt) {
        return txt.toLowerCase();
      });

  // Certain words such as initialisms or acronyms should be left uppercase
  uppers = ['Id', 'Tv'];
  for (i = 0, j = uppers.length; i < j; i++)
    str = str.replace(new RegExp('\\b' + uppers[i] + '\\b', 'g'), 
      uppers[i].toUpperCase());

  return str;
}

function firstLetterOnly(str) {
  return str.replace(/\b(\S)/g, function(t) { return t.toUpperCase(); });
}

function forLoop(str) {
  let upper = true;
  let newStr = "";
  for (let i = 0, l = str.length; i < l; i++) {
    if (str[i] == " ") {
      upper = true;
        newStr += " ";
      continue;
    }
    newStr += upper ? str[i].toUpperCase() : str[i].toLowerCase();
    upper = false;
  }
  return newStr;
}

Note that i deliberately did not change the prototype since I consider it a really bad practice and I don't think we should promote such practice in our answers. This is only ok for small codebases when you're the only one working on it.

If you want to add any other way to do it to this benchmark, please comment a link to the answer !


EDIT 2022 Mac M1: On my new computer, with more recent chrome, split wins. If you really care about performance on a specific machine you should run the benchmark yourself

6 Comments

The parentheses group in the method of 'first letter only' are not consumed, and if you remove them then this method defeats the regex method, as it makes sense.
and str.toLowerCase().replace(/\b\S/g, function(t) { return t.toUpperCase(); }); also win 'regex' method and achieves the same result
Dramatic improvement of complete method: jsben.ch/yTK3Y
@dovid I'll have to admit that I aggregated other answers directly in the benchmark. Hence feel free to edit my answer, and I'd suggest you to also comment directly on the concerned answers :)
When I ran the same benchmarks, the split seemed to outperform others.
|
28

Surprised to see no one mentioned the use of rest parameter. Here is a simple one liner that uses ES6 Rest parameters.

let str="john smith"
str=str.split(" ").map(([firstChar,...rest])=>firstChar.toUpperCase()+rest.join("").toLowerCase()).join(" ")
console.log(str)

2 Comments

I appreciate this solution and have decided that this is the best code for my intended use. I have noticed that it does not consider the use of a hyphen in names. This does not greatly impact my current use; however, I am wondering how this code might be adjusted for that consideration. Thanks again for a solid solution!
This implementation is equivalent to the Python function string.capwords(s, sep=None).
26

var result =
  'this is very interesting'.replace(/\b[a-z]/g, (x) => x.toUpperCase())

console.log(result) // This Is Very Interesting

6 Comments

Just a question, the () construct is for specifying a match on any of a sequence of options: that is, (a|b) matches a or b. What does the construction (.) do?
For anyone who had the same question, it defines a replacement "blob" which is used in the replacement section. The blobs are numbered sequentially, the first () is put into $1, the second into $2. I found this site useful: javascript.info/tutorial/regular-expressions-methods
I am not able to get the above to work, but I'm far from a regex wizard. I'm using 'string'.replace(/^(.)(.*)/,function(s,p1,p2){return p1.toUpperCase()+p2;}) Again, this only works for capitalizing the first letter of a string, but in case that's what you need, my construction works.
For some reason FF35 seems to choke on '$1'.toUpperCase(), seems the uppercase hasn't been done by the time the value is assigned. Worked around by using function 'string'.replace(/^(.){1}/,function(match) { return match.toUpperCase(); })
This doesn’t work on ‘džungla’.
|
21

Without using regex just for reference:

String.prototype.toProperCase = function() {
  var words = this.split(' ');
  var results = [];
  for (var i = 0; i < words.length; i++) {
    var letter = words[i].charAt(0).toUpperCase();
    results.push(letter + words[i].slice(1));
  }
  return results.join(' ');
};

console.log(
  'john smith'.toProperCase()
)

1 Comment

This doesn’t work on ‘džungla’.
18

Just in case you are worried about those filler words, you can always just tell the function what not to capitalize.

/**
 * @param String str The text to be converted to titleCase.
 * @param Array glue the words to leave in lowercase. 
 */
var titleCase = function(str, glue){
    glue = (glue) ? glue : ['of', 'for', 'and'];
    return str.replace(/(\w)(\w*)/g, function(_, i, r){
        var j = i.toUpperCase() + (r != null ? r : "");
        return (glue.indexOf(j.toLowerCase())<0)?j:j.toLowerCase();
    });
};

Hope this helps you out.

edit

If you want to handle leading glue words, you can keep track of this w/ one more variable:

var titleCase = function(str, glue){
    glue = !!glue ? glue : ['of', 'for', 'and', 'a'];
    var first = true;
    return str.replace(/(\w)(\w*)/g, function(_, i, r) {
        var j = i.toUpperCase() + (r != null ? r : '').toLowerCase();
        var result = ((glue.indexOf(j.toLowerCase()) < 0) || first) ? j : j.toLowerCase();
        first = false;
        return result;
    });
};

6 Comments

You can explode a string into an array. So we could have portuguese, spanish, italian and french prepositions: glue ='de|da|del|dos|do|das|des|la|della|delli'.split('|');
This won't ensure capitalization of the first word; ie and another thing becomes and Another Thing. Just need an elegant way to always capitalize the first word.
@BradKoch - pad with spaces so you're using ' and ', ' de ', etc. as the search word, then 'And Another And Another' will replace to 'And Another and Another'.
good except it capitalizes also text after ' and - like H'Dy or Number-One
Instead of using a ternary operator you could just use a fallback: glue = glue || ['of', 'for', 'and', 'a'];
|
18

If you need a grammatically correct answer:

This answer takes into account prepositions such as "of", "from", .. The output will generate an editorial style title you would expect to see in a paper.

toTitleCase Function

The function that takes into account grammar rules listed here. The function also consolidates whitespace and removes special characters (modify regex for your needs)

const toTitleCase = (str) => {
  const articles = ['a', 'an', 'the'];
  const conjunctions = ['for', 'and', 'nor', 'but', 'or', 'yet', 'so'];
  const prepositions = [
    'with', 'at', 'from', 'into','upon', 'of', 'to', 'in', 'for',
    'on', 'by', 'like', 'over', 'plus', 'but', 'up', 'down', 'off', 'near'
  ];

  // The list of spacial characters can be tweaked here
  const replaceCharsWithSpace = (str) => str.replace(/[^0-9a-z&/\\]/gi, ' ').replace(/(\s\s+)/gi, ' ');
  const capitalizeFirstLetter = (str) => str.charAt(0).toUpperCase() + str.substr(1);
  const normalizeStr = (str) => str.toLowerCase().trim();
  const shouldCapitalize = (word, fullWordList, posWithinStr) => {
    if ((posWithinStr == 0) || (posWithinStr == fullWordList.length - 1)) {
      return true;
    }

    return !(articles.includes(word) || conjunctions.includes(word) || prepositions.includes(word));
  }

  str = replaceCharsWithSpace(str);
  str = normalizeStr(str);

  let words = str.split(' ');
  if (words.length <= 2) { // Strings less than 3 words long should always have first words capitalized
    words = words.map(w => capitalizeFirstLetter(w));
  }
  else {
    for (let i = 0; i < words.length; i++) {
      words[i] = (shouldCapitalize(words[i], words, i) ? capitalizeFirstLetter(words[i], words, i) : words[i]);
    }
  }

  return words.join(' ');
}

Unit Tests to Ensure Correctness

import { expect } from 'chai';
import { toTitleCase } from '../../src/lib/stringHelper';

describe('toTitleCase', () => {
  it('Capitalizes first letter of each word irrespective of articles, conjunctions or prepositions if string is no greater than two words long', function(){
    expect(toTitleCase('the dog')).to.equal('The Dog'); // Capitalize articles when only two words long
    expect(toTitleCase('for all')).to.equal('For All'); // Capitalize conjunctions when only two words long
    expect(toTitleCase('with cats')).to.equal('With Cats'); // Capitalize prepositions when only two words long
  });

  it('Always capitalize first and last words in a string irrespective of articles, conjunctions or prepositions', function(){
    expect(toTitleCase('the beautiful dog')).to.equal('The Beautiful Dog');
    expect(toTitleCase('for all the deadly ninjas, be it so')).to.equal('For All the Deadly Ninjas Be It So');
    expect(toTitleCase('with cats and dogs we are near')).to.equal('With Cats and Dogs We Are Near');
  });

  it('Replace special characters with space', function(){
    expect(toTitleCase('[wolves & lions]: be careful')).to.equal('Wolves & Lions Be Careful');
    expect(toTitleCase('wolves & lions, be careful')).to.equal('Wolves & Lions Be Careful');
  });

  it('Trim whitespace at beginning and end', function(){
    expect(toTitleCase(' mario & Luigi superstar saga ')).to.equal('Mario & Luigi Superstar Saga');
  });

  it('articles, conjunctions and prepositions should not be capitalized in strings of 3+ words', function(){
    expect(toTitleCase('The wolf and the lion: a tale of two like animals')).to.equal('The Wolf and the Lion a Tale of Two like Animals');
    expect(toTitleCase('the  three Musketeers  And plus ')).to.equal('The Three Musketeers and Plus');
  });
});

Please note that I am removing quite a bit of special characters from the strings provided. You will need to tweak the regex to address the requirements of your project.

5 Comments

I prefer this solution since it really takes care of title case. It's not "Gone With The Wind" it's "Gone with the Wind"
This should be the accepted answer. You even wrote tests! Ref: titlecase.com danielmiessler.com/blog/a-list-of-different-case-types github.com/gouch/to-title-case
Is that a typo? You passed 3 arguments to capitalizeFirstLetter which only expects 1. I guess JavaScript doesn't care but TypeScript has a fit with that.
nice Answer, it helped a lot
This doesn’t work on ‘džungla’.
14

I made this function which can handle last names (so it's not title case) such as "McDonald" or "MacDonald" or "O'Toole" or "D'Orazio". It doesn't however handle German or Dutch names with "van" or "von" which are often in lower-case... I believe "de" is often lower-case too such as "Robert de Niro". These would still have to be addressed.

function toProperCase(s)
{
  return s.toLowerCase().replace( /\b((m)(a?c))?(\w)/g,
          function($1, $2, $3, $4, $5) { if($2){return $3.toUpperCase()+$4+$5.toUpperCase();} return $1.toUpperCase(); });
}

3 Comments

+1 for name awareness. Does not handle "macy" correctly, either, though.
This was the only function that correctly handled transforming uppercase and lower case to the correct case and that noticed initials like "U.S. Virgin Islands".
You can get around the macy problem by putting a negative lookahead in there so \b((m)(a?c))?(\w) becomes \b((m)(a?c))?(\w)(?!\s)
14

If regex used in the above solutions is getting you confused, try this code:

function titleCase(str) {
  return str.split(' ').map(function(val){ 
    return val.charAt(0).toUpperCase() + val.substr(1).toLowerCase();
  }).join(' ');
}

6 Comments

love it! no conversion to arrays.
uhhh... split does convert it to an array, you just don't see it as obviously because map means you don't have to use [] notation
This is the same as a8m's answer from 2 years earlier.
Breaks for single-char inputs.
@AlexChaffee check the revision history. a8m didn’t use an arrow function in the original answer.
|
11

Most of these answers seem to ignore the possibility of using the word boundary metacharacter (\b). A shorter version of Greg Dean's answer utilizing it:

function toTitleCase(str)
{
    return str.replace(/\b\w/g, function (txt) { return txt.toUpperCase(); });
}

Works for hyphenated names like Jim-Bob too.

3 Comments

Is an elegant partial solution but does not work with accent or upper case strings. I get "Sofía Vergara" => "SofíA Vergara" or "Sofía VERGARA" => "SofíA VERGARA". The second case could be solved with apply .toLowerCase() function before .replace(...). The first case needs to find a right regular expression.
Hmm, that seems like a bug in the regex implementation, I would think accented characters should be word characters (you are correct though, as-is it doesn't work for those cases).
\w only includes the characters [A-Za-z0-9_], not all letters. For that you'd need to use the Unicode category \p{L}. You'll need the /u modifier (see here) and a different solution for \b, which only works between \W and \w (see here)
11

First, convert your string into array by splitting it by spaces:

var words = str.split(' ');

Then use array.map to create a new array containing the capitalized words.

var capitalized = words.map(function(word) {
    return word.charAt(0).toUpperCase() + word.substring(1, word.length);
});

Then join the new array with spaces:

capitalized.join(" ");

function titleCase(str) {
  str = str.toLowerCase(); //ensure the HeLlo will become Hello at the end
  var words = str.split(" ");

  var capitalized = words.map(function(word) {
    return word.charAt(0).toUpperCase() + word.substring(1, word.length);
  });
  return capitalized.join(" ");
}

console.log(titleCase("I'm a little tea pot"));

NOTE:

This of course has a drawback. This will only capitalize the first letter of every word. By word, this means that it treats every string separated by spaces as 1 word.

Supposedly you have:

str = "I'm a little/small tea pot";

This will produce

I'm A Little/small Tea Pot

compared to the expected

I'm A Little/Small Tea Pot

In that case, using Regex and .replace will do the trick:

with ES6:

const capitalize = str => str.length
  ? str[0].toUpperCase() +
    str.slice(1).toLowerCase()
  : '';

const escape = str => str.replace(/./g, c => `\\${c}`);
const titleCase = (sentence, seps = ' _-/') => {
  let wordPattern = new RegExp(`[^${escape(seps)}]+`, 'g');
  
  return sentence.replace(wordPattern, capitalize);
};
console.log( titleCase("I'm a little/small tea pot.") );

or without ES6:

function capitalize(str) {
  return str.charAt(0).toUpperCase() + str.substring(1, str.length).toLowerCase();
}

function titleCase(str) {
  return str.replace(/[^\ \/\-\_]+/g, capitalize);
}

console.log(titleCase("I'm a little/small tea pot."));

2 Comments

This doesn’t work on ‘džungla’.
@user3840170, can you elaborate? Which one doesn't work? And what is ‘džungla’?
10

If you can use third party libraries in your code then lodash has a helper function for us.

https://lodash.com/docs/4.17.3#startCase

_.startCase('foo bar');
// => 'Foo Bar'

_.startCase('--foo-bar--');
// => 'Foo Bar'
 
_.startCase('fooBar');
// => 'Foo Bar'
 
_.startCase('__FOO_BAR__');
// => 'FOO BAR'

1 Comment

startCase is pretty aggressive in also deburring the strings. For example français > Francais or português (Brasil)' > Portugues Brasil
10

ES 6

str.split(' ')
   .map(s => s.slice(0, 1).toUpperCase() + s.slice(1).toLowerCase())
   .join(' ')

else

str.split(' ').map(function (s) {
    return s.slice(0, 1).toUpperCase() + s.slice(1).toLowerCase();
}).join(' ')

6 Comments

Just a heads up, should probably be s.slice(0, 1).toUpperCase() if you still want that first letter.
@jssridhar you should also correct the code in ES6.
Breaks if str is a single character
duplicate of a8m’s answer
This doesn’t work on ‘džungla’.
|
10

jim-bob -> Jim-Bob

jim/bob -> Jim/Bob

jim_bob -> Jim_Bob

isn't -> Isn't

école -> École

McDonalds -> McDonalds

function toTitleCase(str) {
  return str.replace(/\p{L}+('\p{L}+)?/gu, function(txt) {
    return txt.charAt(0).toUpperCase() + txt.slice(1)
  })
}

1 Comment

I think this solution deserves more upvotes
8
var toMatch = "john w. smith";
var result = toMatch.replace(/(\w)(\w*)/g, function (_, i, r) {
      return i.toUpperCase() + (r != null ? r : "");
    }
)

Seems to work... Tested with the above, "the quick-brown, fox? /jumps/ ^over^ the ¡lazy! dog..." and "C:/program files/some vendor/their 2nd application/a file1.txt".

If you want 2Nd instead of 2nd, you can change to /([a-z])(\w*)/g.

The first form can be simplified as:

function toTitleCase(toTransform) {
  return toTransform.replace(/\b([a-z])/g, function (_, initial) {
      return initial.toUpperCase();
  });
}

Comments

8

Try this, shortest way:

str.replace(/(^[a-z])|(\s+[a-z])/g, txt => txt.toUpperCase());

1 Comment

This is sweet. For the basic use case I have (where performance isn't necessarily a priority) this works perfect!
6

Use /\S+/g to support diacritics:

function toTitleCase(str) {
  return str.replace(/\S+/g, str => str.charAt(0).toUpperCase() + str.substr(1).toLowerCase());
}

console.log(toTitleCase("a city named örebro")); // A City Named Örebro

However: "sunshine (yellow)" ⇒ "Sunshine (yellow)"

Comments

6
"john f. kennedy".replace(/\b\S/g, t => t.toUpperCase())

3 Comments

Works for the sample and o'henry, but does weird stuff with horse's mouth.
"john f. kennEdy".toLowerCase().replace(/\b\S/g, t => t.toUpperCase()) better 🤔
Didn’t want to edit @Proximo’s answer: the \b and \S are special character classes denoting “word boundary” and “single, non-whitespace character. So, the regex matches every single character following a word boundary, and capitalizes that character by applying the given arrow function.
5

Try this

String.prototype.toProperCase = function(){
    return this.toLowerCase().replace(/(^[a-z]| [a-z]|-[a-z])/g, 
        function($1){
            return $1.toUpperCase();
        }
    );
};

Example

var str = 'john smith';
str.toProperCase();

Comments

5

Here is my function that is taking care of accented characters (important for french !) and that can switch on/off the handling of lowers exceptions. Hope that helps.

String.prototype.titlecase = function(lang, withLowers = false) {
    var i, string, lowers, uppers;

    string = this.replace(/([^\s:\-'])([^\s:\-']*)/g, function(txt) {
        return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
    }).replace(/Mc(.)/g, function(match, next) {
        return 'Mc' + next.toUpperCase();
    });

    if (withLowers) {
        if (lang == 'EN') {
            lowers = ['A', 'An', 'The', 'At', 'By', 'For', 'In', 'Of', 'On', 'To', 'Up', 'And', 'As', 'But', 'Or', 'Nor', 'Not'];
        }
        else {
            lowers = ['Un', 'Une', 'Le', 'La', 'Les', 'Du', 'De', 'Des', 'À', 'Au', 'Aux', 'Par', 'Pour', 'Dans', 'Sur', 'Et', 'Comme', 'Mais', 'Ou', 'Où', 'Ne', 'Ni', 'Pas'];
        }
        for (i = 0; i < lowers.length; i++) {
            string = string.replace(new RegExp('\\s' + lowers[i] + '\\s', 'g'), function(txt) {
                return txt.toLowerCase();
            });
        }
    }

    uppers = ['Id', 'R&d'];
    for (i = 0; i < uppers.length; i++) {
        string = string.replace(new RegExp('\\b' + uppers[i] + '\\b', 'g'), uppers[i].toUpperCase());
    }

    return string;
}

Comments

5

I think the simplest is using css.

function format_str(str) {
    str = str.toLowerCase();
    return '<span style="text-transform: capitalize">'+ str +'</span>';
}

3 Comments

I updated the code and tested it. It should work now.
You can only use CSS in a fraction of environments that JS is used, so this solution isn't viable. Also inline styles should be avoided at all costs.
@Steve, will it pass toLowerCase()?
5

here's another solution using css (and javascript, if the text you want to transform is in uppercase):

html

<span id='text'>JOHN SMITH</span>

js

var str = document.getElementById('text').innerHtml;
var return_text = str.toLowerCase();

css

#text{text-transform:capitalize;}

Comments

5

Here's a really simple & concise ES6 function to do this:

const titleCase = (str) => {
  return str.replace(/\w\S*/g, (t) => { return t.charAt(0).toUpperCase() + t.substr(1).toLowerCase() });
}

export default titleCase;

Works well included in a utilities folder and used as follows:

import titleCase from './utilities/titleCase.js';

const string = 'my title & string';

console.log(titleCase(string)); //-> 'My Title & String'

1 Comment

I didn't recommend using Lodash's startCase as it strips out characters like '&'
5

I've tested this solution for Turkish and it works with special characters too.

function toTitleCase(str) {
  return str.toLocaleLowerCase().replace(
    /(^|Ü|ü|Ş|ş|Ç|ç|İ|ı|Ö|ö|\w)\S*/g,
    (txt) => txt.charAt(0).toLocaleUpperCase() + txt.substring(1),
  )
}

console.log(toTitleCase('İSMAİL HAKKI'))
console.log(toTitleCase('ŞAHMARAN BİNBİR GECE MASALLARI'))
console.log(toTitleCase('TEKNOLOJİ ÜRÜNÜ'))

I've added "toLocaleLowerCase" at the begining since I've all caps data. You can discard it if you don't need it.

Using locale operations is important for non-english languages.

6 Comments

The selected answer is buggy. This is better.
toTitleCase("TEKNOLOJİ ÜRÜNÜ") is returning Teknoloji̇ üRünü. Fyi.
@OzgunSenyuva thank you. I've edited my answer to fix the issue.
"Using locale operations is important for non-english languages" - but your solution ignores locale operations. Your assumption that the character you need to act on is at char(0) is incorrect. For example, you need a test case that checks that the correct conversion of "oifig na bpasanna" is "Oifig na bPasanna" - "Oifig Na Bpasanna" isn't even close to correct. You also can't do toLocaleUpperCase on individual characters, ever; it just doesn't work. For example, OIFIG NA bPASANNA (note the 'b') is all upper case: commons.wikimedia.org/wiki/File:ALLCAPS_OIFIG_NA_bPASANNA.JPG
Doesn’t work on ‘džungla’.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.