developer · · Updated
camelCase, snake_case, kebab-case and Title Case: Which Goes Where
By Chirag
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
| Where | Convention | Source of the rule |
|---|---|---|
| Python variables and functions | snake_case | PEP 8, Python's style guide |
| Python classes | CapWords (PascalCase) | PEP 8 |
| JavaScript and Java variables, functions | camelCase | Google's JavaScript and Java style guides |
| JavaScript and Java classes, React components | PascalCase | Language convention; React treats lowercase JSX tags as HTML elements |
| CSS classes, HTML custom elements | kebab-case | Custom element names must contain a hyphen |
| URL paths | kebab-case | Google recommends hyphens rather than underscores to separate words in URLs |
| SQL tables and columns | snake_case | See the PostgreSQL note below |
| JSON APIs | Either | GitHub's REST API returns created_at; Google's JSON style guide asks for camelCase property names |
| Headings and titles | Title Case or sentence case | Your 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:
| Input | camelCase | snake_case | Title Case |
|---|---|---|---|
XMLHttpRequest | xmlHttpRequest | xml_http_request | Xmlhttprequest |
getHTTPResponse | getHttpResponse | get_http_response | Gethttpresponse |
userID2 | userId2 | user_id2 | Userid2 |
iPhone app | iPhoneApp | i_phone_app | Iphone App |
customer_first_name | customerFirstName | customer_first_name | Customer_First_Name |
Order Total (INR) | orderTotalInr | order_total_inr | Order Total (Inr) |
café au lait | caféAuLait | café_au_lait | Café 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, notXMLHTTPRequest), but if your codebase keeps acronyms in capitals, fix them by hand. - Brand names split in the wrong place.
iPhonebecomesi_phone, because a capital after a lowercase letter looks like a word boundary. There is no rule that can telliPhonefromuserName, so check proper nouns. - Title Case is for prose. It capitalises each run of letters and doesn't split joined identifiers, so
XMLHttpRequestbecomes 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
- HTTP Status Codes You Will Actually See, From One Real Site · Every status code this site and the two APIs it uses returned in one afternoon of curl requests (301, 308, 304, 204, 400, 404 and 405), what each means, and the redirect that broke a CORS request.
- HEX, RGB and HSL: How the Conversions Work and Where They Round · #4F46E5 converted to RGB and HSL step by step, why 89.4% of all colours change when copied as whole-number HSL, why HSL lightness is not brightness (yellow and blue at 50% differ eightfold in contrast), and the alpha that hex can't write exactly.
- Common JSON Errors and What the Error Messages Mean · Twelve common JSON mistakes, the exact error each one produces in Chrome, Firefox and Safari, why the reported position is sometimes after the real problem, and how to fix each.