Zum Inhalt springen
Allin

camelCase, snake_case, kebab-case: welche - und warum du selten die Wahl hast

Veröffentlicht am 3.7.2026 · 11 Min. Lesezeit · Text- & Sprach-Tools

Daniel Okonkwo

Daniel OkonkwoFront-end-Entwickler und Tech-Redakteur bei Allin

Web-Performance · Dateiformate

Anhand von 7 Quellen geprüft

Profil ansehen
Kurz gesagt

Jede Konvention wird von der umgebenden Syntax erzwungen, nicht nach Geschmack gewählt. In fast jeder Infix-Sprache ist der Bindestrich der Subtraktionsoperator: user-name wird als user minus name gelesen und kann kein Bezeichner sein - JavaScript wirft bei var user-name einen SyntaxError. Diese eine Tatsache teilt die Welt. CSS-Eigenschaftsnamen, HTML-Attribute und URL-Pfade leben in Grammatiken, in denen Bezeichner nie Ausdrücke sind; dort ist der Bindestrich eindeutig und kebab-case der native Stil. Sprachen der Lisp-Familie erlauben Kebab-Bezeichner aus demselben Grund: Sie sind präfix, nicht infix. Alles andere landet bei snake_case oder camelCase, und die Wahl fällt je Ökosystem: PEP 8 schreibt snake_case für Python-Funktionen und -Variablen vor; Rust ebenso, und sein Compiler warnt standardmäßig; Go verlangt MixedCaps und macht den Anfangsbuchstaben semantisch, denn er steuert den Export; Java und JavaScript nutzen lowerCamelCase mit PascalCase-Typen. Die Falle ist der Rundtrip. camelCase nach snake_case und zurück ist bei Akronymen nicht verlustfrei: parseHTMLDocument wird zu parse_htmldocument und dann zu parseHtmldocument, und die Wortgrenze ist für immer weg. Behebe es an der Quelle, indem du Akronyme wie gewöhnliche Wörter schreibst, wie es der Google Java Style Guide verlangt. Und ein URL-Slug ist eine vierte Sache: kleingeschrieben, akzentbefreit, längenbegrenzt.

Die Konventionen sind keine Geschmacksfrage. Der Bindestrich ist der Minus-Operator, deshalb kann kebab-case in den meisten Sprachen kein Bezeichner sein - und genau darum nutzen CSS und URLs ihn. Dazu der Akronym-Rundtrip, der Namen stillschweigend zerstört, und die Regel, die ihn heilt.

Der Bindestrich ist der Minus-Operator - das ist die ganze Erklärung

Tippe var user-name = 1 in Node, und du bekommst SyntaxError: Unexpected token '-'. Der Parser stellt sich nicht an. In einer Infix-Sprache bedeutet a-b in Ausdrucksposition: b von a abziehen - und der Tokenizer kann unmöglich wissen, dass du einen Bezeichner statt zweier Operanden meintest. Python, Java, C, C#, Go, Rust, PHP, Ruby und SQL teilen diese Einschränkung. Der Bindestrich ist vergeben.

Damit bleiben genau zwei Wege, Wörter innerhalb eines Bezeichners zu verbinden: der Unterstrich, den keine Sprache als Operator nutzt, oder ein Großbuchstabe, der im Sinne des Tokenizers gar kein Trennzeichen ist. snake_case und camelCase sind keine zwei ästhetischen Schulen. Sie sind die einzigen zwei Lösungen für eine Beschränkung, die die Arithmetik auferlegt.

Die Ausnahme bestätigt die Regel. Lisp, Scheme, Clojure und Common Lisp erlauben kebab-case-Bezeichner - make-hash-table, my-function-name - weil sie Präfixsprachen sind: Subtraktion schreibt man (- a b), ein Bindestrich zwischen Buchstaben kann also nie ein Operator sein. Ändert sich die Grammatik, ändert sich die Namenskonvention mit - genau darum geht es.

Wo kebab-case zu Hause ist: CSS, HTML-Attribute, URLs

