Lyric highlighter
by rhelminen
HTML
<div class="lyrics">
<p class="lyric-line">Lyric line 1</p>
<p class="lyric-line">Longer lyric line with a lot more text</p>
<p class="lyric-line">OK!</p>
<p class="lyric-line">Baby, baby, yeah</p>
<p class="lyric-line">These are some pretty great lyrics, don't you think?</p>
</div>
SCSS
body {
background-color: #2d2d2d;
}
.lyrics {
margin: auto;
text-align: center;
display: flex;
place-items: center;
flex-direction: column;
}
.lyric-line {
--lyric-progress: 0%;
/* background-clip: text with a transparent text shows the background "under" the text instead of the text itself */
background-clip: text;
color: transparent;
/*
This is the color for the line.
Setting the endpoint of green to the starting point of white gives you a gradient with a hard break
*/
background-image: linear-gradient(90deg, mediumseagreen 0 var(--lyric-progress), white var(--lyric-progress) 100%)
}
JavaScript
document.addEventListener('DOMContentLoaded', async () => {
const lyricLines = document.querySelectorAll('.lyric-line')
// Loop through lyric lines and wait for the previous one to finish before going to the next one
for (let line of lyricLines) {
await colorLine(line, 1000)
}
// Color a single line (msTarget is the target length in milliseconds, adjust according to each line of the lyrics)
function colorLine(line, msTarget) {
let lineProgressPercentage = 0
// Return a Promise that, when resolved, will trigger the process for the next line
return new Promise(resolve => {
const colorizer = setInterval(() => {
// Modify the CSS variable to set the percentage value for the colored portion of the lyric
line.style.setProperty('--lyric-progress', `${lineProgressPercentage}%`)
lineProgressPercentage++
// When progress > 100%, resolve the Promise and clear the interval
if (lineProgressPercentage > 100) {
resolve(line)
clearInterval(colorizer)
}
}, msTarget / 100)
})
}
})