Ancho de los símbolos musicales Unicode frente a la fuente de ancho fijo

Según mi experiencia, los símbolos Unicode musicales para plano (♭) y sostenido (♯) no tienen exactamente el mismo ancho que la fuente de ancho fijo que estoy usando, por lo que la alineación de los caracteres en columnas se vuelve ligeramente torcida. Estoy usando esto para representar acordes de guitarra, y la alineación es una verdadera molestia.

¿Hay alguna manera de dibujar cuerdas y trastes (actualmente usando ╫, ─, ╢) junto con símbolos musicales (actualmente usando ♭, ♯, etc.) y números arábigos (1, 3, 5, 6, 7, 9, 11, 13) y retiene el espaciado de ancho completamente fijo, de modo que las columnas que abarcan varias filas se alineen correctamente? (Actualmente estoy asignando tres caracteres entre cada "traste" (╫) para poder acentuar o aplanar un undécimo o un decimotercero; los números de un solo dígito reciben un carácter de relleno de cadena adicional, ─).

Aquí hay un JSfiddle como caso de prueba. El código vinculado da como resultado esta vista:

ingrese la descripción de la imagen aquí

Bueno, el ancho de los glifos es parte de la fuente y no hay mucho que puedas hacer al respecto. Podría modificarlo con kerning (o espaciado de letras en CSS), pero necesitaría un valor diferente para cada glifo, por lo que no es exactamente ideal. ¿Está seguro de que los glifos que está usando son en realidad parte de la fuente (si no lo son, entonces su navegador debería usar una fuente alternativa, que puede ser la razón por la cual los anchos son diferentes)?
¿Podría ponerlo en una tabla con anchos de columna fijos?
Esto se está volviendo cada vez más una pregunta para StackOverflow, pero de todos modos ... Además de otras respuestas que sugieren el uso de tablas y/o intervalos, es posible que desee probar lettering.js ( letteringjs.com ). Esto pondrá un lapso alrededor de todos los caracteres. Con CSS, puede forzar que estos tramos tengan un cierto ancho. Algo como:display: inline-block; width: 12px.
Eso no es un tipo de letra de ancho fijo

Respuestas (4)

Siguiendo la idea de Cai de usar una estructura tabular para representar esto, se me ocurrió que el contenido de la tabla podría simplificarse enormemente al relegar los aspectos puramente visuales (es decir, la representación gráfica de los trastes mismos) a las propiedades de la tabla: bordes, espaciado, etc. (Creo que esto es esencialmente lo que implicaba el comentario de Chris a la pregunta).

Eso significaría que podría mantener el contenido real (las notas que desea mostrar) como el único contenido real de la tabla en el código, lo que hace que el código sea mucho más legible y no esté plagado de caracteres Unicode que distraen.

 

HTML: la tabla

La tabla en sí es bastante simple: simplemente cree (cadenas + 1) filas cada una con (trastes + 1) celdas. Coloque las notas individuales en intervalos dentro de su respectiva celda de la tabla y agregue un intervalo en la última celda de cada fila con la letra de la cadena correspondiente. Deje todas las celdas de la última fila vacías.

Así de sencilla acaba siendo la tabla:

<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: el estilo

En su CSS, asigne a la tabla un diseño fijo para que las celdas siempre tengan el ancho exacto que defina, independientemente de su contenido. Haz que los bordes horizontales sean líneas simples y los bordes verticales, líneas dobles. Quite los bordes superior, derecho e inferior de la última celda de cada fila. Haz que la primera y la última fila sean algo así como una quinta parte de la altura de las otras filas. Y luego posicione absolutamente los tramos para moverlos hacia abajo lo suficiente como para que se superpongan al borde inferior de la celda, haciendo que parezca que están realmente en la línea, en lugar de en la celda. Dale a los tramos un fondo sólido para eliminar el borde detrás de él.

En definitiva, algo como esto:

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;
}

 

El resultado

Aquí hay un JSFiddle que muestra cómo se ve eso (por supuesto, puedes jugar con el CSS en general para que se vea exactamente como lo quieres; no sé nada sobre guitarras, así que no tengo idea si mi ancho de traste- las proporciones de altura están completamente fuera de control aquí, etc.):

Resultado final

He estado implementando esto, aunque lentamente en un documento grande. Pero verdaderamente esta es la solución más elegante. Gracias por tu contribución.

