htmlcssfontsfont-facetypography

In HTML, is there a way to prevent the ♭ character from shifting down?


I'm trying to write a simple HTML page to output music chords. I display randomly generated chords to practice chord changes (like using flashcards).

When I output a chord containing a "flat" symbol, the whole chord appears to jump down -- it increases the vertical height of the enclosing <div> and appears at the bottom. The Other chords (with a "sharp" or without) appear as expected.

JSFiddle to demonstrate: https://jsfiddle.net/blatwell9/qjfcLtdv/3/

Is there a way to prevent the shift down from happening?

Shift down example

The code to demonstrate the effect. Note the effect when the backgrounds of the <div> and the chord <span> are displayed:

      function showChord() {
          
          
          document.getElementById("chord").innerHTML = chordList[chordIndex];
          document.getElementById("chordWithLineHeight").innerHTML =          chordList[chordIndex];
          
          chordIndex++;
          if (chordIndex > chordList.length -1) chordIndex = 0;
          
          setTimeout(showChord, 1500);
        }
        
        let chordIndex = 0;
        let chordList = ["&sharp;","&flat;"];
        showChord();
    * {margin: 0; padding: 0;}
        body {font-family: sans-serif;}
        
        
      .chord-div {font-size: 3em; background: lightgreen; margin: .1em; }
        
      #chord {background: lightblue; 
            border: 1px blue solid;}
            
        #chordWithLineHeight {background: lightblue; 
            border: 1px blue solid; 
            line-height: 1}
      <h3> No line-height set </h3>
      <div class="chord-div">
        <span id="chord"></span>
      </div>
      
      <h3> With line-height set </h3>
      <div class="chord-div">
        <span id="chordWithLineHeight"></span>
      </div>


Solution

  • Update

    Sans-serif Typeface

    Op has pointed out that there's still a misalignment after my solution. So the original code presented by OP had float: left in which I proved to be one of the problems. In my solution I have font-family: "Opus" because it's used specifically for sheet music. So I assumed that was fixed, unfortunately, it turns out that font-family: sans-serif is buggy and there's a misalignment with ♭. In conclusion, do not use float unless you intend to wrap text around an <img> and don't use sans-serif, use "Opus", or "Helsinki XXL", or "Segoe UI" typeface. See Example A for the float issue and Example B for font issue.

    Float Issue

    Instead of wasting time explaining why not to use float see this post. The example has two <section>s:

    As you can see the floating <div>s are cock-eyed and the ♭ symbol has nothing to do with it. Just use inline elements, flexbox or grid layouts.

    Example A

    @import url('https://fonts.cdnfonts.com/css/opus');
    * {
      margin: 0;
      padding: 0;
    }
    
    :root {
      3ch/1.2 "Opus" "sans-serif";
    }
    
    mark {
      margin: 0.1rem;
      font-size: 3rem;
      background: lightgreen;
    }
    
    div {
      float: left;
    }
    <section>
      <mark>A&sharp;</mark>
      <mark>A&#119082;</mark>
      <mark>A&flat;</mark>
      <mark>A&#119083;</mark>
      <mark>A&natur;</mark>
    </section>
    
    <section>
      <div>
        <mark>A&sharp;</mark>
      </div>
      <div>
        <mark>A&#119082;</mark>
      </div>
      <div>
        <mark>A&flat;</mark>
      </div>
      <div>
        <mark>A&#119083;</mark>
      </div>
      <div>
        <mark>A&natur;</mark>
      </div>
    </section>

    Example B

    const chords = ["&flat;", "&sharp;", "A&flat;", "A&sharp;", "A&sharp;A&flat;", "A&natur;A&#119083;A&#119082;"];
    
    let count = cycle(chords.length);
    
    const showChords = (array, selector) => {
      const tags = document.querySelectorAll(selector);
      const i = count.next().value;
      if (i === 0) tags.forEach(t => t.innerHTML = "");
      tags.forEach(t => t.innerHTML += `<mark>${array[i]}</mark>`);
      setTimeout(() => showChords(array, selector), 1500);
    };
    
    function* cycle(N) {
      let i = 0;
      while (true) {
        ++i;
        i = i > (N - 1) ? 0 : i;
        yield i;
      }
    }
    
    showChords(chords, "p");
    :root {
      font: 2ch/normal "Segoe UI"
    }
    
    p {
      font-size: 3rem;
      background: lightgreen;
    }
    
    mark {
      padding: 0 .1em;
      outline: 1px blue solid;
      background: lightblue;
    }
    
    p:nth-of-type(2) {
      line-height: 1;
    }
    
    p:nth-of-type(3) {
      font-family: sans-serif;
    }
    
    p:nth-of-type(4) {
      line-height: 1;
      font-family: sans-serif;
    }
      
    <main>
      <h3>line-height: 1.2 (default) font-family: "Segoe UI"</h3>
      <p></p>
    
      <h3>line-height: 1; font-family: "Segoe UI"</h3>
      <p></p>
    
      <h3>line-height: 1.2; font-family: sans-serif</h3>
      <p></p>
      
      <h3>line-height: 1; font-family: sans-serif</h3>
      <p></p>
    </main>