Responsive chords above lyrics

Viewed 382

I would like to use HTML and CSS (and if really necessary, some JS) to find a responsive way to put chords above lyrics. I already checked this post: Styling text to make it appear above the line (for chords above the lyrics) Here is what I have so far:

        body {
          padding:20px;
          font-size: 30px;
        }
        .chord{
            position    : absolute;
            top         : -50px;
            width       : 0;
            font-style  : italic;
            font-weight : bold;
            font-size: 50px;
        }

        .chord-lyrics{
            position: relative;
            display: inline-block;
            margin-top: 50px;
        }
<div class="line">
    <div class="chord-lyrics"><span class="chord">C</span> Imagine</div> there's 
    <div class="chord-lyrics"><span class="chord">Cmaj7</span>no</div>
    <div class="chord-lyrics"><span class="chord">F</span>heaven</div>
</div>

The goals:

  1. always keep the chord above the right lyrics
  2. if screen is smaller than the line, each word must overflow on the next line
  3. if the chords are larger than the text below it should create space between the lyrics EDIT:
  4. a chord can also be in the middle of a word

For now, everything works fine for 1. and 2. but not for 3. and this last one is also really important!

Thanks

5 Answers

Another possibility is to use Flexbox:

body {
  padding: 20px;
  font-size: 30px;
}

.container {
  max-width: 450px;
}

.line {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
}

.chord-letter {
  display: flex;
  flex-direction: column;
  padding: 0 5px;
  align-items: center; /* center chord */
}

.chord {
  font-style: italic;
  font-weight: bold;
  font-size: 25px;
}
<div class="container">
  <div class="line">
    <div class="chord-letter"><span class="chord">C</span> Imagine</div> there's
    <div class="chord-letter"><span class="chord">Cmaj7</span>no</div>
    <div class="chord-letter"><span class="chord">F</span>heaven</div>
  </div>
</div>

This code is fully responsive. Each chord-text-combo will be moved to the next line if there's not enough space.

Here is a Fiddle for you to play with.

Using position: absolute removes the elements from the flow of the page and prevents them from having an effect on the other elements.

If you change this to position: relative you can get something close to what you're looking for.

Just as a footnote, using px measurements isn't responsive. You should look to use ems, rems or even vw/vh!

        body {
          padding:20px;
          font-size: 30px;
        }
        .chord{
            position    : relative;
            top         : -50px;
            left        : 50px;
            width       : 0;
            font-style  : italic;
            font-weight : bold;
            font-size: 50px;
        }

        .chord-lyrics{
            position: relative;
            display: inline-block;
            margin-top: 50px;
        }
<div class="line">
    <div class="chord-lyrics"><span class="chord">C</span> Imagine</div> there's 
    <div class="chord-lyrics"><span class="chord">Cmaj7</span>no</div>
    <div class="chord-lyrics"><span class="chord">F</span>heaven</div>
</div>

I'd rather do smthg like that :

div.part {
    float  : left;
    margin : .3em;
    
}
div.chord {
    font-weight : bolder;
    font-style  : italic;
}
div.lyric {
    text-align  : center;
}

            
  <div class="part">
      <div class="chord">C</div>
      <div class="lyric">Imagine</div>
  </div>
  <div class="part">
      <div class="chord">&nbsp;</div>
      <div class="lyric">there's</div>
  </div>
  <div class="part">
      <div class="chord">Cmaj7</div>
      <div class="lyric">no</div>
  </div>
  <div class="part">
      <div class="chord">F</div>
      <div class="lyric">heaven</div>
  </div>

Alternatively, "flexbox" can be used.

body {
  padding: 20px;
  font-size: 30px;
}

.line {
  display: flex;
  align-items: flex-end;
  justify-content: start;
  flex-wrap: wrap;
}

.chord {
  font-style: italic;
  font-weight: bold;
  font-size: 50px;
}

.chord-lyrics {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: end;
}

