アプリ開発・ウェブページ制作のフロントエンジニア

鹿野壮 氏(以下、鹿野):では始めていきます。私は先ほど登壇したICSの池田と一緒に働いている鹿野です。九州大学を卒業していて、TwitterのIDは@tonkotsuboy_comでやっています。愛猫がめちゃくちゃかわいいです。よろしくお願いいたします。

本日のテーマは「古きを捨てて新しきを得るためのCSS」で、GitHubに本日使うサンプルファイルをプッシュしているので、気になる方は後ほどダウンロードして見てください。

ではさっそく本題です。CSSは便利な機能が次々と追加されています。なので今まで当たり前だと自分たちが思っていた手法を見直すことで、より便利にWeb開発をすることが可能になりました。

今回はCSS Gridのおすすめという話と、ボタンブラウザで使えるようになった便利な機能の2つのお話をしていきます。

CSS Gridの使い方

まずはCSS Gridのおすすめから。さっそく、今プッシュしているサンプルファイルは1.0、1.1、1.2といった構成になっています。その中の1.0のGridというサンプルファイルを見てみると、ものすごくかわいい猫ちゃんが出てきました。

こういったレイアウトを私たちが作りたいと思った場合。ちょっとだけ古いやり方としては、フレックスボックスを使ってやっていました。どういうコードを書くかというと、今この右上がHTMLコードになっていて、その下がそれを実現するCSSコードです。

は全部を囲うコンテナの役割をしています。

そこにdisplay: flexを指定して、その下にvisualの、このかわいい猫の写真に対してwidth:50パーセントと書きました。右側の要素は2つまとめて右側に寄せたいのでlogoとparagraph「今日のうにちゃん」と書いているテキストの要素をまとめてrightというクラスで囲んでいます。

こうすることで、メインの下の要素はvisualとrightになったので、左右に寄せられたようなレイアウトになりました。rightの中もさらにdisplay: flexを使っておりまして、flex-directionをcolumnとすることで縦方向にフレックスボックスのレイアウトを適用することが可能です。

通常モードはflex-directionはrowなので横方向に並ぶんですが、flex-directionをcolumnとすることで縦に並びます。その中のlogoとparagraphの高さをそれぞれ80パーセントと20パーセントとすれば、ボックスでレイアウトできます。

できるんですが、フレックスボックス使用時、rightは文章的に意味のある要素ではありません。レイアウトを実現したいがための、言ってしまえば無駄な要素です。これをCSS Gridを使うと、こういったものを使わずにこのレイアウトとまったく同じものが実現できるようになります。

ではやってみましょう。まずはこの無駄だと言った

のrightというクラスを削除。これで今
要素の直下は、visualとlogoとparagraphとなりました。先ほどdisplay: flexと書いていたところをdisplay: gridに書き換えます。

ここからがCSS Gridのポイントです。CSS Gridでは、この全体の要素をどういう行と列に分けるかを考えながらレイアウトをしていきます。今回は左側に大きな画像、右側にロゴと右下にテキストがあるレイアウトです。これをよく見ると2行2列のレイアウトとみなすことができるんですね。これをCSS Gridで実現していきます。

どうやって実現するのかというと、grid-templateプロパティを使って、どういう行列に分離するかを定義していくわけです。今は行列の名前だけを定義しました。行列を2行2列に分割して左上の領域から名前を付けていったんです。

左上はvisual右上はlogoという名前で、左下、右下と名前を付けていきます。ここが1行目を表しているので、ここに80パーセントの行の高さを示すわけです。2行目も同様に2行目の高さを示します。ここをスラッシュで分離して、あとは同じように列の幅を1列目が50パーセント、2列目も50パーセントと設定すれば、目的のレイアウトが実現できて……いませんね。失礼しました。

今はまだ、親のコンテナ要素に対して行列を設定しただけです。あとは子どもの要素をどのようにレイアウトしていくのかを設定していきます。今回は、visualとlogoとparagraphの3要素をそれぞれレイアウトしたいので、visualとlogoとparagraphにgrid-areaプロパティというものを設定します。