In CSS ist background-color ein Eigenschaftsname an einer Stelle, an der kein Ausdruck erlaubt ist - der Bindestrich kann mit nichts verwechselt werden. Dass CSS die Spannung kennt, beweist calc(): Die Spezifikation verlangt dort Leerzeichen um Plus und Minus, genau weil das die eine Stelle in CSS ist, an der ein Bindestrich entweder Subtraktion oder Teil eines Bezeichners sein könnte. HTML-Attribute folgen derselben Logik: data-user-id ist ein Name in Attributposition, nie ein Ausdruck.

Interessant wird es an der Übergangsstelle. Das DOM muss data-user-id an JavaScript weiterreichen, wo der Bindestrich unzulässig ist, also benennt es um: element.dataset.userId. Das CSS Object Model tut dasselbe mit Eigenschaften und macht aus background-color style.backgroundColor. Diese beiden automatischen Umwandlungen sind der denkbar klarste Beleg dafür, dass die Konvention allein eine Funktion der Wirtsgrammatik ist: derselbe Name, zwei Schreibweisen, weil zwei Grammatiken zwei Schreibweisen verlangen.

URLs erlauben Bindestrich wie Unterstrich - beide sind unreservierte Zeichen -, hier ist der Grund also ein anderer und weit weicher. Googles eigene URL-Empfehlungen bevorzugen den Bindestrich, weil er für Crawler wie für Menschen als Worttrenner gelesen wird und weil ein Unterstrich unter der Unterstreichung eines Links verschwinden kann. Das ist ein Lesbarkeits-, kein Grammatikargument - doch es ist zu einer so festen Konvention erstarrt, dass eine URL mit Unterstrichen heute wie ein Fehler aussieht.

Der Rundtrip, der Information verliert

camelCase nach snake_case und zurück zu wandeln sieht nach einer Bijektion aus. Ist es nicht, und Akronyme sind die Bruchstelle. Ein naiver Konverter setzt vor jeden Großbuchstaben, der auf einen Kleinbuchstaben folgt, einen Unterstrich und schreibt dann alles klein. Schick parseHTMLDocument hindurch, und du bekommst parse_htmldocument, denn vor H, T, M und L steht kein Kleinbuchstabe. Zurückgewandelt ergibt das parseHtmldocument. Die Wortgrenze zwischen HTML und Document ist weg, und keine nachgelagerte Raffinesse holt sie zurück.

getIDFromURL ist schlimmer, denn der Schaden bleibt nicht bei der Groß-/Kleinschreibung. Die naive Regel liefert get_idfrom_url - sie greift zwischen t und I und erneut zwischen m und U, aber nicht innerhalb von IDFrom - und zurückgewandelt kommt getIdfromUrl heraus. Aus einem Namen aus drei klaren Wörtern sind zwei verstümmelte geworden, und ist diese Zeichenkette eine Datenbankspalte, ein JSON-Schlüssel oder ein API-Feld, ist die Verstümmelung nun persistiert.

Die Regel, die es behebt - und der Fall, den sie weiter verfehlt

Die Lösung ist eine zweite Grenzregel. Neben der üblichen Trennung klein-dann-groß kommt eine Trennung zwischen einer Folge von Großbuchstaben und einem Großbuchstaben, dem ein Kleinbuchstabe folgt. In regulären Ausdrücken sind das zwei Durchgänge: einen Unterstrich zwischen ([a-z0-9]) und ([A-Z]) einfügen, dann zwischen ([A-Z]+) und ([A-Z][a-z]), danach alles klein. Mit diesen beiden Regeln wird parseHTMLDocument zu parse_html_document und kommt als parseHtmlDocument zurück; getIDFromURL wird get_id_from_url und kommt als getIdFromUrl zurück; exportToPDFFile wird export_to_pdf_file. Die Kebab-Formen lauten parse-html-document, get-id-from-url und export-to-pdf-file. Die Wortgrenzen überleben.

Beachte: Der Rundtrip ist weiterhin nicht die Identität - parseHTMLDocument kommt als parseHtmlDocument zurück, das Akronym in Titelschreibung. Das ist das richtige Ergebnis, kein Restfehler, und es weist auf die eigentliche Lösung. Abschnitt 5.3 des Google Java Style Guide verlangt genau das schon beim Schreiben: Akronyme wie gewöhnliche Wörter schreiben, also XmlHttpRequest statt XMLHTTPRequest - dann wird der Name zum Fixpunkt der Umwandlung. Ein Name, der seinen eigenen Rundtrip übersteht, lässt sich gefahrlos durch Codegenerator, ORM, Serialisierer und zurück schicken.

