camelCase, snake_case, kebab-case: A Developer's Guide to Naming Conventions

posted 5 min read

Every language and platform has its own naming conventions. Getting them right matters for readability, tooling compatibility, and fitting in with existing codebases. Here's a complete reference.

The naming formats

camelCase: First word lowercase, subsequent words capitalized. No separators.

  • getUserById, firstName, apiEndpoint
  • Used for: JavaScript variables and functions, Java methods, Swift methods

PascalCase: Every word capitalized. No separators.
  • UserProfile, HttpRequest, DatabaseConnection
  • Used for: JavaScript/TypeScript classes, React components, C# types, Java classes

snake_case: All lowercase, words separated by underscores.
  • user_id, get_user_by_id, MAX_RETRIES
  • Used for: Python variables/functions, Ruby, PostgreSQL columns, filesystem, SCREAMING_SNAKE_CASE for constants

kebab-case: All lowercase, words separated by hyphens.
  • user-profile, api-endpoint, my-component
  • Used for: CSS class names, URL slugs, npm package names, HTML data attributes, file names

SCREAMING_SNAKE_CASE: All uppercase snake_case.
  • MAX_RETRIES, DEFAULT_TIMEOUT, API_BASE_URL
  • Used for: Constants in most languages, environment variables

For quick one-off conversions between these formats, a case converter handles all formats in one step.

Language conventions at a glance

| Language | Variables | Functions | Classes | Constants | Files |

|----------|-----------|-----------|---------|-----------|-------|

| JavaScript/TypeScript | camelCase | camelCase | PascalCase | SCREAMING | kebab-case |

| Python | snake_case | snake_case | PascalCase | SCREAMING | snake_case |

| Go | camelCase | camelCase/PascalCase | PascalCase | camelCase | snake_case |

| Rust | snake_case | snake_case | PascalCase | SCREAMING | snake_case |

| Ruby | snake_case | snake_case | PascalCase | SCREAMING | snake_case |

| CSS | – | – | – | – | kebab-case |

| SQL | snake_case | snake_case | – | SCREAMING | – |

Go uses exported vs. unexported (public vs. private) to determine case: PascalCase is exported (public); camelCase is unexported (private). There's no class concept, so the distinction is simpler.

Converting between formats in code

JavaScript:

``javascript

// camelCase to snake_case

function camelToSnake(str) {

return str.replace(/[A-Z]/g, letter => _${letter.toLowerCase()});

}

camelToSnake('getUserById') // 'get_user_by_id'

// snake_case to camelCase

function snakeToCamel(str) {

return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());

}

snakeToCamel('get_user_by_id') // 'getUserById'

// camelCase to kebab-case

function camelToKebab(str) {

return str.replace(/[A-Z]/g, letter => -${letter.toLowerCase()});

}

camelToKebab('apiEndpointUrl') // 'api-endpoint-url'

// Any to PascalCase (handles snake, kebab, camel input)

function toPascal(str) {

return str

.replace(/-_/g, (_, c) => c.toUpperCase())

.replace(/^(.)/, c => c.toUpperCase());

}

toPascal('user_profile') // 'UserProfile'

toPascal('user-profile') // 'UserProfile'

toPascal('userProfile') // 'UserProfile'

`

Lodash (if you have it):

<code>javascript <p>import _ from 'lodash';</p> <p>_.camelCase('get_user_by_id') // 'getUserById'</p> <p>_.snakeCase('getUserById') // 'get_user_by_id'</p> <p>_.kebabCase('getUserById') // 'get-user-by-id'</p> <p>_.startCase('getUserById') // 'Get User By Id'</p> <p>_.capitalize('HELLO WORLD') // 'Hello world'</p> </code>

Python:

`python
import re

def camel_to_snake(name):

s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)

return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()

camel_to_snake('getUserById') # 'get_user_by_id'

camel_to_snake('HTMLParser') # 'html_parser'

def snake_to_camel(name):

components = name.split('_')

return components[0] + ''.join(x.title() for x in components[1:])

snake_to_camel('get_user_by_id') # 'getUserById'

With inflection library

import inflection

inflection.underscore('getUserById') # 'get_user_by_id'

inflection.camelize('get_user_by_id') # 'GetUserId' (PascalCase)

inflection.camelize('get_user_by_id', False) # 'getUserById'

`

Handling acronyms

The hardest part of case conversion is acronyms: HTML, URL, API, HTTP, JSON.

Option 1: Treat acronyms as words (recommended)

  • HTMLParserHtmlParser (PascalCase)
  • parseJSONparse_json (snake_case)
  • Most modern style guides (Google's Java, Google's Go, Python's PEP 8)

Option 2: Preserve original case
  • HTMLParser stays HTMLParser
  • userID stays userID
  • Leads to inconsistency (userId vs userID in the same codebase)

Most linters enforce option 1. In Python: json_schema, html_parser, api_endpoint. In JavaScript: jsonSchema, htmlParser, apiEndpoint.

CSS class naming: BEM

BEM (Block Element Modifier) is a popular CSS naming methodology:

<code> <p>block__element--modifier</p> </code>

Examples:

  • .card (block)
  • .card__title (element)
  • .card__title--large (modifier)
  • .nav__link--active (element + modifier)

BEM uses kebab-case with double underscores for elements and double hyphens for modifiers. It prevents specificity conflicts and makes component ownership explicit.

Database column naming

SQL columns use snake_case by convention:

<code>sql <p>CREATE TABLE users (</p> <p>user_id INT PRIMARY KEY,</p> <p>first_name VARCHAR(50),</p> <p>last_name VARCHAR(50),</p> <p>created_at TIMESTAMP</p> <p>);</p> </code>

ORMs typically handle the mapping between SQL snake_case and application camelCase:

<code>javascript <p>// Prisma (Node.js): DB uses snake_case, JS uses camelCase</p> <p>const user = await prisma.users.findFirst({</p> <p>where: { userId: 1 } // mapped to user_id</p> <p>});</p> </code>

<code>python <h1>Django: Python uses snake_case for both DB and model fields</h1> <p>class User(models.Model):</p> <p>first_name = models.CharField(max_length=50) # maps to column 'first_name'</p> </code>

URL slug best practices

URLs should use kebab-case for readability and SEO:

<code> <p>/blog/how-to-write-clean-css ← correct</p> <p>/blog/how_to_write_clean_css ← valid but less conventional</p> <p>/blog/HowToWriteCleanCSS ← wrong — case-sensitive, unreadable</p> </code>

Slugs should be lowercase, use hyphens (not underscores), and exclude stop words when possible (the, a, and).


Naming conventions are one area where consistency within a project matters more than which specific convention you choose. Pick one standard per context (one language, one layer) and enforce it with a linter — eslint's camelcase rule, Python's pylint naming checks, or Go's golint`.

Originally published at https://snappytools.app/case-converter/

More Posts

I’m a Senior Dev and I’ve Forgotten How to Think Without a Prompt

Karol Modelskiverified - Mar 19

How I Built a React Portfolio in 7 Days That Landed ₹1.2L in Freelance Work

Dharanidharan - Feb 9

TypeScript Complexity Has Finally Reached the Point of Total Absurdity

Karol Modelskiverified - Apr 23

Sovereign Intelligence: The Complete 25,000 Word Blueprint (Download)

Pocket Portfolio - Apr 1

5 Web Dev Pitfalls That Are Silently Killing Your Projects (With Real Fixes)

Dharanidharan - Mar 3
chevron_left

Related Jobs

View all jobs →

Commenters (This Week)

4 comments
2 comments

Contribute meaningful comments to climb the leaderboard and earn badges!