ケバブケースってそもそも何か
まず言葉の整理からいきましょう。
「ケバブケース(kebab-case)」は、単語をハイフン - でつなぎ、全部小文字で書くスタイルです。
"userName" → "user-name""UserID" → "user-id""createdAt" → "created-at"
HTML のクラス名や、CSS のプロパティ名、
一部の設定ファイル(YAML など)では、ケバブケースがよく使われます。
JavaScript の世界では userName(キャメルケース)が主流ですが、
「外に出すときは user-name にしたい」という場面が結構あります。
そのギャップを埋めるのが「ケバブケース化ユーティリティ」です。
何を「ケバブケース」に変換したいのか
業務でよくあるのは、次のような状況です。
JavaScript の変数名・プロパティ名は userName で書いている。
CSS のクラス名や data 属性は user-name にしたい。
設定ファイルや API のパラメータ名がケバブケースで決まっている。
つまり、内部ではキャメルケースやパスカルケース、
外部の世界ではケバブケース、という構造です。
このとき、
「内部の名前 → ケバブケースの文字列」
に変換する小さな関数があると、とても楽になります。
ケバブケース化の基本的な考え方
キャメルケース(userNameId)をケバブケース(user-name-id)にする流れを分解すると、こうなります。
大文字の手前にハイフン - を挿入する。
全体を小文字にする。
例えば userNameId なら、
userNameIduser-Name-Id(大文字の前に - を入れるイメージ)user-name-id(全部小文字にする)
という変換です。
UserID のように先頭が大文字、かつ大文字が連続するケースもあります。
この場合は、連続する大文字の「切れ目」にハイフンを入れる、という一工夫が必要です。
シンプルなケバブケース化ユーティリティ
実装例
初心者でも追いやすい形で書いてみます。
function toKebabCase(value) {
if (value == null) return "";
const str = String(value).trim();
if (str === "") return "";
const withHyphen = str
// 小文字 or 数字の直後に大文字が来たら、その間にハイフンを入れる
.replace(/([a-z0-9])([A-Z])/g, "$1-$2")
// 連続する大文字にも対応(UserID → User-ID)
.replace(/([A-Z])([A-Z][a-z])/g, "$1-$2");
return withHyphen
.replace(/[\s_]+/g, "-") // 空白やアンダースコアもハイフンに
.toLowerCase();
}
JavaScriptやっていることを順番に噛み砕きます。
value == null(null / undefined)のときは空文字を返す。String(value).trim() で文字列化し、前後の空白を削る。([a-z0-9])([A-Z]) で「小文字 or 数字の直後の大文字」を見つけて、その間に - を挟む。([A-Z])([A-Z][a-z]) で「連続する大文字の切れ目」に - を挟む(UserID → User-ID)。
空白やアンダースコアは - にまとめる。
最後に toLowerCase() で全部小文字にする。
これで、キャメルケース・パスカルケース・スネークケース・スペース区切りなど、
よくあるパターンはだいたいケバブケースに変換できます。
具体例で動きを確認する
キャメルケースからケバブケースへ
toKebabCase("userName"); // "user-name"
toKebabCase("userNameId"); // "user-name-id"
toKebabCase("createdAt"); // "created-at"
JavaScriptJavaScript のプロパティ名を、そのまま CSS クラス名っぽくできます。
パスカルケースからケバブケースへ
toKebabCase("UserName"); // "user-name"
toKebabCase("UserID"); // "user-id"
toKebabCase("HTTPRequest"); // "http-request"
JavaScript先頭が大文字でも、連続する大文字があっても、
それなりに自然なケバブケースになります。
スネークケース・スペース区切りからケバブケースへ
toKebabCase("user_name"); // "user-name"
toKebabCase("user name"); // "user-name"
toKebabCase(" user name "); // "user-name"
JavaScript設定ファイルやラベルからキー名を作るときにも、そのまま使えます。
業務での実用的な使いどころ
CSS クラス名や data 属性の生成
例えば、コンポーネント名や状態名から CSS クラス名を作りたいとします。
const componentName = "UserCard";
const state = "isActive";
const baseClass = toKebabCase(componentName); // "user-card"
const stateClass = toKebabCase(state); // "is-active";
const className = `${baseClass} ${baseClass}--${stateClass}`;
// "user-card user-card--is-active"
JavaScript内部ではキャメル/パスカルで扱い、
HTML に出すときだけケバブケースにする、という分離ができます。
設定ファイルや API パラメータ名とのマッピング
外部仕様で「パラメータ名はケバブケース」と決まっていることもあります。
const options = {
maxItems: 10,
showHeader: true,
};
function buildQuery(params) {
const query = new URLSearchParams();
for (const key in params) {
const kebabKey = toKebabCase(key);
query.set(kebabKey, String(params[key]));
}
return query.toString();
}
buildQuery(options);
// "max-items=10&show-header=true"
JavaScript内部では maxItems / showHeader で統一しつつ、
外に出すときだけケバブケースに変換できます。
設計として大事なポイント
「内部表現」と「外部表現」を分ける
一番大事なのは、
「内部ではキャメルケースで統一する」と決めてしまうことです。
そのうえで、
外部に出ていくとき(HTML クラス名、data 属性、クエリパラメータなど)はケバブケース化する。
外部から入ってくるとき(設定ファイルなど)がケバブケースなら、入口でキャメルケース化する。
というふうに、「入口」と「出口」で変換する設計にします。
これをやっておくと、
「この名前は userName だっけ? user-name だっけ?」
「CSS と JS で名前が微妙に違ってバグる」
といった混乱が一気に減ります。
変換をその場その場でやらない
悪いパターンは、使うたびにバラバラに変換することです。
toKebabCase("userName");
toKebabCase("userName");
toKebabCase("userName");
JavaScriptどこで何が変換されているのか分からなくなります。
良いパターンは、
「外に出す直前」に一度だけケバブケース化する
それ以外の場所ではキャメルケースだけを使う
という流れにすることです。
小さな練習で感覚をつかむ
コンソールで、いくつか試してみてください。
toKebabCase("userName");
toKebabCase("UserName");
toKebabCase("userNameId");
toKebabCase("UserID");
toKebabCase("user_name");
toKebabCase(" user name id ");
JavaScriptどういうルールでハイフンが入って、
最終的に全部小文字になっているかを目で確認すると、
「ケバブケース化」の感覚がかなりつかめます。
そのうえで、自分のプロジェクトに
export function toKebabCase(value) { ... }
JavaScriptを一つ置いて、
「HTML や外部仕様で“ケバブケース指定”のところは必ずここを通す」
というルールにしてみてください。
それができた瞬間、あなたのコードは
「命名規則の違いに振り回される側」から
「自分たちのルールに正規化してから外と話す側」に、一段レベルアップします。
