Herzlich willkommen zum SELF-Treffen 2026
vom 24.04. – 26.04.2026
in Halle (Saale)
Karaoke
Karaoke (japanisch カラオケ) ist eine weltweit bekannte Freizeitbeschäftigung und ein Partyspiel aus Japan, bei der Mitspieler zum Instrumental-Playback bekannter Musikstücke live ins Mikrofon singen. Damit die Singenden nicht nur mitsummen, ist ein Textblatt empfehlenswert, bei dem wir aber noch die entsprechenden Akkorde hinzufügen wollen.
Anforderung an Textblätter für Proben und Auftritte
- nur eine Seite A4,
um Blättern beim Auftritt vermeiden - Text so groß wie möglich,
um die Breite der Seite nutzen - Akkorde in einem deutlichen Font
um z.BCdeutlich vonGzu unterscheiden.[1]
Hier lernst du, wie man Liedtexte übersichtlich auf einer Webseite anzeigen kann. Dazu verwenden wir einfache HTML-Elemente für den Text und CSS, um das Ganze ansprechend zu gestalten.
Zusätzlich kannst du mit kleinen Effekten wie dem Hervorheben der aktuellen Zeile den Text für Auftritte oder Proben besonders gut nutzbar machen.
Inhaltsverzeichnis
Liedtexte anzeigen
monospace: Der falsche Weg
Webseiten mit Liedtexten und Akkorden werden gerne mit font-family: monospace definiert, um die Akkorde mit Leerzeichen eine Zeile über den Silben zu positionieren. Dadurch geht viel Platz verloren und man braucht mehrere Seiten oder ganz kleine Schrift.
Es gab im Forum immer wieder die Frage, wie man Liedtexte in HTML auszeichnen solle.
Jede Zeile in einem Absatz?
Ein <br> nach jeder Zeile?
Zwischenzeitlich sollte ein custom element namens x-line Abhilfe schaffen.
<p style="white-space:pre; font-family:monospace">
Am G Am
Are you going to Scarborough Fair?
C Am D Am
Parsley, sage, rosemary and thyme,
C G
Remember me to one who lives there,
Am G Am
She once was a true love of mine.
</p>
In diesem Beispiel ist der Text mitsamt Akkorden in einem Absatz notiert. Dieser wird mit white-space: pre so formatiert, dass Zeilenumbrüche im Quelltext respektiert werden. Mit font-family: monospace wird sichergestellt, dass die eingerückten Akkorde in der Zeile darüber passend zum Text stehen.
Allerdings ist so keine direkte Zuordnung zwischen Textstelle und Akkord gegeben.
Text und Akkord im semantischen Zusammenhang
Ruby (japanisch ルビ rubi) bezeichnet ein Anmerkungssystem, bei dem der Text zusammen mit seiner Anmerkung in einer Zeile erscheint. Dies wird vor allem bei asiatischen Texten genutzt, da die dort verwendeten chinesischen Schriftzeichen in vielen Fällen keinen Aufschluss über die tatsächliche Aussprache geben.[2][3]
Dies gibt es auch in HTML:
<section class="lyrics">
<p class="part">1.</p>
<p class="line">
<ruby>Are<rt>Am</rt></ruby> you going to <ruby>Scarborough<rt>G</rt></ruby> <ruby>Fair?
<p class="line">
<rt>Am</rt></ruby> <ruby> <rt>C</rt></ruby>Parsley, <ruby>sage<rt>Am</rt></ruby>, rose-<ruby>mary<rt>D</rt></ruby> and <ruby>thyme,<rt>Am</rt></ruby></p>
...
/* CSS */
ruby {
ruby-position: over;
margin: 0 0.2em;
}
rt {
font-size: 0.9em;
color: #f77;
font-weight: bold;
}
Jeder Akkord ist nun direkt einer Textstelle zugeordnet: Das Wort ist in einem ruby-Element ausgezeichnet und erhält als Kind nun den Akkord in einem rt-Element.
Boomwhacker Musical Notation
Boomwhackers sind Musikinstrumente aus der Gruppe der Schlagidiophone, die auf eine bestimmte Tonleiter gestimmt und daher als Melodieinstrument verwendet werden können.
In der musikalischen Früherziehung haben sich Boomwhacker derart etabliert, dass einige Softwarehersteller Funktionen zum automatischen Generieren farbiger Noten in ihre Notensatzprogramme integriert haben.[4]
International (englischsprachig) wird das deutsche H als B bezeichnet.
span {
color: var(--bgColor);
filter: invert(1) grayscale(1) brightness(1.3) contrast(9000);
mix-blend-mode: luminosity;
opacity: 0.95;
}
Das Script übernimmt den Textinhalt des rt-Elements, erzeugt eine Klasse für rt und fügt den Text in einen span ein. Über die Klasse erhält das rt-Element einen farblich gekennzeichneten Hintergrund.
Die Textfarbe des span-Elements wird mit der CSS-filter-Eigenschaft so gefärbt, dass sie immer ausreichend hohen Kontrast erhält.
Langfristig kann dies mit der contrast-color()-Funktion einfacher erreicht werden.
Karaoke-Player
Beim gängigen Karaoke-Player spielt das Audio und der Liedtext scrollt in einer Box, der aktuelle Text wird farblich hervorgehoben, damit man passend mitsingen kann.
Moderne Mittel dazu sind z.B. eine MP3-Datei für das Audio und eine .lrc-Datei mit den Texten und Zeitstempeln.
Textstellen mit timestamps markieren
In diesem Abschnitt geht es darum, Liedtexte mit der Musik zu synchronisieren. Dafür werden Zeitangaben (Timestamps) genutzt, die entweder in JSON-Dateien oder in speziellen LRC-Lyrics-Dateien gespeichert sind.
Mit etwas JavaScript kannst du dann beim Abspielen des Songs die jeweils aktuelle Zeile automatisch hervorheben – genau wie in einem Karaoke-System.
Die einfachste Version: Händisch können Zeitstempel einfach im HTML notiert und dann per Script ausgelesen werden.
<section class="lyrics">
<p class="part">1.</p>
<p class="line" data-time=".5">
<ruby>Are<rt>Am</rt></ruby> you going to <ruby>Scarborough<rt>G</rt></ruby> <ruby>Fair?<rt>Am</rt></ruby>
</p>
<p class="line" data-time="4.5">
<ruby> <rt>C</rt></ruby>Parsley, <ruby>sage<rt>Am</rt></ruby>, rose-<ruby>mary<rt>D</rt></ruby> and <ruby>thyme,<rt>Am</rt></ruby>
</p>
// Script:
const lines = Array.from(document.querySelectorAll('.line'));
const times = lines.map(line => parseFloat(line.dataset.time));
In diesem Beispiel wird der Text inline notiert, weil es beim Fetch einer .lrc-Datei verschiedene Einschränkungen gibt, welche auch unser Wiki betreffen, Details stehen im Quellcode.
// LRC-Text inline
const lrcInhalt = String.raw`
[ar:Traditional]
[ti:Scarborough Fair]
[offset:0]
[00:00.50]Are you going to Scarborough Fair?
[00:04.50]Parsley, sage, rose- mary and thyme,
[00:09.50]Remember me to one who lives there,
[00:15.50]She once was a true love of mine.
…
`;
// LRC parsen
function lrcParsen(rohtext) {
const zeitMuster = /\[(\d{2}):(\d{2}\.\d+)\](.+)/;
return rohtext
.split("\n")
.map(zeile => {
const treffer = zeile.match(zeitMuster);
if (!treffer) return null;
const minuten = parseFloat(treffer[1]);
const sekunden = parseFloat(treffer[2]);
return { zeit: minuten * 60 + sekunden, text: treffer[3].trim() };
})
.filter(Boolean)
.sort((a, b) => a.zeit - b.zeit);
}
Diese Eigenbaulösung zeigt die Vorgehensweise, für einen einsatz bei Festen und Veranstaltungen würde ich kommerzielle Lösungen, die die Daten bereits fertig aufbereitet haben, vorziehen.
mehrstimmiger Boomwhacker-Player
Jedes .part-Elementes per Grid mit 6 Spalten pro 3/4 Takt.
Noten werden per CSS-Custom-Property in die gewünschte Spalte platziert, z.B. der CSS Code style="--c:5" im HTML gibt die 5. Spalte an: Damit wird aus der CSS-Anweisung .note { grid-column: var(--c); } und der Variablen-Zuweisung --c:5 das Ergebnis .note { grid-column: 5; }. Die Zwischenspalten ermöglichen Töne zwischen den Viertel-Schlägen (Achtel).
Weil diese Audiodatei per Computer zusammengeklickt wurde, sind die Zeiten der Takte für die Markierung einfach berechenbar (anstelle der Verwendung von Zeitstempeln wie in obigen Beispielen).
Die Formel zieht firstBarStart ab (überspringt Vorzähler + Offset), teilt durch die Taktdauer und rundet ab — das ergibt den laufenden Takt-Index.
/* Grid mit 6 Spalten pro 3/4 Takt: */
.part {
display: grid;
grid-template-columns: repeat(6, 1.5em);
}
.note { grid-column: var(--c); }
<!-- Platzierung einer Note in den 6 Schlägen pro Takt: -->
<span class="note d" style="--c:1">d</span>
<span class="note d" style="--c:5">d</span>
// Zeitstempel für die Taktmarkierung
const BPM = 160; // Tempo (Beats per Minute)
const BEATS_PER_BAR = 3; // 3/4 Takt
const COUNT_IN_BEATS = 3; // Einzähler
const EARLY_OFFSET = 0.5; // visueller Vorsprung, damit die Markierung kurz vor dem Audio erscheint
const secondsPerBeat = 60 / BPM; // → 0.375 s
const secondsPerBar = secondsPerBeat * 3; // → 1.125 s
const firstBarStart = secondsPerBeat * COUNT_IN_BEATS - EARLY_OFFSET; // → 0.625 s
// Takt-Index zur Laufzeit
function getMeasureIndex(currentTime) {
if (currentTime < firstBarStart) return -1;
const barIndexFromStart = Math.floor(
(currentTime - firstBarStart) / secondsPerBar
);
return ((barIndexFromStart % totalBarsPerCycle) + totalBarsPerCycle) % totalBarsPerCycle; // mit Modulo abrunden
}
// Markierung setzen:
measures[nextIndex].classList.add('active');
Weblinks
- ↑ Empfehlung: FE Mittelschrift Regular.otf (für Autokennzeichen plus Kleinbuchstaben)
- ↑ Ruby-Annotation (de.wikipedia.org)
- ↑ TIL about ruby (振り仮名) Tech Talk @ Tagesspiegel by Gunnar Bittersmann
CodePen - ↑ Boomwhacker (de.wikipedia.org)