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-color and attributes such as aria-label are 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:

StyleResultTypical use
kebab-casesummer-clothing-saleURLs, CSS classes, file names, CLI flags
snake_casesummer_clothing_salePython and Rust functions and variables, database columns
camelCasesummerClothingSaleJavaScript and Java variables and functions, many JSON APIs
PascalCaseSummerClothingSaleClasses and types, React components
CONSTANT_CASESUMMER_CLOTHING_SALEConstants, environment variables
dot.casesummer.clothing.saleConfig 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:

VersionExampleGoogle
Hyphenshttps://example.com/summer-clothing/filter?color-profile=dark-greyRecommended
Underscoreshttps://example.com/summer_clothing/filter?color_profile=dark_greyNot recommended
Joined wordshttps://example.com/greendressNot recommended

Two more reasons favor kebab-case in URLs:

  • URLs are case-sensitive. Google treats /APPLE and /apple as different URLs, so camelCase or PascalCase paths invite duplicates such as /SummerSale and /summersale. All-lowercase kebab-case avoids the problem.
  • Underscores disappear in links. Many apps underline links, which hides _ and makes summer_sale look like summer 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:

Inputkebab-casesnake_casecamelCasePascalCase
XMLHttpRequestxml-http-requestxml_http_requestxmlHttpRequestXmlHttpRequest
getUserIDget-user-idget_user_idgetUserIdGetUserId
HTTPServerErrorhttp-server-errorhttp_server_errorhttpServerErrorHttpServerError
parseHTML5Docparse-html5-docparse_html5_docparseHtml5DocParseHtml5Doc
user_profile_v2user-profile-v2user_profile_v2userProfileV2UserProfileV2

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-id is a subtraction.
  • Mixing styles in one API. userId next to created_at makes every client guess.
  • Forgetting the boundary conversion. data-user-id is dataset.userId in JavaScript.
  • Trusting converters with acronyms. Check HTTPServerError versus HttpServerError against your style guide.
  • Renaming URLs to "fix" style without redirects. Changing /Summer_Sale to /summer-sale needs 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 redirects

Convert 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

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.