developer · · Updated

camelCase, snake_case, kebab-case and Title Case: Which Goes Where

By

Case conventions look like style, but at the edges between systems they decide whether code works. A column called userId behaves differently from user_id in PostgreSQL, a URL with underscores is read differently from one with hyphens, and converting XMLHttpRequest to snake_case can go wrong in more than one way. This guide covers where each convention is expected and what automatic conversion does to awkward names.

Who expects what

WhereConventionSource of the rule
Python variables and functionssnake_casePEP 8, Python's style guide
Python classesCapWords (PascalCase)PEP 8
JavaScript and Java variables, functionscamelCaseGoogle's JavaScript and Java style guides
JavaScript and Java classes, React componentsPascalCaseLanguage convention; React treats lowercase JSX tags as HTML elements
CSS classes, HTML custom elementskebab-caseCustom element names must contain a hyphen
URL pathskebab-caseGoogle recommends hyphens rather than underscores to separate words in URLs
SQL tables and columnssnake_caseSee the PostgreSQL note below
JSON APIsEitherGitHub's REST API returns created_at; Google's JSON style guide asks for camelCase property names
Headings and titlesTitle Case or sentence caseYour publication's style guide

The rule that holds everywhere: pick the convention of the system you're writing for, and convert at the boundary. A Python backend can use created_at internally and still serve createdAt to a JavaScript client, as long as one layer does the translation consistently.

Why camelCase column names hurt in PostgreSQL

PostgreSQL folds unquoted identifiers to lowercase. Create a column as "userId" (with quotes, as some ORMs do) and a hand-written query SELECT userId FROM users looks for userid and fails with column "userid" does not exist. From then on you have to quote the name every time: SELECT "userId" FROM users. A user_id column never needs quotes, which is why snake_case is the safe default for SQL even when the application code around it is camelCase.

What automatic conversion does to awkward names

A converter has to decide where words start. The Text Case Converter splits at spaces, punctuation, underscores and hyphens, between a lowercase letter or digit and a capital, and between an acronym and the word after it. Here is what that produces for names that trip converters up:

InputcamelCasesnake_caseTitle Case
XMLHttpRequestxmlHttpRequestxml_http_requestXmlhttprequest
getHTTPResponsegetHttpResponseget_http_responseGethttpresponse
userID2userId2user_id2Userid2
iPhone appiPhoneAppi_phone_appIphone App
customer_first_namecustomerFirstNamecustomer_first_nameCustomer_First_Name
Order Total (INR)orderTotalInrorder_total_inrOrder Total (Inr)
café au laitcaféAuLaitcafé_au_laitCafé Au Lait

Three patterns to watch:

  • Acronyms lose their capitals. In camelCase output an acronym becomes an ordinary word (xmlHttpRequest, orderTotalInr). Google's Java and JavaScript style guides actually prefer this form (XmlHttpRequest, not XMLHTTPRequest), but if your codebase keeps acronyms in capitals, fix them by hand.
  • Brand names split in the wrong place. iPhone becomes i_phone, because a capital after a lowercase letter looks like a word boundary. There is no rule that can tell iPhone from userName, so check proper nouns.
  • Title Case is for prose. It capitalises each run of letters and doesn't split joined identifiers, so XMLHttpRequest becomes one word. Convert an identifier to snake_case first if you want "Xml Http Request" style words.

Title Case and sentence case

For headings, Title Case capitalises the first letter of each word, and sentence case capitalises only the first word and proper nouns. The converter's Title Case capitalises every word, including short ones, and lowercases the rest of each word: "the lord of the rings" becomes "The Lord Of The Rings", "NASA" becomes "Nasa" and "O'Brien" becomes "O'brien". Style guides such as AP and Chicago keep short words like "of" and "the" in lowercase unless they start the title, so a heading usually needs a quick manual pass after conversion.

Slugs are a separate job

A URL slug needs more than kebab-case: accented letters simplified, punctuation removed, and repeated separators collapsed. The Slug Generator does that, so "Crème Brûlée à São Paulo" becomes creme-brulee-a-sao-paulo, while the case converter keeps the accents.

Related guides