grid-areaプロパティにそれぞれ配置したい領域を指定することで……すみません、まだ無駄なレイアウトが残っていましたね。配置したいレイアウトを指定することで、このようにCSS Gridでできるようになります。これがCSS Gridのものすごく基本的なところです。フレックスボックスと違って、わざわざレイアウトのためにHTMLコードを分離する必要がないメリットがあります。

CSS Gridを使ったボックスレイアウト

続いては1.2についてです。こういうボックスのレイアウトをやっていきたいと思います。これは親の要素に対してボックスが可変しながら、ボックス間の隙間が固定で20ピクセル空いてるようなものです。これはフレックスボックスで実現しようとすると、けっこう面倒くさいです。

上側にあるのがHTMLコード、下側にあるのがそれを実現しているフレックスボックスのコードになります。ネガティブマージンを使ったりしながら面倒くさいレイアウトをしないといけません。

これもCSS Gridを使えばすぐにできます。ここまでdisplay: flexを使っていたところをdisplay: gridでCSS Gridに変更。先ほどのgrid-templateプロパティというものを使ってセル名とかをcell cell cellと書いてもいいんですが、面倒くさいのです。そこで、このように同じ列が続く場合はrepeat値というものを使うことができます。

repeat値を使って2つの行を作ってください。高さは100ピクセルにしましょうか。下の部分に4列続けてください。4列の列の大きさは1fr、これはフレックスボックスでも出てきたfrという単位ですね。とある領域を同じ分だけ分割してくださいという意味で、こういうふうにすれば実現ができます。子どもの要素はそれぞれ100パーセントにしておきましょうか。

すみません、キャッシュが効いていて動かないんですけど、これで先ほどの2行4列のレイアウトができました。先ほどの隙間を空けたいのはgapプロパティを使うんですね。このgapプロパティで20ピクセルと設定をすれば、これだけでボックス間の隙間をレイアウトすることができます。

ちなみにこのgapプロパティは本当に便利で、フレックスボックスを使わずにCSS Gridを使うときにかなり大きな強みとなるプロパティです。ちなみにこのgapプロパティはフレックスボックスに逆輸入されようとしていて、Firefoxの最新バージョンやGoogle Chromeの今開発バージョンで、フレックスボックスのgapも使えるようになったりしています。(※Chrome 84から正式に対応しました)

gapはCSS Gridの便利な機能です。

CSS Gridを使った画像レイアウト

続いては、CSS Gridの最後ですね。CSS Gridをけっこう覚えてきたので、こういうレイアウトを作りたいなと思ったときがあるとします。このようにテキストと画像が1セットになっていて、それが横並びになっているようなレイアウトです。

これをCSS Gridで実現しようとするときに、我々はCSS Gridを少し学んでいくと、こういうコードを書かないといけないことがわかります。containerの直下にテキスト・画像、テキスト・画像、テキスト・画像といったものです。なんでかというと、CSS Gridの影響範囲はこのcontainerクラスの直下の要素だけなんですね。

本当は文章の意味付けをするために何かしらこのテキストと画像は何かboxとかで囲みたいわけじゃないですか。でもそれができなかったんです。それが最近出てきたCSS Gridと組み合わせて、ものすごく強力なdisplay: contentsを使うと実現できるようになります。

また上にHTMLコード、下にCSSクラスがあります。今は、display: gridを使って2行3列のレイアウトをしてくださいと言っていますが、このboxクラスで囲まれているから思い通りのレイアウトにはなりません。こういうときはこの各boxクラスを見た目上無視してあげて大丈夫です。

見た目上無視するときに使うのが、子どもの要素に設定するdisplay: contentsで、これを設定すると元通りになりました。これは、display: contentsが設定された要素がHTMLコードとしてはありますが、見た目上は消えてくださいねと指定をすることができます。

これをやることでCSS Gridを使いつつ、かつセマンティックなコーディング、タグ付けをすることができるのがdisplay: contentsのメリットです。これもIE 11を除く全モダンブラウザで使うことができるようになっています。

CSS Gridを使ったフォーム作成

ここからは後半の話です。モダンブラウザはIE 11を除く全ブラウザで使えるようになったので、その機能について紹介していきます。我々はこういったフォーム作成について考えてみましょう。よくあるレガシーなフォームですね。

