CSS 中的吉他和弦

2025-06-07

CSS 中的吉他和弦

在我之前的文章中,我研究了attr()CSS 中新的改进方法。我欣喜若狂(双关语)。这次,我将继续研究该attr()方法,展示如何制作易于阅读的组件——至少对于吉他手来说——就像这样:

<fret-board frets="4" strings="6" chord="C Major">
  <string-note string="6" mute></string-note>
  <string-note string="5" fret="3" finger="3"></string-note>
  <string-note string="4" fret="2" finger="2"></string-note>
  <string-note string="3" open></string-note>
  <string-note string="2" fret="1" finger="1"></string-note>
  <string-note string="1" open></string-note>
</fret-board>
Enter fullscreen mode Exit fullscreen mode

... 变成这样 —完全没有 JavaScript

显示 C 大调和弦的指板组件

让我们开始吧!

基本网格

首先,我们需要一个基本的网格。单元格和行数取决于我们在 HTML 中定义的frets和属性——因此,让我们获取它们并设置两个自定义属性:strings<number>

--_frets: attr(frets type(<number>), 4);
--_strings: attr(strings type(<number>), 6);
Enter fullscreen mode Exit fullscreen mode

在 CSS 中,我们将琴弦数量增加一倍,这样就可以将音符放在琴弦——在琴弦左侧一个网格单元的位置。我们还希望顶部和底部两行分别显示和弦名称以及打开/静音指示,因此我们的网格如下所示:

fret-board {
  grid-template-columns: repeat(calc(var(--_strings) * 2), 1fr);
  grid-template-rows:
    var(--fret-board-top-row-h, 12%)
    repeat(calc(var(--_frets)), 1fr)
    var(--fret-board-bottom-row-h, 15%);
}
Enter fullscreen mode Exit fullscreen mode

我们现在有:

基本网格

琴格和琴弦

音品和琴弦作为两个线性渐变添加到伪元素中:

