文字はなくてもfont-sizeプロパティの設定が役立つことがありますよ

文字がない要素にfont-sizeプロパティを設定するって意味がわからん。 そう考えがちですが、そんなことはないのです。ふとした思い付きがあったのでご披露させていただきます。

課題は次のようなUIをGutenbergのブロックで制作するにあたってです。

フォームでユーザーに入力作業をしてもらっているとき、その進捗がどうなっているのかを表示するプログレスバーです。Bの数字とCのバーはAの文字要素に付加された擬似要素です。Bがbefore要素でCがafter要素です。B要素内には文字があるのでcssでfont-sizeを設定しました。コード全体としては次のようになります。

&::before {
  content: counter(step);
  counter-increment: step;
  width: 1.5em;
  height: 1.5em;
  line-height: 1.3em;
  text-align: center;
  display: block;
  font-size: ${font_style_num.fontSize};
  font-family: ${font_style_num.fontFamily};
  font-weight: ${font_style_num.fontWeight};
  font-style: ${fontStyle_num};
  color: ${textColor_num};
  background: white;
  border: ${textColor_num} solid 1px;
  border-radius: 50%;
  margin: 0 auto;
}

${font_style_num.fontSize}のようにテンプレートリテラルで動的にプロパティ値を設定できるのはCSS in JSの一つである「styled-components」を使っているからです(styled-componentsについては別のブログで解説します。)。 このようにするとB要素の大きさは動的に変化します。 ここで問題が生じます。B要素の大きさが変化すると、C要素の縦位置を動かす必要が出てきます(C要素はB要素の中心の高さにないと不細工です。)。 C要素は次のようなコードで設定されています。

&::after {
  content: '';
  width: 100%;
  height: 2px;
  position: absolute;
  left: -50%;
  top: 0.75em;
  background-image: linear-gradient(to right, ${textColor_num} 50%, ${bgColor_num} 50%);
  background-position: 0 0;
  background-size: 200% auto;
  transition: all 1s;
  z-index: -1;
  /*put it behind the numbers*/
}

進捗の変化に応じてアニメーションさせるためにtransitionなどの設定がありますが、それは本題からそれるので無視してください。問題はtop: 0.75em;のところです。emは親要素のフォントサイズを1としたときの相対値で設定する単位です。したがって、親要素であるA要素のフォントサイズが20pxだとすれば、0.75emは15pxになるということですね。 C要素の縦位置はこれで設定されています。しかし、A要素のフォントサイズはC要素の縦位置とは関係ないんです。関係あるのはB要素の大きさです。この変化をC要素に反映させるのはちょっと複雑です。

どうしたものかと悩んでいたのですが、ふと目が行ったのはA要素のCSSにある

width: 1.5em;
height: 1.5em;
line-height: 1.3em;

の部分です。これはB要素を〇で囲むためにフォントに外枠を設定している部分ですが、この数値はB要素のフォントサイズの変化に応じて変化します。なぜかというと、この単位emを決定する親要素はA要素のフォントサイズではなく、B要素のフォントサイズだからです。これはB要素のCSS設定にfont-size: ${font_style_num.fontSize};があることの効果です。 だったら、C要素にも同じように設定してやればいいんじゃないのか。要素に文字がなくてもfont-sizeプロパティは設定できますよね。 ということで、こんなコードを書きました。

&::after {
  content: '';
  width: 100%;
  height: 2px;
  position: absolute;
  left: -50%;
  font-size: ${font_style_num.fontSize};//これが入った
  top: 0.75em;
  background-image: linear-gradient(to right, ${textColor_num} 50%, ${bgColor_num} 50%);
  background-position: 0 0;
  background-size: 200% auto;
  transition: all 1s;
  z-index: -1;
  /*put it behind the numbers*/
}

ばっちりB要素の真ん中にバーが設定されるようになりました。 A要素からフォントサイズを引っ張ってきて、その単位がpxか emか remかで条件分岐させて計算するしかないかなと思ってうんざりしていたのですが、こうすれば何の苦労もなく設定できました。

これってCSS in JSを使う以外の場面でも応用が効くと思いますよ。参考になればうれしいです。