Einen Fall bekommt die Zwei-Regex-Regel weiterhin falsch, und man sollte ihn kennen, weil er wie ein Versagen der Regel aussieht. Akronyme mit gemischter Schreibung hebeln sie aus: supportsIPv6 wird supports_i_pv6, die Kebab-Form supports-i-pv6. Die zweite Regex sieht das große P gefolgt vom kleinen v und trennt dort - genau das soll sie überall sonst tun. Keine Grenzregel, die nur auf Groß- und Kleinschreibung schaut, kann wissen, dass IPv6 ein Token ist. Das ist das stärkste Argument für die Google-Regel: Schreib gleich supportsIpv6, dann muss der Konverter nie raten.

Ein URL-Slug ist eine vierte Sache, nicht kebab-case mit Zusatzschritten

Ein Slug sieht aus wie kebab-case, hat aber drei zusätzliche Pflichten, die ein Bezeichner nie hat. Er muss die Kleinschreibung überstehen, denn Server vergleichen URL-Pfade groß-/kleinschreibungssensitiv, während Menschen sie nachlässig tippen. Er muss das Entfernen der Akzente überstehen, denn ein Pfad mit Akzentzeichen wird prozentkodiert und unlesbar. Und er muss in ein Längenbudget passen, denn Slugs landen in E-Mails, Druckerzeugnissen und Adressleisten, wo ein 200-Zeichen-Pfad unbrauchbar ist.

Beim Entfernen der Akzente verlieren naive Implementierungen stillschweigend Daten. Das übliche Rezept: in die zerlegte Form normalisieren, die kombinierenden Zeichen löschen, dann nur Buchstaben, Ziffern und Bindestriche behalten. Auf einen französischen Titel angewandt funktioniert es: Crème Brûlée & Co. — 2026 Edition wird zu creme-brulee-co-2026-edition, 28 Zeichen. Auf Deutsch angewandt zerstört es Text. Der Titel Größe & Maße: der Überblick kommt als gro-e-ma-e-der-uberblick heraus - denn das scharfe s hat keine kanonische Zerlegung, wird also auf nichts abgebildet, sondern schlicht gelöscht wie jedes andere Zeichen, das kein lateinischer Buchstabe ist.

Die Lösung: vor dem Normalisieren transliterieren, mit einer Tabelle je Sprache - scharfes s zu ss, Umlaute zu oe, ae und ue im Deutschen, das skandinavische durchgestrichene o und das a mit Ring zu ihren zweibuchstabigen Entsprechungen. Mit diesem vorgeschalteten Schritt ergibt derselbe deutsche Titel groesse-masse-der-ueberblick - 28 Zeichen und tatsächlich lesbar. Halte den erzeugten Slug nach der Veröffentlichung unveränderlich, deckle ihn bei etwa 60 bis 80 Zeichen an einer Wortgrenze, und erzeuge ihn nie aus einem geänderten Titel neu, ohne eine Weiterleitung vom alten einzurichten.

Die Wahl in der Praxis

Richte dich nach dem Wirt, nicht nach deiner Vorliebe. In einer Python-Datei snake_case, auch wenn das JSON, das du parst, camelCase ist. In einer CSS-Datei kebab-case, auch wenn die Design-Tokens in camelCase verfasst wurden. In einem PostgreSQL-Schema snake_case, denn der Parser schreibt dein camelCase ohnehin klein, und du verbringst den Rest des Projekts damit, doppelte Anführungszeichen zu tippen.

Wandle nur an Grenzen um, und nur an einer Stelle. Spricht deine API camelCase und deine Datenbank snake_case, setz eine einzige Abbildungsschicht dazwischen, statt an jeder Aufrufstelle ad hoc zu konvertieren - und mach diese Schicht zum einzigen Code, der die Zwei-Regex-Regel kennt. Schreib Akronyme überall wie Wörter, damit die Umwandlung ein Fixpunkt ist und niemand mehr darüber nachdenken muss. Und behandle einen erzeugten Slug ab dem Moment der Veröffentlichung als publizierten Bezeichner: Er ist die einzige dieser vier Formen, die Fremde in eine Nachricht kopieren.

