kebab-case

All lowercase, words separated by hyphens. Also called dash-case or spinal-case.

Where it's used

CSS class names, HTML attributes, CLI flags, URL paths.

Worked examples

The engine handles every common input pattern — spaces, hyphens, underscores, camelCase humps, and ALLCAPS acronym runs — and produces the canonical kebab-case output.

Input kebab-case
user profile user-profile
main heading main-heading
is logged in is-logged-in
user agent string user-agent-string

Smart tokenization

Our engine splits identifiers correctly. HTMLParser doesn't become h_t_m_l_parser — the ALLCAPS run is recognized as a single token and produces html_parser. getXMLHttpRequest tokenizes to get, XML, Http, Request for clean output in any case format.

The name and the convention

kebab-case writes identifiers in all lowercase with words separated by hyphens — like words skewered on a kebab. The convention is also called dash-case, spinal-case, lisp-case, or sometimes simply hyphen-case. The "kebab" name has become dominant in modern web development, particularly because Vue.js documentation popularized it.

Like snake_case, kebab-case creates unambiguous word boundaries that survive copy-paste between editors and look the same in every font. Unlike snake_case, hyphens are allowed in many contexts where underscores aren't (and vice versa) — which determines where each convention belongs.

Where kebab-case is canonical

  • CSS class names and IDs: .btn-primary, #nav-menu, .user-profile-card. CSS has used kebab-case since its inception, and modern conventions (BEM, Tailwind utility classes) double down on it.
  • HTML attributes: data-user-id, aria-label, tabindex. The HTML specification uses kebab-case throughout, and custom data attributes must use it.
  • URL paths and slugs: /user-profile, /blog/best-coffee-shops. Google explicitly recommends hyphens over underscores in URLs because crawlers treat hyphens as word separators but underscores as part of the word.
  • Command-line flags: --verbose, --max-retries, --output-format. Every major CLI tool (git, npm, docker, kubectl) uses kebab-case for long-form flags.
  • Web Components custom elements: the spec requires at least one hyphen in the tag name to distinguish custom elements from built-in HTML elements. <my-button>, <app-header>.
  • Lisp-family languages: Clojure, Scheme, and Common Lisp use kebab-case throughout. (defn parse-html [s] ...). This is possible because Lisp doesn't use the hyphen as a subtraction operator the way C-family languages do.
  • Package names in npm: npm package names are conventionally kebab-case. react-router, http-server, babel-loader.

Why hyphens beat underscores for URLs

Google's official documentation explicitly states that hyphens are word separators in URLs while underscores are not. A URL like /best_coffee_shops is treated as a single token by Google's crawler — meaning the page won't match the query "best coffee shops" as strongly as /best-coffee-shops would.

This is one of the clearer cases where convention isn't arbitrary. URLs use hyphens because Google says they should, and SEO matters. Database tables use underscores because SQL case-folds identifiers and hyphens are interpreted as the subtraction operator in many SQL dialects.

The minus sign problem

The reason kebab-case can't be used universally is that the hyphen is also the minus sign. In most programming languages, user-name would be parsed as "user minus name" — a subtraction expression, not an identifier. This is why JavaScript variables can't use kebab-case but JavaScript object keys (when quoted as strings) can: { "user-name": "alice" } is valid; const user-name = "alice" is a syntax error.

Languages that use kebab-case for identifiers (Lisp, Clojure, CSS) handle this by either not having a subtraction operator with the same symbol, or by parsing identifiers and operators based on whitespace context.

Conversion edge cases

  • Numbers in identifiers: html5 stays as html5, not html-5. Numbers attach to the preceding word.
  • Acronyms: XMLHttpRequest becomes xml-http-request, recognizing "XML" as one token before "Http".
  • Multiple consecutive hyphens: some style guides allow -- for emphasis (like Tailwind's responsive prefix md:hover:bg-blue-500), but standard kebab-case uses single hyphens only.
  • Leading or trailing hyphens: never. A leading hyphen would parse as a CSS vendor prefix or a CLI flag start; trailing hyphens are always errors.

kebab-case versus snake_case

The choice between them is almost always determined by context. CSS, HTML, URLs, CLIs: kebab-case. Python, Ruby, SQL, environment variables: snake_case. They're rarely interchangeable, and choosing the wrong one in the wrong context creates obvious friction (kebab-case database columns require quoting; snake_case CSS classes work but stand out as foreign).

When generating slugs from user input — like converting an article title to a URL — kebab-case is the universally correct output. Our find-and-replace tool can handle batch conversions if you need to change a column of titles to kebab-case slugs.

Convert to kebab-case now.

Open the converter →

See all programming naming conventions.