.space {
  margin-right: .3em;
  margin-top: .3em;
  margin-bottom: .3em;
}
<div class="line">
  <div class="chord-lyrics space"><span class="chord">C</span> Imagine</div>
  <span class="space">there's</span>
  <div class="chord-lyrics space"><span class="chord">Cmaj7</span>no</div>
  <div class="chord-lyrics space"><span class="chord">F</span>heaven</div>
  <div class="chord-lyrics space"><span class="chord">C</span> Imagine</div>
  <span class="space">there's</span>
  <div class="chord-lyrics space"><span class="chord">Cmaj7</span>no</div>
  <div class="chord-lyrics space"><span class="chord">F</span>heaven</div>
  <div class="chord-lyrics space"><span class="chord">C</span> Imagine</div>
  <span class="space">there's</span>
  <div class="chord-lyrics space"><span class="chord">Cmaj7</span>no</div>
  <div class="chord-lyrics space"><span class="chord">F</span>heaven</div>
  <div class="chord-lyrics space"><span class="chord">F</span>heaven</div>
</div>


For your second question:

In overflows, the word and the chord behave as a whole, and the chord and word are always centered.

body {
  padding: 20px;
  font-size: 30px;
}

.line {
  display: flex;
  align-items: flex-end;
  justify-content: start;
  flex-wrap: wrap;
}

.chord {
  font-style: italic;
  font-weight: bold;
  font-size: 50px;
}

.chord-lyrics {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: end;
}

.space {
  margin-right: .3em;
  margin-top: .3em;
  margin-bottom: .3em;
}
<div class="line">
  <div class="chord-lyrics space"><span class="chord">C</span> Imagine</div>
  <span class="space">there's</span>
  <div class="chord-lyrics space"><span class="chord">Cmaj7</span>no</div>
  <div class="chord-lyrics space"><span class="chord">F</span>heaven</div>
  <div class="chord-lyrics space"><span class="chord">C</span> Imagine</div>
  <span class="space">there's</span>
  <div class="chord-lyrics space"><span class="chord">Cmaj7</span>no</div>
  <div class="chord-lyrics space"><span class="chord">F</span>heaven</div>
  <div class="chord-lyrics space"><span class="chord">C</span> Imagine</div>
  <span class="space">there's</span>
  <div class="chord-lyrics space"><span class="chord">Cmaj7</span>no</div>
  <div class="chord-lyrics space"><span class="chord">F</span>heaven</div>
  <div class="chord-lyrics space"><span class="chord">F</span>heaven</div>
</div>

Thanks to everyone, here is what I was able to do:

body {
    padding: 20px;
    font-size: 30px;
}

.line {
    display: flex;
    align-items: flex-end;
    flex-wrap: wrap;
}

.chord-letter {
    display: flex;
    flex-direction: column;
    align-items: left;
}

.no-space {
    margin-right: 0;
    border: solid 1px red;
}

.space {
    margin-right: 0.33em;
    border: solid 1px green;
}

.chord {
    color: gray;
    font-style: italic;
    font-weight: bold;
    font-size: 1.2em;
    border: solid 1px blue;
}

.no-space .chord {
    margin-right: 0.33em;
}

.word {
    display: flex;
    flex-direction: row;
    align-items: flex-end;
}
<div class="line">
   <div class="word">
      <span class="no-space">Ima</span>
      <div class="chord-letter space"><span class="chord">C</span>gine</div>
   </div>
   <span class="space">there's</span>
   <div class="chord-letter space"><span class="chord">Cmaj7</span>no</div>
   <div class="chord-letter space"><span class="chord">F</span>heaven</div>
   <div class="word">
      <span class="no-space">Ima</span>
      <div class="chord-letter space"><span class="chord">C</span>gine</div>
   </div>
</div>

It is:

  1. Fully responsive
  2. Allow chords inside a word
  3. Avoid breaking the words on wrapping
Related