Podría usar una tabla con una celda para cada glifo.

Entonces, así es como se representa con su marcado actual:

ingrese la descripción de la imagen aquí

Así es como se ve con cada glifo en su propia celda:

ingrese la descripción de la imagen aquí

El marcado para eso es:

<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>
Si coloca los contenidos reales (♯9, ♭7, etc.) en intervalos, incluso podría jugar con los bordes de las celdas y el espaciado y la ubicación de los intervalos arriba/abajo de la celda en la que se encuentran para que se superpongan al borde. De esa manera, podría obtener el mismo efecto sin tener que tener &#x2500;en cada celda, y sin necesitar una celda separada para el ♭/♯ y el siguiente número. También necesitaría (número de trastes + 1) celdas por fila para mostrarlo, lo que haría que el código fuera mucho más legible.

Se reduce a: necesita (para encontrar) una fuente monoespaciada que contenga símbolos musicales y cárguela como una fuente web en su documento.

Si tal fuente no existe (o no quiere pagar por ella)...

...hacer uno usted mismo:

  • Encuentre una fuente monoespaciada agradable, gratuita y abierta (¿puedo recomendar Hack ?)
  • Agregue los símbolos musicales que faltan (pruebe con wikimedia ) y vuelva a exportarlo
  • Cargue su nueva fuente como fuente web en su sitio web.

Existen varios programas de edición de fuentes, entre los que destaca Fontforge (gratuito, de código abierto,… pero…). También puede usar icomoon.io (una aplicación web, gratuita) y cargar una fuente SVG en él. (puede descargar una versión SVG de Hack desde su cuenta de GitHub)

ACTUALIZACIÓN: La fuente que necesita es inconsolata . Disponible en las fuentes de Google, tan fácil de usar como fuente web.

Si bien hay algunas buenas respuestas que usan CSS y mucho HTML , la solución más fácil es usar una fuente que realmente tenga los símbolos musicales, suponiendo que pueda incluir la fuente. La mayoría de las fuentes monoespaciadas que he probado no tienen símbolos musicales. Para compensarlo, su sistema operativo sustituye un carácter de otra fuente (no estoy seguro de si Mac maneja esto mejor, pero en Windows no tiene exactamente el ancho correcto).

La única fuente que he encontrado en mi sistema que tiene símbolos musicales (y los símbolos gráficos que está usando) es DejaVu Sans Mono .

    <style>
        pre { font-family: "DejaVu Sans Mono"; }
    </style>
    <pre>
╫───╫───╫───╢
╫───╫─1─╫───╢
╫───╫───╫─3─╢
╫───╫♭7─╫───╢
╫♯9─╫───╫───╢
    </pre>

El descubrimiento genial es que stackexchange lo está procesando correctamente (al menos en mi computadora). Si inspecciona el html que se muestra arriba usando el inspector de su navegador, verá que el sitio está usando DejaVu Sans Mono. Su pila de fuentes completa es:

pre { font-family: Consolas,Menlo,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace,sans-serif; }

Luego de una inspección adicional: si inspecciona el elemento de código anterior y aumenta el tamaño de fuente, notará que la línea con el ♭7 no se alinea. Consolas se está utilizando para todo menos para el piso. Elimine las fuentes antes de DejaVu y todo se alineará nuevamente.

Ninguna de las fuentes de Google (que son fáciles de incluir en una página web) tiene los caracteres. Cousine parecía que lo hizo usando la página de prueba, pero cuando lo probé no funcionó. Mi prueba de Inconsolata con el conjunto de caracteres latin-ext tampoco funcionó (a la mayoría de esas fuentes les falta el símbolo plano ♭).

¡Buen descubrimiento! De hecho, es muy elegante: el único inconveniente es que lo limita a una fuente monoespaciada que contiene los símbolos nítidos y planos y tiene una altura de línea que funciona sin espacios entre líneas, mientras que la versión HTML funciona con cualquier fuente, monoespaciada o no.
Sí, ciertamente no es bueno estar limitado a una fuente para esto, especialmente si se trata de trabajos de impresión. Los anchos coinciden con Courier New, por lo que puede usar eso adelante en la pila si le gusta esa fuente, pero las alturas de línea no coinciden, por lo que también debe establecer la altura de línea en CSS para ese combo.