Scribe 0.4

Scribe is a CSS-powered technique for displaying music notation, packaged in a custom element that turns sequence data into HTML. Scribe is laid out using flex and grid, sized in relative font sizes, and responds to the flow of the web, making it very readable, and perfect for embedding musical examples in tutorials, for publishing lead sheets to be read on a phone at a gig, or for live feedback of, say, MIDI input in a web app.

<scribe-music src="./blue-in-green.json"></scribe-music>
<scribe-music clef="drum" src="./caravan-drums.json"></scribe-music>
<scribe-music clef="piano" src="./ae-fond-kiss.json"></scribe-music>

There are more examples on the-dots.app.

Get started

Import the custom element

Include the CSS and JS from the CDN in your document <head>:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/stephband/scribe@0.4.x/build/scribe-music/element.css" />
<script type="module" src="https://cdn.jsdelivr.net/gh/stephband/scribe@0.4.x/build/scribe-music/element.js"></script>

Write a tune

Write some sequence data and use <scribe-music> to render it:

<script type="application/json" id="tune">{
    "events": [
        [0, "key", "D"],
        [0, "meter", 4, 1],
        [0, "note", "D4", 0.1, 1],
        [1, "note", "F#4", 0.1, 1],
        [2, "note", "A4", 0.1, 1]
    ]
}</script>
<scribe-music src="#tune"></scribe-music>

Attributes and properties

attribute property type description
src .src URL URL of a JSON file or hashref of a script containing sequence data
  .data object The sequence data object
clef .clef string "treble", "bass", "piano", "alto", "drum" or "percussion"
key .key string The name of a major key, accepts "Ab" or "A♭" and "F#" or "F♯"
meter .meter string A meter expressed as a standard time signature, such as "4/4" or "6/8"
transpose .transpose number Transpose notation, but not the underlying data, by a given number of semitones
layout   string When set to "regular", fits an even number of bars per line
shuffle   boolean Boolean attribute, displays swung 16ths as straight 16ths
swing   boolean Boolean attribute, displays swung 8ths as straight 8ths

Sequences

Scribe consumes sequence data. A sequence is an object with an events property, an array of events. An event has the form [beat, type, ...data]. In Scribe, 1 beat is a quarter note. A sequence may also have a sequences property, an array of 'child' sequences. As an example, here are the first four bars of Herbie Hancock's Dolphin Dance as sequence data:

{
    "name": "Dolphin Dance",
    "events": [
        [0, "key", "Eb"],
        [0, "meter", 4, 1],
        [0, "sequence", 1, 0, 16]
    ],
    "sequences": [{
        "id": 1,
        "name": "Intro",
        "events": [
            [0,    "chord", 3, "∆", 4],
            [2,    "note",  67, 0.1, 0.5],
            [2.5,  "note",  68, 0.1, 0.5],
            [3,    "note",  70, 0.1, 0.5],
            [3.5,  "note",  65, 0.1, 3.5],
            [4,    "chord", 10, "-", 4],
            [8,    "chord", 3, "∆", 4],
            [10,   "note",  67, 0.1, 0.5],
            [10.5, "note",  68, 0.1, 0.5],
            [11,   "note",  70, 0.1, 0.5],
            [11.5, "note",  65, 0.1, 3.5],
            [12,   "chord", 2, "ø", 2],
            [14,   "chord", 7, "7alt", 2]
        ]
    }]
}

What's going on here? The main events array declares the key and the meter at beat 0, then cues the "Intro" sequence to 'play' for 16 beats. The intro sequence contains the melody and chords. The result renders as:

Events

Scribe understands the following event types:

beat type data
beat "chord" root | number extension duration
beat "key" name | number
beat "meter" beats divisor
beat "note" name | number dynamic duration
beat "sequence" id target duration transforms
beat "text" string duration

Unrecognised types are ignored.

Transforms

Sequence events may carry transforms for the sequences they cue:

[0, "sequence", 1, 0, 16, "transpose", -3, "rate", 2]

This renders as:

Notice that all 16 beats are still rendered – the duration of the event itself is not transformed – but the rate of the melody is transposed down a minor third and is twice as fast. Transforms are applied to sequences in the order they are declared. Scribe supports the transforms:

transform data
"displace" float (beats)
"gain" float (gain)
"rate" float (playback rate)
"transpose" integer (semitones)

Some examples of sequence JSON can be found in the repository's data folder.

SMuFL fonts

Scribe supports SMuFL fonts, W3C-standard fonts for rendering musical symbols. By default Scribe uses Jazz font, as seen in the examples on this page. It comes tested with a number of other openly licensed SMuFL fonts. To change the look of your music include one of these stylesheets:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/stephband/scribe@0.4/build/fonts/petaluma.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/stephband/scribe@0.4/build/fonts/bravura.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/stephband/scribe@0.4/build/fonts/broadway.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/stephband/scribe@0.4/build/fonts/ash.css" />

And set the new font-family:

Petaluma

font-family: Petaluma, PetalumaText;

Bravura

font-family: Bravura, BravuraText;

Broadway

font-family: Broadway, BroadwayText;

Ash

font-family: Ash, AshText;

Status

Scribe 0.4 is an evaluation release. It is capable of rendering a decent lead sheet, and there are some example lead sheets at the-dots.app. It does have some rough edges, and I am looking for feedback. Leave an issue on GitHub github.com/stephband/scribe/ or bleat me on BlueSky bsky.app/profile/stephen.band.

If you're curious about how the CSS works, there's a blog post outlining the approach at cruncher.ch/blog/printing-music-with-css-grid/.