Width of unicode musical symbols vis a vis fixed width font

In my experience, the musical Unicode symbols for flat (♭) and sharp (♯) are not exactly the same width as the fixed width font that I am using, consequently columnar character alignment becomes slightly crooked. I am using this to depict guitar chords, and the alignment is a real nuisance.

Is there some way that I can draw strings and frets (presently using ╫, ─, ╢) together with musical symbols (presently using ♭, ♯, etc.) and Arabic numerals (1, 3, 5, 6, 7, 9, 11, 13) and retain completely fixed width spacing, such that columns spanning multiple rows will align properly? (I am presently allocating three characters between each “fret” (╫) so that I can sharpen or flatten an eleventh or thirteenth; single digit numerals receive an extra string filler character, ─.)

Here’s a JSfiddle as a test case. The linked code results in this view:

enter image description here

Answer

Going with Cai’s idea of using a tabular structure to represent this, it occurred to me that the contents of the table could be vastly simplified by relegating the purely visual aspects (i.e., the graphical representation of the frets themselves) to table properties: borders, spacing, etc. (I think this is essentially what Chris’ comment to the question implied as well.)

That would mean you could keep the actual content (the notes you want to show) as the only real content of the table in the code, which makes the code vastly more readable and not riddled with distracting Unicode characters.

 

HTML: the table

The table itself is simple enough: just create (strings + 1) rows each with (frets + 1) cells. Put the individual notes in spans inside their respective table cell, and add a span in the last cell of each row with the letter for the corresponding string. Leave all cells in the last row empty.

This is how simple the table ends up being:

<table class="frets">
    <caption>Example: 7<sup>♯9</sup></caption>
    <tbody> 
        <tr>
          <td></td>
          <td></td>
          <td></td>
          <td><span>E</span></td>
        </tr>

        <tr>
          <td></td>
          <td><span>1</span></td>
          <td></td>
          <td><span>A</span></td>
        </tr>

        <tr>
          <td></td>
          <td></td>
          <td><span>3</span></td>
          <td><span>D</span></td>
        </tr>

        <tr>
          <td></td>
          <td><span>♭7</span></td>
          <td></td>
          <td><span>G</span></td>
        </tr>

        <tr>
          <td><span>♯9</span></td>
          <td></td>
          <td></td>
          <td><span>B</span></td>
        </tr>

        <tr>
          <td></td>
          <td></td>
          <td></td>
          <td><span>e</span></td>
        </tr>

        <tr>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
        </tr>
    </tbody>
</table>

 

CSS: the styling

In your CSS, give the table a fixed layout so that cells are always the exact width you define, regardless of their content. Make horizontal borders single lines and vertical borders double lines. Remove the top, right, and bottom borders from the last cell in each row. Make the first and last rows something like one fifth the height of the other rows. And then absolutely position the spans to move them downwards enough that they overlap the bottom border of the cell, making it look like they’re actually on the line, rather than in the cell. Give the spans a solid background to knock out the border behind it.

All in all something like this:

body {
    font-size: 30px;
}

caption {
    font-weight: bold;
    font-style: italic;
    padding: 0.3em 0;
}

table {
    table-layout: fixed;
    border: none;
    border-collapse: collapse;
}

tr:first-of-type td {
    height: 0.1em;
    border-top: none;
}

tr:last-of-type td {
    height: 0.1em;
    border-bottom: none;
}

td {
    border-color: black;
    border-width: 1px 5px;
    border-style: solid double;
    width: 3em;
    height: 1em;
    padding: 4px;
    text-align: center;
    position: relative;
}

    td:last-of-type {
        border-color: transparent transparent transparent black;
        width: 2em;
    }

    td:last-of-type span {
        background: none;
    }

td span {
    display: block;
    position: absolute;
    left: 50%;
    bottom: calc(-0.5em - 4px);
    transform: translateX(-50%);
    padding: 0 0.3em;
    background: #f3f5f6;
}

 

The result

Here is a JSFiddle showing how that ends up looking (of course, you can fiddle around with the CSS in general to get it to look exactly how you want it; I know nothing about guitars, so I have no idea if my fret width-to-height ratios are completely out of whack here, etc.):

Final result

Attribution
Source : Link , Question Author : Kirk A , Answer Author : Janus Bahs Jacquet

Leave a Comment