fret-board {
  --fret-board-fret-c: light-dark(#000, #FFF);
  --fret-board-fret-w: clamp(0.0625rem, 0.03125rem + 0.5cqi, 0.5rem);
  --fret-board-string-c: light-dark(#0008, #FFF8);
  --fret-board-string-w: clamp(0.0625rem, 0.03125rem + 0.5cqi, 0.125rem);

  background-image:
    /* Vertical strings */
    linear-gradient(
      90deg, 
      var(--fret-board-string-c) var(--fret-board-string-w), 
      transparent 0 var(--fret-board-string-w)
    ),
    /* Horizontal frets */
    linear-gradient(
      180deg,  
      var(--fret-board-fret-c) var(--fret-board-fret-w), 
      transparent 0 var(--fret-board-fret-w)
    );

  background-position: 
    0 var(--fret-board-fret-w), 
    0 0;

  background-repeat: 
    repeat-x, 
    repeat-y;

  background-size:
    /* Width and height for strings */
    calc(100% / (var(--_strings) - 1) - (var(--fret-board-string-w) / var(--_strings))) 
      calc(100% - (2 * var(--fret-board-fret-w))),
    /* Width and height for frets */
    100% 
      calc(100% / var(--_frets) - (var(--fret-board-fret-w) / var(--_frets)));
}
Enter fullscreen mode Exit fullscreen mode

好的,这确实有点麻烦,但我们基本上从上到下为音品创建了水平线,并为贯穿整个琴弦创建了垂直线。

添加音品和琴弦

添加音符和手指

让我们添加一些注释 - 但首先,让我们抓住这些属性:

--barre: attr(barre type(<number>), 1);
--fret:  attr(fret type(<number>), 0);
--string:  attr(string type(<number>), 0);
Enter fullscreen mode Exit fullscreen mode

我们很快就会讲到--barre,但是现在,我们使用这个公式来放置注释:

string-note {
  grid-column: calc((var(--_strings) * 2) - (var(--string) * 2 - 1)) / span calc(var(--barre) * 2);  
  grid-row: calc(var(--fret) + 1);
}
Enter fullscreen mode Exit fullscreen mode

让我们来分析一下:

  1. 网格列定位:

    • (var(--_strings) * 2)- 从网格的最右侧开始
    • (var(--string) * 2 - 1)- 计算从右侧移动多远
    • 例如,有 6 个字符串:
      • 字符串 1(最高)位于位置12 - (1*2-1) = 11
      • 弦 6(最低)位于位置12 - (6*2-1) = 1
  2. 跨度计算:

    • span calc(var(--barre) * 2)- 对于常规笔记,跨越 2 列
    • 对于封闭和弦,跨越更多列,具体取决于覆盖的弦数
  3. 网格行公式:

    • calc(var(--fret) + 1)-+1标题行的帐户
    • 开放弦(品位 = 0)放在第 1 行,第一品位放在第 2 行,等等。

这让我们:

音符和手指

显示手指编号

为了获得良好的指法谱,我们需要显示每个音符应该用哪个手指弹奏。我们从fingerHTML 中的属性中获取它,并使用伪元素显示它:

string-note::after {
  color: var(--string-note-c, light-dark(#FFF, #222));
  content: attr(finger);
  font-size: var(--string-note-fs, 7cqi);
  font-weight: var(--string-note-fw, 500);
  text-box: cap alphabetic;
}
Enter fullscreen mode Exit fullscreen mode

注意: text-box: cap alphabetic是一项现代 CSS 功能,用于修剪由 产生的间距line-height。该light-dark()功能会自动调整文本颜色以适应亮色或暗色模式。

静音弦和开放弦

吉他和弦通常涉及未按下的琴弦,而是空弦演奏或静音(未演奏):

<string-note string="6" mute></string-note>    <!-- Muted string -->
<string-note string="3" open></string-note>    <!-- Open string -->
Enter fullscreen mode Exit fullscreen mode

对于字符串状态的视觉表示:

  • 对于静音弦,我们使用 Temani Atif 的十字形状border-image45° 旋转创建一个 X 符号
  • 对于开放的字符串,我们使用带有径向渐变的 CSS 蒙版来创建空心圆效果
string-note[mute] {
  border-image: conic-gradient(var(--fret-board-bg) 0 0) 50%/calc(50% - 0.25cqi);
  rotate: 45deg;
}
string-note[open] {
  border-radius: 50%;
  mask: radial-gradient(circle farthest-side at center, 
    transparent calc(100% - 1cqi), 
    #000 calc(100% - 1cqi + 1px));
}
Enter fullscreen mode Exit fullscreen mode

封闭和弦

“封闭和弦”是指用一根手指按住多根琴弦。让我们barre在 HTML 中添加以下属性:

<string-note string="6" fret="1" barre="6" finger="1"></string-note>
Enter fullscreen mode Exit fullscreen mode

我们已经介绍了上面的计算,但它的视觉效果如下:

封闭和弦

品格数

有时,和弦并非从第一品开始,我们需要指明品位编号。为此,我们使用有序列表,并在第一项上<ol>设置属性:value

<ol><li value="7"></li></ol>
Enter fullscreen mode Exit fullscreen mode

您可以在最终演示中检查样式,但它看起来像这样:

品格数

其他带有琴格和琴弦的乐器

现在,通过几个属性控制 CSS 的好处在于,我们可以轻松地将其应用于其他乐器。以下是一些示例:

尤克里里 — 4 弦:

尤克里里

班卓琴——5 弦:

班卓琴


演示

以下是演示。请注意,目前仅适用于 Chrome

我希望您像我写这篇文章一样喜欢它——现在,我要拿起吉他弹奏一些和弦。

文章来源:https://dev.to/madsstoumann/guitar-chords-in-css-3hk8
PREV
使用 CSS 重建 1883 年的日本烟花目录
NEXT
时钟和倒计时:CSS 和 JavaScript 中的计时