Was der jeweils eigene Style Guide des Ökosystems vorschreibt - und was es tatsächlich erzwingt: Konvention, ein Linter oder der Parser selbst.
ÖkosystemVariablen und FunktionenTypen und KlassenKonstantenWas es erzwingt
Python (PEP 8)snake_caseCapWordsUPPER_SNAKE_CASEReine Konvention; Linter warnen, der Interpreter akzeptiert alles
Rustsnake_caseUpperCamelCaseSCREAMING_SNAKE_CASEDer Compiler: non_snake_case und non_camel_case_types warnen standardmäßig
GomixedCapsMixedCapsMixedCaps, nie UnterstricheDer Compiler: Ein großer Anfangsbuchstabe exportiert den Bezeichner - Groß-/Kleinschreibung ist Semantik, nicht Stil
Java (Google Java Style)lowerCamelCaseUpperCamelCaseUPPER_SNAKE_CASEKonvention plus die ausdrückliche Regel, Akronyme wie Wörter zu schreiben: XmlHttpRequest, nicht XMLHTTPRequest
JavaScript und TypeScriptcamelCasePascalCaseUPPER_SNAKE_CASEKein offizieller Leitfaden; die Grammatik schließt allein den Bindestrich aus, weil er der Minus-Operator ist
CSS und HTMLkebab-case für Eigenschaften, Klassen und benutzerdefinierte EigenschaftenCSS kennt keine benutzerdefinierten Typen; HTML-Elementnamen sind kleingeschriebenbenutzerdefinierte Eigenschaften in kebab-case, mit zwei Bindestrichen als PräfixDie Grammatik: Ein Eigenschaftsname ist nie ein Ausdruck, ein Bindestrich darin kann also kein Minus sein - deshalb verlangt calc() Leerzeichen um seine Minuszeichen
PostgreSQLsnake_case für Tabellen und Spaltensnake_case für Typen und DomänenUPPER_SNAKE_CASE nur konventionellDer Parser: Unquotierte Bezeichner werden auf Kleinschreibung gefaltet - ein camelCase-Tabellenname wird stillschweigend klein, es sei denn, du setzt ihn für immer in Anführungszeichen
kebab-case-KonverterWandle beliebigen Text oder camelCase-Bezeichner in kleingeschriebenes kebab-case (mit Bindestrichen) um.Tool ausprobieren

Häufige Fragen

Warum kann ich in CSS background-color schreiben, aber nicht backgroundColor?
Weil CSS-Eigenschaftsnamen ein festes, von der Spezifikation definiertes Vokabular sind - und die Spezifikation schreibt sie in kebab-case. Nicht camelCase ist grammatisch verboten: backgroundColor ist schlicht kein Eigenschaftsname, die Deklaration wird als unbekannt verworfen. Die camelCase-Schreibweisen existieren nur im CSS Object Model, der JavaScript-Sicht auf einen Stil, wo der Bindestrich ein Minuszeichen wäre. Zwei Schreibweisen, zwei Grammatiken, eine Eigenschaft.
Liest sich camelCase oder snake_case leichter?
Die veröffentlichten Blickbewegungsstudien dazu sind wenige, alt und umstritten und tragen keine starke Aussage in irgendeine Richtung: Manche finden snake_case marginal schneller lesbar, andere finden geübte Leser jeweils in dem Stil schneller, den sie täglich benutzen. Unumstritten sind die Kosten der Uneinheitlichkeit innerhalb einer Codebasis. Nimm, was das Ökosystem vorschreibt, erzwing es mit einem Formatierer und gib dein Diskussionsbudget für etwas aus, das Verhalten ändert.
Wie wandle ich das camelCase-JSON einer API sicher in eine snake_case-Datenbank um?
Nimm die zweistufige Grenzregel, wende sie in genau einem Modul an und fixiere die Abbildung für jeden Namen mit Akronym. Pragmatisch heißt das: eine ausdrückliche Ausnahmetabelle führen - ein kurzes Wörterbuch der fünfzehn oder zwanzig Feldnamen deines Schemas, über deren Umwandlung keine Regex entscheiden soll. Diese Tabelle kostet eine Stunde und beseitigt die gesamte Fehlerklasse, während eine rein algorithmische Abbildung irgendwann auf einen Namen wie supportsIPv6 trifft und etwas erzeugt, das niemand im Review bemerkt - bis eine Abfrage nichts zurückgibt.
Kann ich camelCase für PostgreSQL-Tabellen- und Spaltennamen verwenden?
Kannst du - aber nur, indem du den Bezeichner jedes einzelne Mal in doppelte Anführungszeichen setzt, für immer, in jeder Abfrage, Migration, View und jedem Skript. PostgreSQL faltet unquotierte Bezeichner auf Kleinschreibung, eine als userAccounts angelegte Tabelle wird also useraccounts, und eine spätere Abfrage nach userAccounts findet sie nur, weil auch die zu useraccounts gefaltet wird - bis jemand eine davon quotiert und beide nicht mehr zusammenpassen. snake_case ist hier keine Stilvorliebe, sondern die Form, die den Parser unversehrt übersteht.
Sollte ein URL-Slug einfach der Titel in kebab-case sein?
Fast, aber mit drei Zusätzen, die kebab-case allein nicht liefert. Alles kleinschreiben, denn ein Pfad, der sich nur in der Groß-/Kleinschreibung unterscheidet, ist für einen Server eine andere Ressource, für Menschen dieselbe Sache. Vor dem Entfernen der Akzente transliterieren, sonst verschwinden Zeichen wie das scharfe s ganz, statt zu ss zu werden. Und die Länge an einer Wortgrenze deckeln, etwa bei 60 bis 80 Zeichen, denn der Slug wird an Stellen eingefügt, wo kein Platz ist. Eine weitere Regel, die nichts mit Schreibung zu tun hat: Einmal veröffentlicht, nie ohne dauerhafte Weiterleitung vom alten Pfad ändern.

