ToolMelt

Camel Case vs Snake Case vs Kebab Case

Camel case vs snake case vs kebab case compared: rules, examples, and where each naming convention is standard in JavaScript, Python, CSS, URLs and constants.

This guide pairs with a free tool:

Open the Case Converter

If you have ever moved code between a JavaScript front end and a Python API, you have felt it: the same idea is userLoginCount in one file and user_login_count in the other. Case styles are not interchangeable decoration — every language, framework and file format has settled on its own naming convention, and matching it is what makes code look native. This guide compares camel case vs snake case vs kebab case, adds PascalCase, CONSTANT_CASE, Title Case and Sentence case, shows where each one is the standard, and covers the edge cases that trip people up.

The seven naming styles at a glance

Every identifier style does the same two jobs: split a phrase into words, then rejoin them with a casing rule and maybe a separator. Here is what each style does to the phrase "user login count":

StyleExampleRule
camelCaseuserLoginCountWords joined directly; first word lowercase, every later word capitalized
PascalCaseUserLoginCountSame joining as camelCase, but the first word is capitalized too
snake_caseuser_login_countAll lowercase, words joined with underscores
kebab-caseuser-login-countAll lowercase, words joined with hyphens
CONSTANT_CASEUSER_LOGIN_COUNTAll uppercase, words joined with underscores
Title CaseUser Login CountWords separated by spaces, each one capitalized
Sentence caseUser login countWords separated by spaces, only the first one capitalized

Two pairs are easy to confuse. camelCase and PascalCase join words identically — the only difference is the very first letter, userLoginCount versus UserLoginCount. snake_case and kebab-case share the same all-lowercase casing and differ only in the separator: underscore versus hyphen. CONSTANT_CASE is simply snake_case shouted, which is why some people call it SCREAMING_SNAKE_CASE.

Where each style is the convention

ContextConventionExample
JavaScript & Java variables, functions, methodscamelCasegetUserById, retryCount
Classes in JavaScript, Java, Python, C#PascalCaseShoppingCart, HttpClient
Python functions & variables (PEP 8)snake_casecalculate_total
Ruby, Rust, PHP, SQL identifierssnake_casecreated_at
CSS classes & HTML data attributeskebab-case.main-header, data-user-id
URLs and slugskebab-case/blog/naming-conventions
Constants & environment variablesCONSTANT_CASEMAX_RETRY_COUNT
JSON keys & GraphQL fieldscamelCasefirstName
Headlines, book titles, headingsTitle CaseThe Quick Brown Fox
UI labels and body copySentence caseSave changes

These are community standards, not compiler rules. Python's PEP 8 style guide prescribes snake_case for functions and variables, PascalCase (it says CapWords) for classes and UPPER_CASE for constants. Java and JavaScript reach for camelCase everywhere except class names. CSS itself is hyphenated — background-color, font-size — so authors naturally extend kebab-case to class names. And Google's URL guidelines recommend hyphens over underscores in URLs, because a hyphen is treated as a word separator while an underscore glues words into one token for search.

Edge cases: acronyms, numbers and leading digits

Acronyms: XMLHttpRequest or XmlHttpRequest?

Two respectable answers exist. The browser DOM API kept the acronym fully capitalized: XMLHttpRequest. The Google Java style guide instead says treat acronyms as ordinary words, which produces XmlHttpRequest. The .NET design guidelines split the difference: two-letter acronyms stay uppercase (System.IO), but anything longer becomes a normal word — Html, Xml, Json. None of these is wrong; mixing httpRequest and HTTPRequest inside one codebase is. Pick the rule of your language community and apply it everywhere.

Numbers inside identifiers

Digits glue to the word they belong to: sha256Hash, utf8Encode, version2Id. Converters differ on whether a letter–digit boundary counts as a word boundary, so sha-256-hash may normalize to sha256Hash or keep the digits as their own segment — glance at the output whenever numbers are involved rather than assuming.

Leading digits

Identifiers may not start with a digit in JavaScript, Python, Java, C and most other languages — 2faEnabled is a syntax error before it is anything else. Move the digit (enable2fa) or spell the number out (twoFactorAuthEnabled). HTML allows a class attribute to begin with a digit, but the corresponding CSS selector then needs escaping, which is why stylesheets avoid names like .404-page.

Renaming identifiers across languages

Porting code between ecosystems usually means a bulk rename. A reliable procedure:

  1. Split the source name into words on underscores, hyphens, spaces and camelCase humps, so getHTTPResponseCode becomes get / http / response / code.
  2. Decide the acronym rule once for the target style — whether http rejoins as Http or stays HTTP — before touching any files.
  3. Rejoin with the target casing and separator: getHttpResponseCode in Java becomes get_http_response_code in Python.
  4. Search case-sensitively across the whole repo for the old name, including string literals, JSON keys, config files, log messages and database columns that reference it.

The mechanical part is what the Case Converter automates: paste an identifier in any style — it understands spaces, underscores, hyphens and camelCase boundaries — and copy it back as camelCase, snake_case, kebab-case or CONSTANT_CASE. Everything runs in your browser, so even production variable names never leave the page.

More guides