X Xerobit

Kebab Case — What It Is and Where to Use kebab-case

Kebab case uses hyphens between lowercase words: hello-world, user-first-name. It's the standard for CSS class names, URLs, HTML attributes, and npm package names. Here's where...

Mian Ali Khalid · · 4 min read
Use the tool
Case Converter
Convert text between camelCase, PascalCase, snake_case, kebab-case, SCREAMING_CASE, Title Case, sentence case, and more. Bulk mode.
Open Case Converter →

Kebab case (also called hyphen-case or spinal-case) writes multi-word identifiers with hyphens between lowercase words: hello-world, user-first-name, primary-color. It’s named after letters skewered on a kebab stick.

Use the Case Converter to convert any text to kebab-case instantly.

Kebab case rules

user name       → user-name
getUserProfile  → get-user-profile
First Name      → first-name
background_color → background-color
  • All letters lowercase
  • Words separated by hyphens
  • No spaces or underscores
  • Numbers are allowed: h1-heading, col-12

Where kebab-case is standard

CSS class names

Kebab-case is the conventional style for CSS class names:

/* Class names */
.primary-button { ... }
.user-profile-card { ... }
.nav-menu-item { ... }
.error-message { ... }

/* Custom properties (CSS variables) */
:root {
  --primary-color: #3b82f6;
  --font-size-base: 16px;
  --border-radius-sm: 4px;
  --spacing-large: 2rem;
}

HTML attributes and data attributes

HTML uses kebab-case for custom data attributes and ARIA attributes:

<div 
  data-user-id="123"
  data-product-name="Blue Shirt"
  data-is-active="true"
  aria-label="Close modal"
  aria-expanded="false"
  role="dialog"
></div>

<input
  type="text"
  id="first-name"
  name="first-name"
  placeholder="Enter first name"
/>

URLs and routing

SEO best practice (and Google’s recommendation) is to use hyphens in URLs, not underscores:

Good (hyphens):
/blog/how-to-center-div
/products/blue-running-shoes
/user-profile/settings

Avoid (underscores — Google treats as single word):
/blog/how_to_center_div

Avoid (camelCase — hard to read):
/blog/howToCenterDiv

npm package names

npm package names must be lowercase and can use hyphens:

{
  "name": "my-awesome-package",
  "dependencies": {
    "react-router-dom": "^6.0.0",
    "tailwind-css": "^3.0.0",
    "date-fns": "^2.0.0",
    "lodash-es": "^4.0.0"
  }
}

React/Vue component props (JSX)

While React components themselves use PascalCase, HTML element attributes in JSX use camelCase — but custom HTML attributes still use kebab-case via data-*:

// JSX attribute conventions:
<Button 
  onClick={handleClick}        // camelCase (React events)
  className="primary-button"   // kebab-case class names
  data-testid="submit-btn"     // kebab-case data attributes
  aria-label="Submit form"     // kebab-case ARIA
/>

Vue.js component naming

Vue recommends kebab-case for components in templates:

<!-- Vue template: kebab-case component names -->
<template>
  <user-profile-card :user-id="userId" />
  <nav-menu :is-open="menuOpen" />
  <error-message :message="errorText" />
</template>

Converting to kebab-case in code

JavaScript

function toKebabCase(str) {
  return str
    .replace(/([A-Z])/g, '-$1')         // Insert - before capitals
    .replace(/[\s_]+/g, '-')            // Replace spaces/underscores with -
    .replace(/^-/, '')                  // Remove leading -
    .toLowerCase();
}

toKebabCase('camelCaseString');     // 'camel-case-string'
toKebabCase('PascalCaseString');    // 'pascal-case-string'
toKebabCase('snake_case_string');   // 'snake-case-string'
toKebabCase('Title Case String');   // 'title-case-string'

// Better handling for acronyms:
function toKebabCaseAdvanced(str) {
  return str
    .replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')
    .replace(/([a-z\d])([A-Z])/g, '$1-$2')
    .replace(/[\s_]+/g, '-')
    .toLowerCase();
}

toKebabCaseAdvanced('parseHTTPRequest');  // 'parse-http-request'
toKebabCaseAdvanced('getHTML5Content');   // 'get-html5-content'

Python

import re

def to_kebab_case(name):
    s1 = re.sub('(.)([A-Z][a-z]+)', r'\1-\2', name)
    result = re.sub('([a-z0-9])([A-Z])', r'\1-\2', s1).lower()
    result = re.sub(r'[\s_]+', '-', result)
    return result

to_kebab_case('camelCaseString')    # 'camel-case-string'
to_kebab_case('PascalCaseString')   # 'pascal-case-string'
to_kebab_case('parseHTTPRequest')   # 'parse-http-request'
to_kebab_case('snake_case_string')  # 'snake-case-string'

CSS custom property generation

// Convert JS style object keys to CSS custom properties:
const theme = {
  primaryColor: '#3b82f6',
  fontSizeBase: '16px',
  borderRadiusSm: '4px',
};

const cssVars = Object.entries(theme)
  .map(([key, value]) => `--${toKebabCase(key)}: ${value};`)
  .join('\n');

// Output:
// --primary-color: #3b82f6;
// --font-size-base: 16px;
// --border-radius-sm: 4px;

Kebab case in frameworks

Tailwind CSS (custom classes)

<!-- Tailwind uses kebab-case for all utilities -->
<div class="flex items-center justify-between gap-4">
  <span class="text-sm font-medium text-gray-600">Label</span>
  <button class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-md">
    Submit
  </button>
</div>

Next.js file-based routing

pages/
  user-profile.tsx      → /user-profile
  blog/
    [post-slug].tsx     → /blog/:post-slug
  api/
    auth-callback.ts    → /api/auth-callback

Kebab case vs other conventions

ConventionExampleUsed In
kebab-caseuser-nameCSS, URLs, HTML attributes, npm
snake_caseuser_namePython, SQL, Ruby
camelCaseuserNameJS variables, React props
PascalCaseUserNameClasses, React components

Related posts

Related tool

Case Converter

Convert text between camelCase, PascalCase, snake_case, kebab-case, SCREAMING_CASE, Title Case, sentence case, and more. Bulk mode.

Written by Mian Ali Khalid. Part of the Dev Productivity pillar.