Artikel, die dich interessieren könnten

Alle Ratgeber
ErklärungcamelCase vs. snake_case: Ein Leitfaden zu Namenskonventionen im CodecamelCase, snake_case, PascalCase und kebab-case erklärt: wie jede aussieht, wo sie Konvention ist und wie man eine konsequent wählt.RatgeberURL-Kodierung erklärt: Prozentkodierung und wo sie beißtProzentkodierung wird pro URL-Komponente entschieden, und genau daher rührt die Verwirrung. Ein Schrägstrich ist in einem Pfad erlaubt und muss in einem Query-Wert maskiert werden; ein Leerzeichen ist im Pfad %20 und im Formularkörper womöglich +. Hier stehen die exakten RFC-3986-Mengen, die drei uneinigen JavaScript-Funktionen und die Fallen.ErklärungDie Caesar-Chiffre erklärt: So funktionieren Verschiebechiffren und ROT13Die Caesar-Chiffre verschiebt jeden Buchstaben um einen festen Betrag. Erfahre, wie die Verschiebung funktioniert, warum ROT13 ein Sonderfall ist, wie man von Hand ver- und entschlüsselt und warum die Chiffre heute keine echte Sicherheit bietet.AnleitungJSON in CSV umwandeln: Arrays von Objekten in Zeilen und Spalten überführenEine praktische Anleitung, um ein JSON-Array von Objekten in eine saubere CSV-Datei zu verwandeln, samt Abflachen verschachtelter Felder und heikler Sonderfälle.ErklärungAkzente entfernen zerstört die Suche — bis du es auf beiden Seiten tustDiakritika zu falten ist ein Normalisierungsschritt, und Normalisierung wirkt nur, wenn dieselbe Funktion über Index und Suchanfrage läuft. NFC gegen NFD mit offengelegten Codepunkten und die Buchstaben — ø, ł, ß, œ, ı —, die den Faltvorgang unverändert überstehen.ErklärungHashtags sind ein Suchindex, kein MegafonEin Hashtag macht einen Beitrag in einer Suche auffindbar, was eine andere Aufgabe ist, als ihn zu verbreiten. Modelliere die Sichtbarkeit, die ein Tag tatsächlich kauft, und die Antwort fällt heraus: Der Wert eines Tags ist seine Zahl an Betrachtern je veröffentlichtem Beitrag, nicht sein Volumen — ein sehr beliebtes Tag bringt also fast nichts und ein spezifisches fünfundzwanzigmal mehr.

Ähnliche Tools

Quellen

Hast du einen Fehler in diesem Artikel entdeckt?