長体フォントを使ったデザインで使えるSass/PugのMixinをつくってみた

長体フォント使うデザインで、「長体フォントをデバイスフォントで使いたい!」という時に使える小技みたいなものです。

長体フォントにするには

そもそもブラウザでは長体フォントの指定はありません。長体のウェブフォントを導入するか、自前で実装する必要が生じます。
よくある実装方法としては、transform: scaleX() を使用するものがあります。


.text-wrap
  .text 吾輩は猫である

.text {
  transform: scaleX(0.7);
}

ただし、親要素を拡縮してしまうと、ボックスサイズが見た目ではなく元のサイズでレンダリングされるため、全体的にテキストが中央に寄ってしまいます。

意図したレイアウトにしやすい長体フォント用mixin(pug/SASS)

今回は見た目のボックスサイズに限りなく近いレイアウトになるようにするために、以下のようにmixinを作成しました。


mixin condensed(str)
  each i in str
    span=i

@mixin condensed($font_size: 16px, $scale: 0.7)
  span {
    display: block;
    font-size: $font_size;
    width: $font_size * $scale;
    transform: scaleX($scale);
    transform-origin: left center;
  }
}

使い方

Pug/Sassでは、以下のようにincludeすれば良いです。


.text
  +condensed("吾輩は猫である。")
.text
  +condensed("名前はまだ無い。")

.text {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin: 0 auto;
  max-width: 400px;
  font-family: YuMincho, "游明朝体", serif;
  @include condensed(28px, 0.7);
}

実際のコードデモはCodePenの方にも書いています。(CodePenではPug/SASS記法で書いています。)

何をしているのか

最初の方に書いたとおり、transform で変化させた要素は、幅や高さを再計算するわけではないので、transformで変化させる前の幅・高さ分の余白が残ってしまいます。

(以下CSSでは背景などは付けてないです)


.text-wrap
  .text 吾輩は猫である

.text-wrap {}
.text {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin: 0 auto;
  width: 100%;
  font-size: 40px;
  text-align: center;
  transform: scaleX(0.7);
  transform-origin: left center;
}

そこで、一文字一文字をspanで囲い、各spanに対してtransform: scale()を適用します。これで親要素のボックスサイズをそのままに、文字は長体にすることができます。


mixin condensed(str)
  each i in str
    span=i

.text-wrap
  .text
    =condensed("吾輩は猫である")

.text-wrap {}
.text {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  font-size: 40px;
  text-align: center;
  span {
    transform: scaleX(0.7);
  }
}

しかし、これだけではspanで囲った一文字も同じように見た目の幅が期待した幅と一致しません。

ここで、各span要素に、transform後の幅を先に指定しておきます。

width: $font_size * $scale;

これで、transform後でも見た目の幅と同じ幅だけ余白が調整されます。


.text-wrap
  .text
    =condensed("吾輩は猫である")

$font-size: 40px;
$scale: 0.7;
.text-wrap {}
.text {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  font-size: $font-size;
  text-align: center;
  span {
    display: block;
    width: $font-size * $scale;
    transform: scaleX($scale);
  }
}

ただ、ここまでで終わりではありません。

元の文字幅はwidthよりも大きいため、文字がやや右にずれた状態でscaleX()が適用されてしまい、やや右に寄ってしまいます…。

これはtext-align: centerでは解決しません。
元々のテキストは、ボックスサイズよりも大きいため、強制的に左づめされてしまうためです。

これを意図した位置に調整するために、transofrm-origin: left center;を指定します。これでtransformの起点が要素の左中央になります。

transform-origin: left center;

これで、見た目のサイズも位置も完全に一致しました。

最終的なコードは以下になります。


mixin condensed(str)
  each i in str
    span=i

.text-wrap
  .text
    =condensed("吾輩は猫である")

$font-size: 40px;
$scale: 0.7;
.text-wrap {}
.text {
  display: flex;
  justify-content: center;
  align-items: center;
  span {
    display: block;
    font-size: $font_size;
    width: $font_size * $scale;
    transform: scaleX($scale);
    transform-origin: left center;
  }
}

これをmixin化したものが、先述したものとなります。

ちなみに、.textjustify-content/aligin-itemsの値を変更すれば、それぞれtext-align/vertical-alignと同じような振る舞いをしてくれます。

対応ブラウザ

flexbox/transformを対応しているブラウザであれば問題なく動作するはずです。

Can I Use…

注意点

結構いい感じに長体フォントを指定できるようになったのですが、以下のように少し注意する点が有りますので、使用する場合は念頭に置いてください。

  • タグの数が増える
  • Pug/Sassなどのテンプレートエンジン/メタ言語でないと実装が厳しい
  • letter-spacing は隣接セレクタなどで margin を指定する必要がある
  • ブラウザのフォント対応によってはずれる可能性がある

おわりに

長体フォントはデザインがスタイリッシュなサイトでよく見かけるので、今後のトレンド対策として覚えておくと役に立つかもしれないです。

  • BLOG
  • >
  • web
  • >
  • 長体フォントを使ったデザインで使えるSass/PugのMixinをつくってみた