擬似要素のbeforeとafterを理解して、文字を装飾してみよう

擬似要素のbeforeとafterについて例を交えてちょっと書きます。 今回は、文字列の両脇に線を表示させるようなものを考えてみます。

文字列の両脇に線を入れる

f:id:utr066:20180107152520p:plain

<p class="hello-world">Hello World</p>
.hello-world {
  margin: 0 0 30px;
  letter-spacing: 1px;
  font-size: 2.2rem;
}
.hello-world::before,
.hello-world::after {
  content: '';
  display: inline-block;
  width: 140px;
  height: 2px;
  margin: 0 30px;
  background-color: #fff;
  vertical-align: middle;
}

beforeもafterも使っていますね。ちょっとこれがどういう風にできているかを見ていきましょう。

.hello-worldの方は単にmarginとフォントサイズ、文字幅を調整しているだけです。

このデザインにするポイントは、beforeとafterの使い方。

前提としてのbeforeとafter

beforeとafterはそのクラスの要素の前後にcssで指定したものを入れることができる。

つまり、こういったことをするとどうなるか。

.hello-world::before,
.hello-world::after {
  content: 'sss';
}

これはhello-worldクラスがついている要素の前後にsssという文字列をcontentというcssプロパティを使って入れています。

f:id:utr066:20180107153446p:plain

結果としてこんな表示になりますね。

じゃあ、両脇の線はこれでいいじゃん!ってなりますね。

.hello-world::before,
.hello-world::after {
  content: '----------------';
}

確かにこれでも線は表示されます。

f:id:utr066:20180107153710p:plain

ですが、美しくないですよね。線の幅も数値で指定していないので、どれぐらいの長さかもわかりません。

もっとスマートにするために色々なcssプロパティを使って整えていくんです。

cssの中身をもう一度見てみましょう。

.hello-world::before,
.hello-world::after {
  content: '';
  display: inline-block;
  width: 140px;
  height: 2px;
  margin: 0 30px;
  background-color: #fff;
  vertical-align: middle;
}

線を表示すると聞くと、borderとかを使っているのかなあと思ったりするかもしれませんが、使っていませんね。 ではそうやって、線を表示しているのでしょうか。

これはdisplay: inline-block;というものが関わってきます。

インライン要素とブロック要素

インラインブロック要素のことを書く前に、ちょっとブロック要素とインライン要素のことを。

htmlで何か要素を作った時には主にブロック要素とインライン要素に分けられます。

例えば、divタグで作ったものはブロック要素となります。

ブロック要素は画面幅いっぱいに広がり、高さや横幅を持つ要素ですね。

一方インライン要素は高さや横幅を持ちません。spanタグなんかがそうですね。あくまでspanタグで囲った文字だけが表示されます。

この要素には高さや横幅を指定することができないってわけです。 ですから例えば、こんな風に指定しても、高さは反映されません。

<span class="hello-world">Hello World</p>
.hello-world {
  margin: 0 0 30px;
  letter-spacing: 1px;
  font-size: 2.2rem;
  height: 300px;
}

ただ、インライン要素でも高さ等の指定をできるものもあります。気になれば見てみると。

インライン要素にwidthとheightを指定して、無視されるとき/されないとき - 以下斜め読んだ内容

インラインブロック要素

元のcssをみてみましょう。

display: inline-block;

これですね。 これってなんで指定しているのでしょう。 ちょっと考えてみましょう。そもそもこれを指定しないとdisplayの値は何になるでしょうか。

インライン要素になるんです。 beforeやafterはそうなのかな。

では、なぜインライン要素ではダメなのでしょうか。

これで試してみましょう。

.hello-world::before,
.hello-world::after {
  content: '';
  width: 140px;
  height: 2px;
  margin: 0 30px;
  background-color: #fff;
  vertical-align: middle;

初期値はinlineなので、何も指定しなくてもokなはず。 見てみると何も表示されないですね。 なんでですかね。インライン要素は高さや横幅を持たないからですね。

じゃあ高さも横幅も持つブロック要素にすればいいんじゃないでしょうか。

f:id:utr066:20180107160437p:plain

ブロック要素を指定すると上記のようになってしまいました。

これはbeforeとafterの参照する位置がblock要素では、上記のようになるためでしょうね。ブロック要素は横幅いっぱいまで広がりますから。

じゃあ高さも横幅も指定できるインラインの性質を持ったdisplayの値ってないの? って考えた時に出てくるのがinline-blockです。

これを指定するとこんな風に線が出てきます。

f:id:utr066:20180107152520p:plain

borderみたいなものを指定していないのになんで線が出るの

最初の疑問に戻ります。 なんでcssで線を入れるようなものがないのに、こんな風に表示されているのか。

ここで大事なのは以下のプロパティです。

  display: inline-block;
  content: '';
  width: 140px;
  height: 2px;
  background-color: #fff;
  vertical-align: middle;
  • インラインブロック要素にします。

  • 要素の中身は空とします。

  • その要素は横幅も高さも持つことができるので、widthheightを指定します。

  • 要素の色は白とします。

  • vertical-alignでその要素の出現位置を縦から見て真ん中にします。

cssで書いていることは上記のことです。 つまり、なんで線が表示されていたかっていうと、線っぽい要素を作っていたんですね。 線ではなく、あくまで線に見える形の要素を作っていたっていうだけです。heightを100とかにするとそれが線ではなく、ただの要素だということがわかります。

vertical-alignとは

vertical-alignだけ見慣れないかもしれないので、ちょっと書きます。

f:id:utr066:20180107163119p:plain

vertical-alignを使用しないで、さっきと同じように線のような要素を作ってafterで表示させます。 すると、「こんにちは」の後ろに線が出てきましたね。

これにvertical-alignを指定するとどうでしょう。

f:id:utr066:20180107163239p:plain

middleだと違いがわかりにくいので、topにしてみました。 線が上に来ていますね。 こんな風にvertical-alignを使うことで縦方向からみた要素の位置を変更することができます。

さっきまでやっていたのはmiddleを指定していましたが、あれは線の位置を真ん中にしたかったからなんですね。

線の位置を調整する

あとは、margin: 0 30px;のように空白を開けたりして調整すれば完成です。

<p class="hello-world">Hello World</p>
.hello-world {
  margin: 0 0 30px;
  letter-spacing: 1px;
  font-size: 2.2rem;
}
.hello-world::before,
.hello-world::after {
  display: inline-block;
  content: '';
  width: 140px;
  height: 2px;
  margin: 0 30px;
  background-color: #fff;
  vertical-align: middle;
}

f:id:utr066:20180107152520p:plain