ラベルの中に<input>タグがあるレイアウトです。私たちがやりたいのは、このテキストフォームにフォーカスをあてたときに<label>タグを丸ごと……例えば名前と住所の2つともを囲んでスタイリングをしたいケースを考えてみます。従来のCSSで考えてみたときに、この<input>タグに対してフォーカス疑似要素を付けて、上にHTMLコードと下にCSSスタイルがあります。

<input>に対して、このフォーカスを付けてできるかなと思ってやってみると、今は<input>にしかスタイルが当たってくれません。なぜなら今は<input>にしか当ててないからです。じゃあここをlabel:focusとかにして見ても、これも当たりません。

じゃあ自分の子ども要素の<input>にフォーカスが当たったときに、このラベル含めて丸ごとスタイルを当てたいときは、今まではJavaScriptを使う方法しかありませんでした。JavaScriptを使うとJavaScriptでこのラベルにjs-focusというクラスが当たって初めて色が付くようにするCSSの定義をしていきます。

JavaScriptはどう書くかというと<input>タグを全部キャッチにする。その中の<input>タグにフォーカスがあたったら<input>タグの親要素、今回でいえば<label>タグですね。親要素に対してjs-focusというクラスを設定してくださいみたいなことをやると、初めて目的のコードが実現できます。これはけっこう面倒くさいですよね。

これが今ではJavaScriptを全部消してfucos-withinを使うと、JavaScriptを書いていませんが目的のレイアウトが実現できるようになっています。これは<label>の自分自身の要素、または自分自身の子孫要素、この場合は<input>タグですね。

自分自身が自分自身の子孫要素にフォーカスが当たったときにスタイルを変更してくださいという命令ができます。これもChromium版のEdgeを含むすべてのモダンブラウザで使える非常に便利な機能です。こういったものをJavaScriptを使わずに実現可能になりました。

CSS Gridを使った画像サイズの指定

次に、我々がこういうレイアウトを作りたいと思った場合です。ヒヨコの画像はウインドウサイズを小さくしたときは、画面サイズに応じて小さくなります。今はウインドウサイズを700ピクセルと指定していますが、700ピクセル以上は大きくならないような要素を考えてみましょう。

こういった作業を今まではどうしていたかというと、レスポンシブなレイアウトを作るときは一定以上は大きくならないでくださいねみたいなレイアウトをよくやっていました。

<img>タグに対して幅100パーセントにする。でも横幅の最大は700ピクセルにしてください。こういった命令が必要だったわけです。これが最近でたmin関数を使うと、こう書くことができます。min(700px, 100パーセント)と指定すると、目的のレイアウトが実現できました。

これは、700ピクセルと100パーセントのうちどちらか小さいほうを採用してくださいねという関数です。画面サイズを小さくしたときに、今<img>タグは700ピクセルと100パーセントだと、画面サイズが700ピクセルより小さいので100パーセントのほうが小さい値になります。なので今は100パーセントのレイアウトです。

逆に画面サイズを700ピクセルより大きくすると、今度は700ピクセルが小さい値になるので、700ピクセルが採用される。これがmin関数です。ちなみにこれはmax関数やclamp関数といって、2つを合わせたような使い方もできます。つい先日のFirefoxのバージョンアップによって対応したので、今は全モダンブラウザで使える状態です。できたてほやほやの新しい関数と言えるでしょう。

ちなみにこれを応用していくと、こういった絶対に10文字しか入らないようなテキストの表現とかもできます。この画面サイズを小さくすると、それに応じてフォントサイズが画面サイズ100vw(viewport width)を分割するようにもできます。これがmin関数です。

CSSには便利な機能が増えていく

このように最近のCSSの機能はどんどん増えています。今まで使っていたCSSコードの見直しや新しい機能を取り入れることで、開発スピードをどんどん上昇させることができて作業が楽にすることができます。

積極的に新しい機能を取り入れて作業時間を減らしていく。それによって、コンテンツのブラッシュアップに時間をかけて、早く仕事を終わらせて家に帰るようにしましょう。

ご清聴ありがとうございました。ICS MEDIAやTwitterでも情報を発信しているので、ぜひこちらもご覧いただければと思います。以上です。