kebab-case, snake_case, camelCase, PascalCase and CONSTANT_CASE all solve the same problem: writing several words without spaces. Each one has a home. URLs and CSS use hyphens, Python uses underscores, JavaScript uses camelCase, and mixing them up causes bugs, broken links or code reviews full of renames. This guide shows every style side by side, explains why URLs use hyphens, lists which style each language and file format expects according to MDN and PEP 8, and covers the hard cases: acronyms and numbers. Every converted name below is real output from our kebab case converter, and the two code snippets were run against it in our tests.
Tip
The short answer
- URLs: kebab-case. Google recommends hyphens between words in URLs, not underscores, and lowercase avoids duplicate URLs.
- CSS and HTML: kebab-case. Properties such as
background-colorand attributes such asaria-labelare hyphenated. - Python and Rust: snake_case for functions and variables; Python classes use PascalCase (PEP 8 calls it CapWords).
- JavaScript and Java: camelCase for variables and functions, PascalCase for classes.
- Constants and environment variables: CONSTANT_CASE.
- Follow the convention of the ecosystem you are in, and convert at the boundaries, for example between a JSON API and your code.
The naming styles at a glance
The phrase "Summer Clothing Sale" in each style:
| Style | Result | Typical use |
|---|---|---|
| kebab-case | summer-clothing-sale | URLs, CSS classes, file names, CLI flags |
| snake_case | summer_clothing_sale | Python and Rust functions and variables, database columns |
| camelCase | summerClothingSale | JavaScript and Java variables and functions, many JSON APIs |
| PascalCase | SummerClothingSale | Classes and types, React components |
| CONSTANT_CASE | SUMMER_CLOTHING_SALE | Constants, environment variables |
| dot.case | summer.clothing.sale | Config keys, translation keys, package names in some ecosystems |
MDN describes kebab case as words "typically all lower case" joined by hyphens, and notes that kebab case is not an option for variable names in many languages because the hyphen means subtraction. summer-clothing-sale in JavaScript is summer minus clothing minus sale. Snake case never contains uppercase letters; MDN calls the all-uppercase form, as in Number.MAX_SAFE_INTEGER, "screaming snake case". Camel case starts each word after the first with a capital letter; when the first letter is also capitalized, it is called upper camel case or Pascal case.
Why URLs use hyphens
Google's URL structure guide is explicit: use hyphens rather than underscores to separate words in URLs, because that helps users and search engines identify the concepts in the URL. Its reason for not recommending underscores is historical. Underscores are commonly used to keep things together, for example in function names such as format_date, while hyphens clearly signal a word boundary. The guide lists three versions of the same URL:
| Version | Example | |
|---|---|---|
| Hyphens | https://example.com/summer-clothing/filter?color-profile=dark-grey | Recommended |
| Underscores | https://example.com/summer_clothing/filter?color_profile=dark_grey | Not recommended |
| Joined words | https://example.com/greendress | Not recommended |
Two more reasons favor kebab-case in URLs:
- URLs are case-sensitive. Google treats
/APPLEand/appleas different URLs, so camelCase or PascalCase paths invite duplicates such as/SummerSaleand/summersale. All-lowercase kebab-case avoids the problem. - Underscores disappear in links. Many apps underline links, which hides
_and makessummer_salelook likesummer sale.
That is why our URL slug generator only produces lowercase, hyphenated slugs. For the rest of a good slug, see our URL slug SEO guide.
Where each style belongs in code
Python (PEP 8). Function and variable names are lowercase, with words separated by underscores as necessary to improve readability. Class names normally use CapWords. Constants are written in all capital letters with underscores, such as MAX_OVERFLOW. Modules have short, all-lowercase names; underscores are allowed in module names but discouraged in package names. mixedCase (camelCase) is allowed only where it is already the prevailing style, for backwards compatibility.
JavaScript and Java. MDN calls camelCase the most popular convention in JavaScript, Java and various other languages. Built-in names show it: encodeURIComponent, ArrayBuffer, HTMLElement. Classes and React components use PascalCase.
Rust. MDN lists snake case as the most popular convention in Python, Rust and various other languages.
CSS and HTML. CSS properties such as background-color and font-family are kebab-case, and so are HTML attributes such as aria-label and data-*. In JavaScript, element.dataset turns data-user-id into userId, and element.style uses backgroundColor, so the same name crosses from kebab-case to camelCase at the boundary.
Files and command lines. Kebab-case file names such as summer-sale.md are safe on every operating system and become clean URLs on static sites. Command-line flags such as --dry-run use hyphens by convention.
Data. JSON APIs vary: many JavaScript-facing APIs use camelCase, many Python- and database-backed APIs use snake_case. Pick one per API and convert in one place, ideally the serialization layer or API client, so the rest of your code sees only one style.
Acronyms and numbers
Acronyms are where styles disagree. MDN notes that camel-casing practice varies: some keep acronyms uppercase (encodeURIComponent), others capitalize only the first letter (XmlHttpRequest), and the real XMLHttpRequest mixes both. PEP 8 takes a side for Python class names: "HTTPServerError is better than HttpServerError".
Converters have to split such names into words before they can join them again. Ours treats a run of capitals as one word and a capital followed by lowercase letters as the start of a new word:
| Input | kebab-case | snake_case | camelCase | PascalCase |
|---|---|---|---|---|
| XMLHttpRequest | xml-http-request | xml_http_request | xmlHttpRequest | XmlHttpRequest |
| getUserID | get-user-id | get_user_id | getUserId | GetUserId |
| HTTPServerError | http-server-error | http_server_error | httpServerError | HttpServerError |
| parseHTML5Doc | parse-html5-doc | parse_html5_doc | parseHtml5Doc | ParseHtml5Doc |
| user_profile_v2 | user-profile-v2 | user_profile_v2 | userProfileV2 | UserProfileV2 |
Note the PascalCase column: the converter normalizes acronyms to HttpServerError. If you follow PEP 8 for Python classes, restore the capitals by hand to HTTPServerError. Digits stay attached to the word before them, so v2 and html5 survive as one word.
A slug generator and a case converter are different tools for this reason. A slug generator treats input as a title, so XMLHttpRequest becomes the single word xmlhttprequest. A case converter treats input as an identifier and finds the word boundaries inside it: xml-http-request. Use the slug generator for page titles and the kebab case converter for code names.
Converting between styles in code
These two functions split identifiers the same way as our converter (for ASCII names) and return kebab-case. Both were tested against the converter on every example in this guide:
function toKebab(name) {
return name
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
.replace(/([A-Z])([A-Z][a-z])/g, '$1-$2')
.split(/[^A-Za-z0-9]+/)
.filter(Boolean)
.map((w) => w.toLowerCase())
.join('-');
}
toKebab('XMLHttpRequest'); // 'xml-http-request'import re
def to_kebab(name):
name = re.sub(r"([a-z0-9])([A-Z])", r"\1-\2", name)
name = re.sub(r"([A-Z])([A-Z][a-z])", r"\1-\2", name)
return "-".join(w.lower() for w in re.split(r"[^A-Za-z0-9]+", name) if w)
to_kebab("getUserID") # 'get-user-id'Each regex handles one kind of boundary. The first inserts a hyphen between a lowercase letter or digit and a capital, which splits camelCase such as getUser. The second inserts a hyphen between a run of capitals and a capital followed by a lowercase letter, which splits XMLHttp into XML and Http. The result is then split on anything that is not a letter or digit, lowercased and joined with hyphens. Keep the steps in this order to match the converter exactly.
For snake_case, join with _ instead of -. For non-ASCII names or production code, use a tested library or the converter rather than a regex you wrote yourself. To turn page titles into URL slugs, use the slugify snippets in our code snippets guide; they also handle accents and &.
Warning
Common mistakes
- Underscores or camelCase in URLs. Use lowercase kebab-case; Google recommends hyphens.
- Kebab-case variable names. In most languages
user-idis a subtraction. - Mixing styles in one API.
userIdnext tocreated_atmakes every client guess. - Forgetting the boundary conversion.
data-user-idisdataset.userIdin JavaScript. - Trusting converters with acronyms. Check
HTTPServerErrorversusHttpServerErroragainst your style guide. - Renaming URLs to "fix" style without redirects. Changing
/Summer_Saleto/summer-saleneeds a 301 redirect.
Copyable naming style checklist
[ ] URLs and slugs: lowercase kebab-case
[ ] CSS classes, file names and CLI flags: kebab-case
[ ] Python and Rust functions/variables: snake_case
[ ] JavaScript and Java variables/functions: camelCase
[ ] Classes, types and components: PascalCase
[ ] Constants and environment variables: CONSTANT_CASE
[ ] One style per API, converted in one place
[ ] Acronyms checked against the style guide
[ ] Renamed URLs have 301 redirectsConvert names with the tools
Paste names into the kebab case converter to see kebab-case, snake_case, camelCase, PascalCase, CONSTANT_CASE and more at once, one name per line. For page titles use the URL slug generator, and when you fix old underscore or uppercase URLs, create the redirects with the 301 redirect generator.
Sources
- MDN Web Docs: Kebab case
- MDN Web Docs: Snake case
- MDN Web Docs: Camel case
- Python: PEP 8, Style Guide for Python Code, "Naming Conventions"
- Google Search Central: URL structure best practices for Google Search
FAQ
Frequently asked questions
Is kebab-case or snake_case better for URLs?
kebab-case. Google recommends hyphens rather than underscores to separate words in URLs, because hyphens clearly mark word boundaries while underscores are commonly used to join concepts, as in function names. Keep URLs lowercase as well, since they are case-sensitive.
Why can't I use kebab-case for variable names?
In most programming languages the hyphen is the minus operator, so user-id means user minus id. Use snake_case or camelCase for variables, depending on the language, and keep kebab-case for URLs, CSS and file names.
Which naming style does Python use?
PEP 8 uses snake_case for functions, variables and modules, CapWords (PascalCase) for classes, and CONSTANT_CASE for constants. camelCase is allowed only where it is already the prevailing style.
How should acronyms be written in camelCase?
Practice varies. JavaScript's own names mix styles (XMLHttpRequest, encodeURIComponent), and PEP 8 prefers HTTPServerError for Python classes. Many style guides treat acronyms as words, as in xmlHttpRequest. Pick one rule for your codebase and apply it everywhere.
