3

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

  • Well, the width of the glyphs is a part of the font and there isn't much you can do about it otherwise. You could fudge it with kerning (or letter-spacing in CSS) but you'd need a different value for each glyph so that isn't exactly ideal. Are you sure the glyphs you're using are actually a part of the font (if they aren't then your browser should just use a fallback font, which may be why the widths are different)? – Cai Feb 16 '17 at 13:44
  • Could you put it in a table with fixed column widths? – Westside Feb 16 '17 at 13:49
  • This is getting more and more a question for StackOverflow, but anyway... In addition to other answers suggesting using tables and/or span, you might want to try lettering.js (letteringjs.com). This will put a span around all characters. With CSS, you can force these spans to have a certain width. Something like: display: inline-block; width: 12px. – Ideogram Feb 20 '17 at 15:36
  • That is not a fixed-width typeface – Yorik Feb 24 '17 at 19:14
2

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

  • 1
    I have been implementing this, albeit slowly over a large document. But truly this is the most elegant solution. Thank you for your contribution. – Kirk A Mar 17 '17 at 11:55
3

It boils down to: you need (to find) a monospaced font that contains musical symbols and load this as a webfont into your document.

If such a font does not exist (or you do not want to pay for it)...

...make one yourself:

  • Find a nice, free, open monospace font (may I recommend Hack ? )
  • Add the musical symbols that lack (try wikimedia) and export it again
  • Load your new font as a webfont into your website.

There exist several font-editing programs out there, among which Fontforge (free, open source,… but…). You can also use icomoon.io (a web-app, free) and load a SVG-font into it. (you can download a SVG version of Hack from their GitHub account)

UPDATE: The font you need is inconsolata. Available from Google fonts, so easy to use as a webfont.

2

You could just use a table with a cell for each glyph.

So, this is how it renders with your current markup:

enter image description here

This is how it looks with each glyph in its own cell:

enter image description here

The markup for that is:

<table align="left" border="0" cellpadding="0">
<caption align="top"><b><i>Example: 7<sup>&#9839;9</sup></i></b></caption>
    <tbody>
        <tr>
            <td>&#9579;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#9579;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#9579;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#9570;</td>
            <td>E</td>
        </tr>
        <tr>
            <td>&#9579;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#9579;</td>
            <td>&#x2500;</td>
            <td><b>1</b></td>
            <td>&#x2500;</td>
            <td>&#9579;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#9570;</td>
            <td>A</td>
        </tr>
        <tr>
            <td>&#9579;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#9579;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#9579;</td>
            <td>&#x2500;</td>
            <td><b>3</b></td>
            <td>&#x2500;</td>
            <td>&#9570;</td>
            <td>D</td>
        </tr>
        <tr>
            <td>&#9579;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#9579;</td>
            <td><b>&#9837;</b></td>
            <td><b>7</b></td>
            <td>&#x2500;</td>
            <td>&#9579;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#9570;</td>
            <td>G</td>
        </tr>
        <tr>
            <td>&#9579;</td>
            <td><b>&#9839;</b></td>
            <td><b>9</b></td>
            <td>&#x2500;</td>
            <td>&#9579;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#9579;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#9570;</td>
            <td>B</td>
        </tr>
        <tr>
            <td>&#9579;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#9579;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#9579;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#x2500;</td>
            <td>&#9570;</td>
            <td>e</td>
        </tr>
    </tbody>
</table>
  • If you put the actual contents ( ♯9, ♭7, etc.) in spans, you could even fiddle around with cell borders and spacing and positioning the spans above/below the cell they’re in so they overlap the border. That way you could get the same effect without having to have &#x2500; in every cell, and without needing a separate cell for the ♭/♯ and the following number. You’d only need (number of frets + 1) cells per row, too, to display it, which would make the code a lot more readable. – Janus Bahs Jacquet Feb 19 '17 at 9:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.