CSS

CSS & Design

CSSを
学ぶチュートリアル

第1章CSSのあらまし

CSS & Design編』へようこそ!

CSS(Cascading Style Sheet)」とは、World Wide Webのデザイン言語です。開発者やデザイナーは、CSSを用いて、Webページの表示や装飾や振る舞いを定義1します。皆さんがブラウザで表示するどんなWebサイトでも(よほどの変わり種でもない限り)、ユーザーエクスペリエンスや画面のインターフェイスを魅力的に見せるためにCSSを活用しています。すなわち、CSSの基礎を学ぶことは、Web開発者やWebデザイナーになるうえで欠かせません。また、Web開発者やWebデザイナーと仕事上のやりとりをするうえでも必ず役に立ちます。

世の中にあるCSSのチュートリアルで教えているのは、そのほとんどが「孤立した単独の単元としてのCSS」であり、テキストの色やフォントのサイズの変更方法などをこまごまと教えてくれることはあっても、それがHTMLやWebサイトやJavaScriptやWebフレームワークとどのように関連するかという全体像については何も教えてくれません。これはちょうど、学生に外国語の辞書を読ませて外国語を教えているようなものです。単語は山ほど覚えられるかもしれませんが、覚えた単語を実際の会話でどんな場合にどう応用したらいいのかという「勘どころ」についてはほとんど何もわからずじまいでしょう(図 1.12

CSS & Design編』はそれとは対照的に対照的に、CSSが現実のWebサイトでどのように活用されているかを理解することに特化して構成されています。

images/figures/spanish
図 1.1: 辞書だけでスペイン語を学ぼうとする人は普通いないでしょう

特に、Webページの「レイアウト」をどのように組み立てればよいか、つまり「ある要素をページ上で具体的に配置する方法」「どんなコンテンツをどこに配置すればよいかを正しく決める方法」を網羅したチュートリアルを見つけるのは簡単ではありません。これは重要な単元であるにもかかわらず、軽んじられています。

レイアウトの扱いがこれほど軽い理由はどこにあるのでしょう?CSSのレイアウトに関する側面がかなり複雑であることも理由のひとつですが、正しくレイアウトを組むためには、単なるHTMLやCSSの枠を超えた知識と練習が必要になるからです。現実の商用レベルWebサイトを構築するには、何らかの「テンプレートシステム(templating system)」を使ってさまざまなパーツを自動的に組み立てることが求められます。そうした商用Webサイトでは、同じ記述の繰り返し(重複)や、ヘッダーやフッターや動的に生成される名前や日付といったカスタム要素があまりにもふんだんに出現するので、もはや手書きでのサイト構築は絶望的でしょう(図 1.2)。

images/figures/page
図 1.2: 現代のWebサイトのほとんどが、カスタム要素や要素の繰り返しを大量に使っています

世の人は「CSSは基本部分を押さえておけばいいんじゃないの?」と思いがちですが、早く本物のCSSエキスパートになろうとするあまりCSSの基本部分だけを短期集中型で学んで済ませてしまうと、後から学ばなければならないことがものすごく増えてしまい、逆に高くつきます。つまり、CSSの基本的なスタイル設定を学ぶだけでは不十分であり、ページレイアウトを支配する高度な規則も学ぶことはもちろん、大量のパーツをひとつに組み立てるツールも学ぶ必要があるということです。

CSS & Design編』は、まさにこのニーズを押さえる目的で構成されています。本チュートリアルは、『HTML編』を学んだ直後に続けて学ぶことを想定して最適化されていますが、Webデザインの知識を強化したい現役のベテラン開発者3の学習にも最適です。何よりも、あの『Ruby on Railsチュートリアル』を学ぶ前の必須科目でもあり、学んだ後に知識を強化する極上のフォローアップ本でもあるのです。

私たちは『開発環境の基本』コラム 1.1)を執筆しながら『CSS & Design編』の構想を練り上げたことで、他のチュートリアルと同様に、プロの開発手法を用いてサンプルCSSサイトを実際のWebにデプロイするという、他に類を見ないアプローチを採用しています。この網羅的なアプローチによって、本チュートリアルは、CSSを既に学んだ方でもおそらく目にしたことのないレベルですべてが盛り込まれています。

コラム 1.1. 必要な前提知識

本チュートリアルでは、「Unixコマンドラインを使いこなせる」「テキストエディタをストレスなく扱える」「Gitによるバージョン管理に慣れ親しんでいる」、そして「HTMLの基本的な構造を理解している」読者を前提としています。これらの単元の概要を知りたい方、または改めて学びなおしてみたい方は、以下のチュートリアルから該当のものをお読みいただくことをおすすめいたします。

  1. コマンドライン編
  2. テキストエディタ編
  3. Git/GitHub編
  4. HTML編

上記チュートリアルは、皆さんのコンピュータで適切な開発環境をセットアップするときにも役立ちます。これについては『Learn Enough Dev Environment to Be Dangerous』でも扱われていますが、本チュートリアルでは5までセットアップ作業をスキップしても構いません。

1.1 「あなたはフロントエンド開発者なのだ」

CSSは、ちょっと本を読んで手を動かせば覚えられるタイプの便利な言語ではありません。雑に作るだけならその程度の学習でもできるようになれますが、多くの人がCSSで難しいと感じているのは、さまざまなレベルの複雑さが共存するWebサイトをどうやって「隅々まで正しく」作るかです。大変なのは「隅々まで正しく」の部分なのです。「コンテンツやデータを使いやすく編成できる柔軟なレイアウトを持ち」「さまざまな大量のコード片4 を柔軟なレイアウトに配置できる」マルチページWebサイトを立案・設計する方法を会得しなければ、本物のCSSスキルとは言えません。

MDN CSSリファレンスのように、あらゆるCSSプロパティを網羅したWebサイトは既に世に満ちあふれていますので、本チュートリアルで同じ説明を繰り返したところで「屋上屋を架す」のと変わりません。その代わり『CSS & Design編』は、現実のWebサイトでCSSをどうデザインに適用するかを詳しく解説することで、そうしたリファレンスを補完するように構成されています。その結果、ストーリー中心の解説によって、CSSのリファレンスを理解して応用するのに必要となる「現場での事例」「うまい調査方法」「アプローチを変えるべきタイミング」といった利用上のコンテキストが具体的に見えるようになっています。特に、例の「技術の成熟」と合わせ技にすることで効果が倍増します(コラム 1.2)。

コラム 1.2. 技術の成熟

本チュートリアルシリーズを貫く基本的なテーマのひとつは、皆さんの「技術の成熟(technical sophistication)」精神、つまり技術上の問題を自力で解決するスキルとマインドセットを育て上げることです。

本チュートリアルでは、「技術の成熟」精神を適用する機会が多数用意されています。たとえば、多くのコードは、何も考えずにコピペしてエディタに貼るだけでは動かず、CSSファイルの中で何を行うべきかという方針をある程度自力で見出し、リストに示された新しいスタイルをどこに置くべきかをある程度自分で考えるようになっています。「コピペすればおしまい」の上げ膳据え膳方式や「材料は用意した、後は自分で考えろ」の放置プレイに陥ることを避けて、自力で解決するスキルを少しずつ絶え間なく身につけられるよう配慮しています。

本チュートリアルにおけるもうひとつの重要な手法は「CSSのコメントアウト」の活用です。つまりCSSのスタイル指定をコメントアウトしてブラウザを更新し、ブラウザ表示がどう変わるかを実際に見ながら学ぶようになっています。また、折に触れてCSSのスタイル指定をデモンストレーションする目的でスタイル指定を追加することもあります。「技術の成熟」精神は、そうしたデモ用コードが安全に削除できるかどうかを自分で判断するスキルでもあります(特に、その後の作業リストに削除の指示が含まれていない場合)。

後半の章、特に5以降では、開発環境を正しく設定することと、テンプレートシステムを実行してプロレベルのWebサイトを構築することも求められます。おそらくこれらの作業を終えるまでに何度でも間違える可能性があります。途中で行き詰まったときは「ググって決める」以外に道はありません。どちらも「技術の成熟」精神の重要な側面です。

開発者として学習を進めるうえで重要なポイントは、「スタイル指定とレイアウトの概念が密接に関連して動作するしくみ」「HTMLとCSSを効果的に組み合わせて実際に使いやすいレイアウトを作る方法」「サイト内でのコードの繰り返し(重複)を回避して、複数ページのスタイルを一括指定するシステムの使い方(コラム 1.3)」を最初に学ぶことです。これらをスキップして細かなプロパティを丸暗記しても、テキストの色やサイズを変更するエキスパートぐらいにはなれますが、学んだ知識を実際の現場で活用する機会は巡ってこないでしょう。実はCSSをこのように「全体像から学ぶ」ということは、単にスタイル指定方法の初歩に触れるだけではなく、本格的な「フロントエンド開発(front-end development)」の世界を初めて垣間見ることでもあるのです(図 1.35)。

images/figures/owl
図 1.3: 「あなたは魔法使いフロントエンド開発者なのだ、ハリー」
コラム 1.3. DRYの原則

ネットで開発者がたむろしている場所を覗いたことがある方なら、「DRYにせよ」という言葉を見かけたことがあるかもしれません(DRYはすべて大文字)。もちろん部屋の湿度の話ではなく、プログラミングにおける重要な原則「繰り返すな(Don’t Repeat Yourself)」のことです。

DRY原則は「人間がやらかす可能性のある無駄な繰り返しをできるかぎり避けることも、よいコーディングの条件のひとつである」という考え方に基づいています。アプリケーションの中で同じコードがあちこちにばらまかれていると、変更のたびにそれらをひとつ残らず変更して回らなければならなくなってしまうというシンプルな理由です。たとえば手作りWebサイトのナビゲーションバーへのリンクを変更しようと思ったら、すべてのページを開いてリンクを変更しなければならなくなるでしょう。ページが2つしかないWebサイトなら大した手間ではありませんが、大規模なWebサイトでは悪夢そのものです。

プログラマーは、ある方面については徹底的に怠け者であろうとする特殊な気質を持ち合わせています。特に、たとえどんなにささいな作業であっても、同じことを何度も繰り返すことを徹底的に嫌がります。積極的なプログラマーは、繰り返しをせずに済むためなら、どれだけ時間がかかっても他のプログラマーたちが同じことを繰り返さないためのシステムを構築したりします。怠けるためならいくらでも頑張れる、という一見相矛盾する情熱を有するのが、プログラマーという人種です。ある日彼らが、「今のうちに手間暇かけて作っておけば今後は楽にやれるから」と決定を下してくれたおかげで、他の人たちもその恩恵にあずかれるというわけです。

5で導入する予定の「テンプレートソフトウェア(templating software)」は、まさにそのようにして生まれたソフトウェアのひとつです。さまざまなファイルに繰り返し出現するコードをかき集め、それに対応するコード片を必要に応じて自動的に配置することで、繰り返しを避けられるようになります。

そのおかげで、ナビゲーションメニューのようなパーツをサイトで「一度」作っておけば、それ専用の小さなファイルに保存して、ナビゲーションの必要なページに自動的に配置できるようになります。後日ナビゲーションを変更するときも、編集の必要なファイルは1つしかなく、変更結果はナビゲーションを含む全ページに自動的に反映されます。利用法について詳しくは 5.6で扱います。

1.1.1 ところでフロントエンド開発って何?

誰かを指してフロントエンド開発者と呼ぶとき、「Webサイトのうち、ユーザーが目にしたり操作したりする部分を開発する人」を意味し、作業内容にはHTMLやCSSやJavaScriptも含まれます。他にも「UIデザイン」(表示の設計)や「UXデザイン」(User eXperience: ユーザーエクスペリエンス、UIやページの機能を駆使してユーザーがWebサイト上で目的を達成できるようにする方法)という言葉を聞いたことのある人もいるでしょう。

フロントエンド開発の対義語は「バックエンド開発(back-end development)」です。バックエンド開発では、データの構造や保存や配信の方法などを扱います。バックエンド開発の基礎学習は『Ruby編(翻訳予定)』から開始される予定で、そのときに「データベース」「ユーザー管理」「ログインと認証」といった機能を備えたフルスペックのWebアプリケーション開発を扱います。

では、HTMLイモムシがフロントエンド開発チョウチョになるにはどうしたらよいのでしょう?(図 1.4

images/figures/butterfly
図 1.4: 「『CSS & Design編』を読むほうが羽化するよりラクだね〜」

まずは、『HTML編』で学んだスタイル指定の方法を振り返ってみましょう。最後のセクションでは、まずスタイル指定をページの要素に直接追加する方法(インライン方式)を学び、次にそのスタイルをスタイルシートに切り出す方法についても少しばかり学びました。本チュートリアルでは、後者のテーマを大きく発展させます。

本章ではこれより、さまざまなCSS宣言や値の基礎を学びます。そのため、きわめてシンプルな要素を少しだけ配置したサンプルページを用いて、最初のうちは上述のDRY原則(コラム 1.3)を徹底することに集中します。本章の最後では「CSSセレクタ(CSS selector)」という重要なテクニックが初めて登場し、これを用いてページ内の特定の要素のみに狙いを定めてスタイルを指定する方法を学びます。

2では、セレクタのさまざまな側面について解説します。セレクタは、プロジェクト開始時点で正しく扱うことが重要です(プロジェクトが始まってからでは遅いのです)。ここで学ぶ「よい名前の付け方」は、複雑なサイトを正しく管理し、柔軟性を損なわないために重要です。CSSの色指定方法もここで登場します。

3では、CSSのさまざまな値の中でも二大筆頭である「色指定用の値」「サイズ指定用の値」が登場します。ここで学ぶ内容は、4の「ボックスモデル(box model)」の重要な基礎知識を準備し、ページ上のさまざまな要素がどのように組み合わせられるかを決定します。

5および6では「静的サイトジェネレーター(static site generator)」を導入します。これを用いてこれまで学んできたことをひとつのレイアウトに盛り込み、メンテナンスも更新もしやすいプロ級のWebサイトを構築します。

7では「flexbox」を用いて柔軟なページレイアウトを組む方法を学びます。これを用いてフォトギャラリーページにレイアウトを追加したり(このページは『JavaScript編』で仕上げます)、ブログページに投稿を表示したりします。8ではブログそのものを追加し、Jekyllというツールを用いてプロ級のブログサイトを構築します。

現代のWebトラフィックの大部分は、モバイルデバイス(スマホやタブレットなど)によるものであり、これらを軽んじていけません。9ではCSSと「メディアクエリ(media query)」の基礎を学んで、DRY原則(コラム 1.3)を守りながらモバイルでも使いやすWebサイトを構築できるようにします。

最後の10では、「カスタムフォント」「metaタグ」などの細かな点を追加してWebサイトの完成度を高めます。ここまでくれば、いい感じにスタイルが設定された業務レベルのWebサイトを実際にデプロイして動かせるようになります。

それでは始めましょう!

1.2 CSSの概要と歴史

CSSはプレーンテキスト形式で宣言され、テキストエディタを用いてHTMLファイルやCSSファイルに配置します。典型的なCSS宣言はリスト 1.1のようになります。この時点でCSSの内容がわからなくても問題ありません。

リスト 1.1: 典型的なCSS宣言
body {
  color: black;
}

p {
  font-size: 1em;
}

p.highlighted {
  font-size: 1.5em;
  background: yellow;
}

CSSの「カスケード(cascading)」とは、定義されたスタイル指定がある要素から別の要素へ伝搬することを指します。カスケードは、「何が最初に宣言されたか」「その要素に親要素はあるか」「その親要素にはスタイルが指定されているか」「宣言の詳細度は高いか低いか( 2.3で後述)」といった点に基づいて進行します。

この「スタイルの継承」(トップレベルからその下にある子要素にスタイルが受け継がれること)が発生することで、すべての要素にひとつひとつスタイルを設定して回らなくても済むようになります。たとえば、先ほどのリスト 1.1bodyタグの中にあるcolor属性を変更したとすると、その変更はbody要素で囲まれているすべての要素のcolor属性にも伝搬して反映されます。このようにスタイル指定が伝搬して受け継がれる様子をカスケードと呼びます6

CSSの「スタイルシート(style sheet、stylesheetと書くことも)」とは、そのページのスタイル宣言(スタイル指定)を、ページ内にあるひとつの独立したセクション(内部スタイルシート)または外部ファイル(外部スタイルシート)に集約できるようにするしくみを指します。外部スタイルシートは、HTMLのheadセクションにリンクとして記述することでページに読み込まれます(この方法については5で実践します)。このようにすることで、ページの実際のコンテンツから、ページ上に表示するときの外観や配置を定義するコードを切り離せるようになり、コンテンツやコードがシンプルになってメンテナンスしやすくなります。

1.2.1 CSSの仕様は常に変化している

ここでCSSについて知っておくべき重要なポイントがひとつあります。WebデザイナーやWeb開発者のニーズに応えるために、HTMLと同様、CSSも常に進化を繰り返しています。実際、CSSの進化の方がHTMLの進化よりはるかにテンポが早いのです(図 1.57

images/figures/goldblum
図 1.5: CSSもジュラシックパークの恐竜と同じく、進化する

公式のCSS仕様には将来のための追加が常に繰り返されてはいますが、まだ「均等には行き渡っていません(ウィリアム・ギブスンの名言より)」。CSSへの新しい仕様追加が提案されても、そうした新しい概念を実際に採用するかどうかはブラウザごとにまちまちです。たとえば、あるスタイル指定はGoogle Chromeでは動いても、Mozilla FirefoxやMicrosoft Internet Explorer(またはポストIEのMicrosoft Edge)ではまったく動かないということもあるのです。ブラウザで新しいスタイルがサポートされているとしても、実際には当面の間、一時的な名前を特別にスタイルで指定した場合に限り(コラム 1.4)、開発者が使いたいスタイルをサポートしているブラウザでだけ使えるものもあります。

コラム 1.4. ベンダープレフィックス

追加が提案された新しい仕様(spec: specification)が実際に公式のCSSに反映されるまでには、しばらく時間がかかります。そのため、新しい機能は必ずしもすべての(メジャーな)ブラウザで一斉に受け入れられるとは限りません。しかしブラウザ開発者(ベンダー)の多くは、仕様が公式に更新されるまで待つつもりはなく、自分たちのブラウザをいち早く限界まで強化(あるいは魔改造)したがる傾向があります。そうしたブラウザベンダーは、CSS仕様の新しい提案を察知するとただちにその仕様を独自に実装し始めます。

ブラウザごとにまちまちな実装状況による混乱を回避するため、ブラウザごとに動作が異なる機能については、ブラウザベンダーはそうした機能にベンダー固有のプレフィックス(prefix: 接頭語)を追加して、そのスタイル指定が実験的な機能であることを示すことがよくあります。ベンダープレフィックスには「-webkit-WebKit: ChromeEdgeSafariなど)」「-moz-Firefoxなど)」「-ms-IE)」などがあり、これによって、ブラウザによってサポート状況の異なるスタイル指定を、特定のブラウザで指定できるようになります。

たとえば、CSSのtransition( 7.4で後述)は、公式のCSS仕様に追加される前にほとんどのブラウザで実装されていました。そして実際に使うときには、以下の例のようにスタイル指定の冒頭にベンダープレフィックスを追加して宣言する必要がありました。

  -webkit-transition: all 0.1s linear;
  -moz-transition: all 0.1s linear;
  -ms-transition: all 0.1s linear;
  transition: all 0.1s linear;

上の1行目は、WebKitというレイアウトエンジン(SafariやChromeや新しいEdgeなどで使われています)を内蔵するブラウザのみを対象とし、2行目はMozillaのGeckoエンジン(Firefoxなどで使われています)を対象とし、3行目はMicrosoftのブラウザ(IE)を対象としています。末尾の4行目は、プレフィックスなしの宣言(ここではtransitionそのもの)です。このようにプレフィックスなしの宣言を置くことで、今後ブラウザベンダーがベンダープレフィックスを廃止してこの機能を本採用しても、宣言を追加せずに済みます8

訳注: ブラウザとレンダリングエンジンの関係は移り変わりが激しいので全体像が把握しにくく、注意が必要です。本注釈は2020年12月時点の情報です。Chromeは、以前はWebKitエンジンでしたが、その後WebKitから枝分かれしたBlinkエンジンを採用しています(ベンダープレフィックスはどちらも-webkit-)。Internet Explorer(IE)は既にEdgeに移行しており、最終バージョンのIE 11が今後順次サポート終了しますが、現実にはまだまだ使われているようです。Microsoft Edgeは2020年にChromeと同じエンジンを採用したので、現在のベンダープレフィックスは-webkit-です。また、同じブラウザでもOSによってエンジンが異なることもあります。特にiOSでは、Appleの規約によって他社のブラウザであってもエンジンはWebKitを使わなければならず、たとえばiPhone版のChromeでは実際にはSafariと同じWebKitエンジンが使われています。

ありがたいことに、最もよく使われるスタイル定義は、現在さまざまなブラウザで本質的に同じように使えます9。そして本チュートリアルでは、ブラウザでのサポート状況が怪しいスタイル指定などについて扱う予定もありません。とは言うものの、新しい機能をいち早く使ってみたいこともあるものです。そんなときは、CanIUseなどのツールでブラウザでのサポート状況を調べることをぜひおすすめします。なお、このようなリファレンスサイトで調査することを恥ずかしがる必要も隠す必要もありません。CSSが激しく移り変わることは避けようがありませんし、ブラウザでのサポート状況が今ひとつであることも珍しくないので、長年フロントエンド開発に従事している人々にとってもCanIUseなどのツールは必要不可欠です10

1.2.2 CSSの発展史

はるか昔、インターネットの世界にあったのは単なるプレーンテキストのコンテンツばかりでした。あるとき、コンテンツを論理的に組み立てる手法が現れ始めると(1990年頃に登場したHTMLもそのひとつです)、データの外観やレイアウトを整える手法が無数に出現し、覇を唱えようと互いに争うようになり、戦国時代を迎えました。

始めのうちは、コンテンツの作者の意図はそっちのけで、ユーザーが使う表示プログラム(今で言うブラウザ)で外観を自分好みに設定するようなスタイル指定法が幅を利かせていました。やがてWeb世界が複雑になってくると、少なくともページのコンテンツをどう配置してどのようなスタイル指定で表示するかは、個別の表示プログラムで設定するのではなく、コンテンツの作者が決めるべきだということが明らかになり始めました。

興味深いスタイル設定方法が数多く提案されましたが、それらは無駄に複雑すぎたり、文書構造がまったく直感に反したりしていたため、いずれも広く採用されるには至りませんでした。

  • Robert Raischの開発した「RRP」は、何の略だかよくわからない2文字の略語でスタイルを宣言する方式でしたが、読みやすいとは言えませんでした。
  • Pei-Yuan Weiが開発したViolaWWWという初期のブラウザには、PWPというスタイル指定システムが組み込まれていました。PWPはスタイルのネストや外部スタイルシートなどを導入するなど現代でも通用する機能もありましたが、Unix OS版しかなく、広く支持を得ることもありませんでした。
  • FOSI」は、HTMLの先輩であるSGML向けのスタイルシート言語で、ページのコンテンツの周囲に難解なタグを追加する方式でした(残念な出来)。
  • DSSSL」は、どちらかというとスタイル指定もできる一種のプログラミング言語で、複雑な宣言を扱えましたが、構文が難解で、スタイル指定が複雑になりがちでした。

要するに、この時代は生物史で言うカンブリア爆発そのもので、よりよいWeb標準についての各種提案が古代Webの海にあふれかえっていました。その中のいくつかは、後にCSSとなったものにいくばくかの遺伝子を残したものの、CSSの直系の先祖はひとつもありません(図 1.611)。

images/figures/cambrian
図 1.6: CSSのおびただしいご先祖たち…生き長らえたのはほんのひと握り

HTML誕生の5年後の1996年12月、Bert Bosと共同作業していたHåkon Lieが、CHSS(Cascading HTML Style Sheet)というスタイル指定システムを提案しました。皆さんのご想像どおり、オリジナルのCHSSには、今のCSSには存在しない詳細もありましたが、Håkon Lieは博士論文でCHSSの仕様をシンプルな形に改めました。これは現代のCSSにだいぶ近いものになっていました。そしてこの概念が最終的にW3C(WWW Consortium)にWebコンテンツのスタイル指定システムとして採用されたのです。

これはもちろん大きな前進ですが、仕様の策定は前半戦に過ぎません。エンドユーザーが自由にスタイルを指定するには、ブラウザがその標準を実装してサポートしなければなりません。実際、1997年になるまで、CSSを部分的にでもサポートするブラウザは存在しませんでした。標準を完全にサポートするブラウザの出現は、2000年3月まで待たなければなりませんでした(図 1.7)。

images/figures/2000
図 1.7: CSSがやってきたのはミレニアムパーティの後(喜んでよかったんだろうか?)

CSSは長い間、ブラウザごとに違うオレオレ実装によって扱われていました。フロントエンド開発に少しでも関わったことがあれば、Webサイトのスタイル指定を複数のブラウザで同じように表示しようとすると、正気を保っていられなくなるほどの困難に直面したものです。中でも、Microsoft Internet Explorer(IE)は当時最大の問題児でした(図 1.8)。初期のIEのCSSサポートが箸にも棒にもかからないほどひどかったために12、一体何人の人々がWebデザインとWeb開発の世界に見切りをつけたかについては、皆さんのご想像にお任せするよりほかにありません。

images/figures/ie6
図 1.8: IE6で画面をデザインしてみなければ、本当の憎しみというものはわからない

ブラウザごとにCSSの実装が違ってしまっているという問題は、ほんの数年前にWebKitエンジンを搭載したブラウザ(Google ChromeとApple Safari)と、Geckoエンジンを搭載したMozilla Firefoxが台頭して世の中を席巻するまで、長い間引きずられていました。まとめると、本チュートリアルを読むときには「Webのスタイル指定は、1997年にCSSの最初の仕様が公開されてから15年もの間(ほんのついこの前まで)、混乱の極みだった」ということを頭の片隅に置いていただければと思います。

訳注: CSSの仕様に興味のある方向け情報です。CSSの正式な仕様は、標準化団体であるW3Cのサイトで読めます。CSSの仕様は大変巨大なので、全体像を把握するだけでも骨が折れます。なお2019年からは、業界団体であるWHATWGHTMLDOMについては最新の仕様を公開していますが、CSSについてはW3Cのドラフトを参照しています(参考: 『HTML標準めぐりブラウザー業界団体とW3Cが合意–主導権は業界側に』)。これらはいずれも英語資料ですが、日本語のCSSリファレンスとしてはMDN(Mozilla Developer Network)のCSSドキュメントがよく整備されていて利用しやすいと思います(その代わり上述の英語仕様ほど最新ではありません)。

1.2.3 永遠の主観という名の沼

CSSのお勉強を始める前に、最後にもうひとつだけ、ちょっとしたメタ情報をお教えします。ページ上でCSSを実際に実装する方法は1つではありません。CSSの実装方法を「これしかない」「これさえやっておけばいいんだ」と1つに決め打ちすると、後々混乱を招く可能性があります。

既刊のチュートリアル(コラム 1.1)は、本チュートリアルよりも原則論を重視して進める形になっていて、何かを行う方法が複数ある場合にも、なるべく標準的または既に定着した正しい方法をひとつだけ提示するようにしています。これは学習者を迷わせないための配慮でもあり、実際に正しい答えをひとつに絞り込める内容でもあるからです。

しかしここから先には「正しい答えが用意されていない」こともざらにある未踏の世界が広がっています。私たちはその世界へ冒険の旅に出発しようとしているのです。WebサイトをCSSでデザインしようとすると、問題を解決する手法が次から次に見つかってまごついてしまうのが普通です。自分の主観を頼りに判断することは、この世界では例外的な行為ではなく、「」です(図 1.913)。

この混乱の沼を乗り切るお手伝いをするのが、私たちの仕事です。

冒険の旅が少しでも楽しくなるよう、別の話もしましょう。コラム 1.4では、どんなブラウザでもCSS標準の実装方法がそれぞれ少しずつ違っている部分がどこかにあるというお話しをしたかと思います。つまり、同じWebサイトを別のブラウザで表示したときに、表示結果が完全に一致するとは決して断言できないということです。画面の大きさを変えたらどうか、モニタの解像度が変わったらどうなるか、OSが違う場合はどうか、については言うまでもありません(9)。

まず、「見る人が変わっても完全に同じ画面を表示できるWebサイトというものは、この世に存在しない」ことをしっかりと身体に刻み込みましょう。これから学ぶのは、Webサイトをデザインするとき(またはデザイナーから受け取ったデザインを実装するとき)に、CSSの継承があいまいな場合にも表示の食い違いを許容範囲におさめる方法です。印刷や出版のような厳密な制約の多い世界とは異なりますので、あらゆるブラウザやあらゆるOSで表示を完全に一致させようと気に病むのではなく、限度を見切ることが肝心です。

もうひとつ付け加えます。Webサイトにスタイルを指定するときやレイアウトを組むときに、結局どのCSSスタイル指定を使えばよいのかがよく話題になりますが、そうしたベストプラクティスは流行り廃りに左右されやすく、プロジェクトの前任開発者の主観にも影響される傾向があることを覚えておきましょう。たとえばこの後 1.5でも取り上げるように、ページ上のさまざまな要素にCSSのクラスやidを割り当てる必要が生じることがよくありますが、そこでどんな名前を付けるかは完全にコードを書く人次第です。エンジニアやデザイナーの知り合いが多い方なら既にお察しかもしれませんが、人間は、えてして命名の話になると途端に「いや、名前はこう付けるべきだ」「こういう名前はダメだ」などと意固地になり、ちょっとやそっとでは意見を曲げてくれなくなります。技術の世界に昔からよくある宗教戦争のパターンです(図 1.1014)。

images/figures/holywar1
図 1.10: 宗教戦争その1:「クラス以外はまかりならぬ!」

いろいろ申し上げましたが、実装方法でも命名でも何でも、「一貫させること」つまり「ばらつかせないこと」が何よりも肝心です。たとえ実装が少々まずくても、複数の実装方法が混じり合ってしまうよりずっとましです。命名ルールが拙いことよりも、命名ルールが統一されない方が大きな問題です。

プロジェクト開始時点で何かひとつ方法を定めたら、プロジェクトが完了するまでその方法を変えないようにしましょう。途中で方針を大きく転換するのであれば、その後数日間は既存コードの更新に専念し、自分を含む今後のプロジェクトメンバーが困らないようにしましょう。本チュートリアルでは「スタイルメモ」というコラムをいくつか用意してあり、そこではCSSの別の用法に適した現時点のベストプラクティスも紹介していますので、こちらもぜひお読みください。

1.3 サンプルサイトをセットアップする

CSSの目的や起源に関するあらましを学んだので、いよいよ具体的なサンプルの作成に取り掛かりましょう。最初のスタイル指定は必ずしもシンプルではありませんが、5から始まる作業用Webサイト(レイアウトを含む)に備えて重要な基礎知識を固めますので、ここは辛抱が肝心です。

新規プロジェクト作成の手始めは、『HTML編』でプロジェクトを作成したときと同じように、mkdirコマンドでreposディレクトリを作成します(リスト 1.215

リスト 1.2: サンプルプロジェクト用のディレクトリを追加する
$ cd                                   # ホームディレクトリに戻る
$ mkdir -p repos/<ユーザー名>.github.io  # サイトのディレクトリを作る
$ cd repos/<ユーザー名>.github.io        # 作ったディレクトリに移動する

このとき、以下のようにメインのGitHub Pagesサイトで使う自分のアカウント名と同じ名前を、上のコマンドのディレクトリ名で使うことにご注意ください。

<ユーザー名>.github.io

リスト 1.2<ユーザー名>は、自分のGitHubアカウント名に置き換えます。これで、完全なURLはmhartl.github.ioのようになります。

GitHub Pagesは、実際にはmhartl.github.io/sample_cssのようにサブディレクトリからのサイト公開もサポートしていますが、残念ながらこのソリューションはmhartl.github.io/sample_css/galleryのようにさらにサブディレクトリが存在する場合はうまくいきません。その理由は、ファイルや画像を1個のサブディレクトリ(つまりsample_css)に保存する場合は、それより下のサブディレクトリを保存する自然な方法がないためです。このサンプルWebサイトは最終的にまさにこの構成を取ることになるので( 6.4)、サブディレクトリを使わずにGitHub Pagesドメインのルートを使うことにしました。より良い方法は「カスタムドメイン」を使うことで、これならGitHub Pagesのサイトをwww.example.comのようなURLにホストできます。カスタムドメインについては無料の『Learn Enough Custom Domains to Be Dangerous』チュートリアルをどうぞ。

HTML編』で解説したときと同じように、サイトを動かすのに必要なindex.htmlファイルを以下のようにtouchコマンドで作成します(リスト 1.3)。

リスト 1.3: 空のindex.htmlファイルを追加する
$ touch index.html    # 空のindexファイルを作る

この新しいディレクトリで作成したindex.htmlファイルを好みのテキストエディタで開き、リスト 1.4のマークアップを貼り付けます。ご覧のとおり、ごく基本的なHTMLページです。このHTMLがまだよくわからない場合は、今のうちに『HTML編』をおさらいすることをおすすめします。

リスト 1.4: サイトの最初のHTML index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Test Page: Don't Panic</title>
    <meta charset="utf-8">
  </head>
  <body>
    <h1>I'm an h1</h1>
    <ul>
      <li>
        <a href="https://example.com/" style="color: red;">Link</a>
      </li>
      <li>
        <a href="https://example.com/" style="color: red;">Link</a>
      </li>
      <li>
        <a href="https://example.com/" style="color: red;">Link</a>
      </li>
    </ul>
    <h2>I'm an h2</h2>
    <div style="border: 1px solid black;">
      <a href="https://example.com/" style="color: green;">I'm a link</a>
    </div>
    <div style="border: 1px solid black;">
      <a href="https://example.com/" style="color: green;">I'm a link</a>
    </div>
    <div style="border: 1px solid black;">
      <a href="https://example.com/" style="color: green;">I'm a link</a>
    </div>
    <div style="border: 1px solid black;">
      <a href="https://example.com/" style="color: green;">I'm a link</a>
    </div>
  </body>
</html>

このHTMLドキュメントをブラウザで表示すると(コラム 1.5)、赤い文字のリンク、見出し、ボックスに入った緑色のリンクがいくつか表示されます(図 1.11)。これが最初のテストページになります。

ブラウザの種類やウィンドウのサイズなどによっては図とわずかに表示が異なる可能性もありますが、既に申し上げたとおり、わずかな違いは心配無用です。本チュートリアルでは、1ピクセルのずれもなく図と完全に一致させることに頑張るのではなく、必要にして十分な画面を表示することに集中することが重要です。

images/figures/index-start
図 1.11: 一見どうということはなさそうだけど、ここで何かすごいことが始まる
コラム 1.5. HTMLファイルの開き方

皆さんの環境のセットアップに応じて、リスト 1.4のHTMLファイルをブラウザで開く方法がいくつもあります。最も素直なのは、『HTML編』でも解説したように、OSの機能を使うことです。macOSの場合、以下のようにopenコマンドを使うのが私たちの好みです。このコマンドは、ファイルの種類に対応するデフォルトのプログラム(つまりHTMLファイルならSafariかChrome、PDFならプレビューアプリなど)をOSが判定して開きます。

$ open index.html    # macOSでのみ有効

Linuxシステムの多くは、xdg-openという似たコマンドが使えます。

$ xdg-open index.html    # Linuxでのみ有効

ここで知っていただきたいのは、このようにOSの機能でファイルを開く方法は、チュートリアルが進むにつれて使いづらくなるということです。その理由は、 5.2から使い始めるJekyllという静的サイトジェネレーターの設定上の都合によるものです。Jekyllでは、Webサイトや動的Webアプリを開発するのに必要なプログラミング言語やツールを使うために、そのOSのユーザー環境を正しい「開発用環境」としてセットアップすることが求められます。

本チュートリアルを進めているときに(ここ、または5で)開発環境のセットアップで何か困ることがあったら、『Learn Enough Dev Environment to Be Dangerous』で自分のOS環境に合う手順を参考にしてください。

一部読者向けの注意事項: 素のWindows環境は、そのままでは開発に不向きです。開発環境のよい構築方法を教えるときに常に問題となるのが、Windows環境の上にソフトウェア開発環境を構築することの難しさです。『Learn Enough Dev Environment to Be Dangerous』でも解説されているように、Windowsユーザーは何らかの「クラウドIDE」または何らかの「Linux VM」環境を使うことをおすすめします(なお、私たちが推奨するクラウドIDEであるCloud9はLinuxを実行することからわかるように、クラウドIDEとLinux VMは実質的に同じです)。

クラウドIDEは設定も実行も手軽なので、特に便利な選択肢です。クラウドIDEのデメリットは、ネットに接続しないと使えないことです。最終的に何らかのクラウドIDEを使うことに決めたのであれば、「Run」ボタンをクリックしてから開きたいURLをクリックするだけでできます(図 1.12)。

訳注: WindowsのDOSプロンプト(DOS窓)は、一見Unixのコマンドラインと似ていますが、しくみや作法が大きく異なっているうえに、OSの深い部分に食い込んでいるため、Windows OSの構造やDOS特有の作法を知っておかないとUnix系のコマンドを動かすのに非常に手間取ります。幸い、最近はWindowsのWSL2という組み込みのLinux環境がかなりよくなってきていて、WSL2を愛用するプロ開発者も増えていますが、それでもクラウドIDEに比べると環境構築の難易度はまだ高いと言えるでしょう。

実は、ファイルをブラウザで開く方法はこの他にもいろいろあります。そのような方法を自力で見つけるのは、例の「技術の成熟」精神のよい例のひとつです(コラム 1.2)。

最後に、自分が使っているコンピュータのOSにも精通しておくと後々役に立ちます(特にUnixベースのOS、つまりmacOSやLinuxをお使いの場合)。開発環境を学ぶには今が絶好のチャンスです。

images/figures/open_html_cloud9
図 1.12: クラウドIDE(Cloud9)でHTMLファイルをブラウザ表示する

Git/GitHub編』や『HTML編』のときと同様に、新しいWebサイトを今すぐproduction(本番)環境にデプロイします(これを習慣づけておくのはよいことです)。まず、『HTML編』で解説したように、GitHubで新しいプロジェクトを作成します(コラム 1.6についても考慮しておきましょう)。この場合は図 1.13のような感じになります。

コラム 1.6. GitHubのデフォルトブランチ名について

2020年10月、GitHubから次のアナウンスがありました。新規作成されるリポジトリのデフォルトのブランチ名が、従来のmasterからmainに変更されたというものです。デフォルトブランチ名が変更された理由についてはWikipediaに譲りますが、masterもまだ広く使われているため、皆さんが今後ドキュメントや書籍などでmasterというブランチ名を見かけることもあるかもしれません。その場合は適宜mainに読み替えて理解すると良いでしょう。詳しくはブログ記事「Default Git Branch Name with Learn Enough and the Rails Tutorial(英語)」をご参照ください。

images/figures/new_repo
図 1.13: GitHubに新しいリポジトリを作成する

リポジトリの作成が終わったら、リスト 1.5のコマンドを実行して、Gitの初期化とデプロイを行います。

リスト 1.5: Deploying the initial site to GitHub pages.
$ git init
$ git add -A
$ git commit -m "Initialize repo"
$ git remote add origin <repo url>
$ git push -u origin master

リスト 1.5のコマンドが難しいと感じる場合は、今のうちに『Git/GitHub編』と、『HTML編』のプロジェクトを開始するをおさらいしておくとよいでしょう。なお、デプロイが成功したかどうかの確認については、演習問題に回します( 1.3.1)。

本チュートリアルでは折に触れてGitのコミットとデプロイを実行しますが、一般には自分のやりやすいタイミングで行っても構いません。『Git/GitHub編』と『HTML編』を学び終えた方(または元々Git操作に慣れている方)は、そろそろコミットとデプロイのタイミングを自分で決めて実行してもよい頃です。

1.3.1 演習問題

  1. 「<ユーザー名>.github.io/index.html」というURLをブラウザで開き、GitHub Pagesへのデプロイが成功したことを確認してください。このURLに含まれている「index.html」は省略可能かどうかをまず予想し、次に実際にやって確かめてください。

1.4 スタイル指定を始めよう

 1.2で解説したように、CSSはHTMLページの要素を「どんな外観で表示するか」「ページのどこに配置するか」を定義する方法です。CSSのスタイル指定は、「最初の宣言はどれか」「その要素は別の親要素の子要素か」「その親要素にはスタイルが適用されているか」「宣言の詳細度(specificity)は高いか低いか」といった点に基づいて、上位の要素のスタイルから下位の要素に伝搬(カスケード)されます。

ところで、今の説明に登場した「親」「子」「詳細度」は、Webページ上で何を指すのでしょうか?具体的にはこれらでどのようにスタイル指定が行われるのでしょうか?

ここで思い浮かべていただきたいのは、次の考え方です。ページ上のあらゆる要素は、マトリョーシカ人形のように「別の要素の内側に含まれる」こともあれば「別の要素をその内側に含む」こともあります(図 1.1416)。

images/figures/russian_dolls
図 1.14: マトリョーシカ人形は互いに入れ子にできるように作られている

親要素と子要素の典型的な関係(構造)は、図 1.15のようなチャートで表現できます。

images/figures/parent-child
図 1.15: 要素の親子関係は、常に上(親要素)から下(子要素)に向かって進む

図 1.15に示したタグの階層構造は、「DOM(Document Object Model)」と呼ばれます17。親子関係は相対的なので、DOMのある階層レベルは、その上の階層レベルから見ると「子」になりますし、その下の階層レベルから見れば「親」になります。この図をHTMLタグで説明すると、bodyタグはそのページ全体にとって「親」であり、bodyタグはhtmlタグから見れば「子」である、という具合に繰り返されます。bodyタグも独自の子をいくつか持っており、それぞれ見出しのh1要素とh2要素、順序なしリストのul要素、そしてdiv要素です。CSSでは、スタイル指定は「親から子へ」(図では上から下へ)と流れ落ちるように伝搬します。この流れ(フロー)は、他のスタイル指定に遮られるか、そのスタイルより詳細度の高いスタイルに出会うと、そこで終わります。

この考え方の最初の応用として、先ほどのサンプルページでインライン方式のスタイル指定が繰り返されている様子を観察しましょう。たとえば、ページにdiv要素がいくつかあり、どれもまったく同じボーダー(枠線)スタイルが指定されていることがわかります(リスト 1.6)。

サンプルコード内で縦に並んでいるドットは「コードの省略」を意味しますので、コピーしてはいけません。

リスト 1.6: DRY原則に違反するインライン方式の繰り返し index.html
.
.
.
<div style="border: 1px solid black;">
.
.
.
<div style="border: 1px solid black;">
.
.
.
<div style="border: 1px solid black;">
.
.
.

DRY原則については既にコラム 1.3で学んだので、この手の冗長なスタイル指定を目にしたプログラマーはお尻がムズムズして落ち着かなくなるはずです。このかゆみを癒やすには、重複を解消するに限ります。これから行う、コードの機能を変えずに形式を整える作業は「リファクタリング(refactoring)」と呼ばれます。言い換えると、このセクションをリファクタリングしてもブラウザ表示は変わらないはずです(し、変わってはいけません)。

コードをきれいにするために、 1.2で登場した内部スタイルシートを使うことにします。内部スタイルシートを実装するには、styleという新しいタグ(リスト 1.7)が必要です。このstyleブロックにはすべてのスタイル宣言を置きますが、styleタグはレンダリングされたページ上に表示されない仕様なので、ユーザーのブラウザ画面には表示されません。

リスト 1.7: ページに空のstyleブロックを置いた様子 index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Test Page: Don't Panic</title>
    <meta charset="utf-8">
    <style>

    </style>
  </head>
  .
  .
  .

styleブロックは、実はページのどこに置いても同じなのですが、慣例上はページのheadタグの内側が定位置です(本当はCSSスタイル指定は外部ファイルに置くのがベストプラクティスですが、これについては 5.5で行います)。

それではリスト 1.6の冗長な繰り返しを消し去りましょう。リスト 1.8のように最初のCSS宣言を追加します18

リスト 1.8: 最初のCSSスタイルを追加する index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Test Page: Don't Panic</title>
    <meta charset="utf-8">
    <style>
      div {
        border: 1px solid black;
      }
    </style>
  </head>
  .
  .
  .

図 1.16は、リスト 1.8のCSSスタイル指定を例に構文を示したものです。この構文で、山かっこ「{}」の外にあるdivの部分は「セレクタ(selector)」と呼ばれます。ここではHTMLのdiv要素だけがセレクタの対象になります。山かっこの内側には「宣言(declaration)」が1個あり、宣言の冒頭にあるborderは「プロパティ(property)」、プロパティの後ろはコロン:で区切られ、その後ろの1px solid blackはプロパティの「値(value)」です。そして宣言の末尾にはセミコロン;が置かれます。

これらの用語を適当に使う不注意な人をちょくちょく見かけます(セレクタを指して宣言と呼ぶなど)。皆さんは用語を正確に使ってくださいね。

images/figures/names
図 1.16: ジュリエット「名前なんか何だっていいじゃないの

リスト 1.8のコードのインデントにはスペース文字が使われていますが、CSSもまた、HTMLと同様にホワイトスペース(スペース文字や改行やタブの総称)ブラウザでは無視されます。しかしインデントがある方が人間にとって読みやすいので、常にインデントを整えておくのはよい習慣です(コラム 1.7)。

コラム 1.7. スタイルメモ: スタイル指定そのものの書式も整えよう

リスト 1.8のスタイル指定文は、以下のように1行にまとめても同じように機能します。

  div {border: 1px solid black}

場所も取らないので一見よさげに見えますが、CSSをこのような「ワンライナー」方式で書くことは避けておくべきでしょう。1行だけのときはよくても、スタイルを追加すればするほど読みづらさが倍増します。やはりワンライナーよりも、以下のように書式を整える方がずっと読みやすくなります。

  button {
    background-color: gray;
    border: 1px solid black;
    color: white;
    cursor: pointer;
    display: inline-block;
    font-family: "proxima-nova", "Proxima Nova",
                 sans-serif;
    font-size: 12px;
    font-weight: bold;
    letter-spacing: 0.15em;
    padding: 10px 15px;
    text-decoration: none;
    text-transform: uppercase;
    transition: all 0.1s linear;
  }

同じものをワンライナーに押し込めると、以下のような無残な結果になります。

  button { background-color: gray; border: 1px solid
  black; color: white; cursor: pointer; display:
  inline-block; font-family: "proxima-nova",
  "Proxima Nova",
  sans-serif; font-size: 12px; font-weight: bold;
  letter-spacing: 0.15em; padding: 10px 15px;
  text-decoration: none; text-transform: uppercase;
  transition: all 0.1s linear}

スタイル指定がぎっしり並んだページで「あのプロパティはどこだったかな?」と探し始めたときに、この無残なワンライナーを目にした人の気持を考えてみましょう。そのつらさは「悪夢」などというありきたりな言葉では到底説明しきれません。

CSSスタイル指定の書式について、もうひとつ心がけておきたい点は、スタイルのプロパティの並び順を常に「アルファベット順」に保つことです。アルファベット順を崩さないようにするのは一見面倒に思えますが、やがてスタイル指定がびっしり増えてくれば、どう考えてもアルファベット順の方が断然探しやすいことが身に沁みてわかってきます。いきあたりばったりに追加していてはこうはいきません。

ありがたいことに、たいていのテキストエディタには選択範囲を一発でアルファベット順に並べ替えてくれる機能があります。Sublime Textの場合は、行を選択してF5キー(Mac)かF9キー(Windows)を押せば一発で完了です。Atomなどの他のエディタにも、同じ機能が使えるパッケージがあるのが普通です。

さて、リスト 1.8のCSSを追加したら、4つのdivタグにあるstyle="border: 1px solid black;"属性をすべて削除します。削除後のコードはリスト1.9のようになるはずです。

リスト 1.9: ページ全体の表示は果たして変わるか変わらないか index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Test Page: Don't Panic</title>
    <meta charset="utf-8">
    <style>
      div {
        border: 1px solid black;
      }
    </style>
  </head>
  <body>
    <h1>I'm an h1</h1>
    <ul>
      <li>
        <a href="https://example.com/" style="color: red;">Link</a>
      </li>
      <li>
        <a href="https://example.com/" style="color: red;">Link</a>
      </li>
      <li>
        <a href="https://example.com/" style="color: red;">Link</a>
      </li>
    </ul>
    <h2>I'm an h2</h2>
    <div>
      <a href="https://example.com/" style="color: green;">I'm a link</a>
    </div>
    <div>
      <a href="https://example.com/" style="color: green;">I'm a link</a>
    </div>
    <div>
      <a href="https://example.com/" style="color: green;">I'm a link</a>
    </div>
    <div>
      <a href="https://example.com/" style="color: green;">I'm a link</a>
    </div>
  </body>
</html>

変更結果を保存して、ブラウザ表示を更新すると…ジャジャーン!期待どおり表示は元のままです。もし表示が変わってしまった場合は、ここまでの作業を再確認してみてください。

さて、ここでは何が変わったのでしょうか?htmlbodyの中にあるすべてのdivタグに対して、「幅1ピクセルの黒いsolidボーダー」を適用するようブラウザに指示するのに必要なCSSスタイルを、リスト 1.8で追加したこの宣言1個だけで指定できるのです(ピクセルについて詳しくは 3.3で扱います)。これによって、ページの見た目をまったく変えずに、コードをシンプルにできました。

何度も繰り返されているインライン方式のスタイル指定を1個のCSS宣言にまとめる方法がこれでわかったので、今度は同じことをliタグでもやってみましょう。リンクの色を赤くする指定をliタグから消し去るのです。変更後のサンプルページのコードはリスト 1.10のようになるはずです。

今度も、ブラウザ表示を更新したときに何も変わらないはずです。

ここまでの作業で、冗長な「インライン方式」のスタイルを頑張って消し去ったという大きな進捗が得られました。しかし下半分の緑色のリンク文字は、まだスタイル指定がインライン方式のままです。後に 1.5で学ぶ「CSSクラス」を使うのもひとつの手ですが、まずは通常のCSSセレクタだけでやれるかどうか試してみましょう。

下半分のリンクはdivタグの内側にありますが、先ほどリファクタリングした上半分のリンクはそうなっていません。こんなときは、CSS継承のネストを利用して、divタグの内側にあるリンクの色だけを変更するスタイルを定義します。これを行うには、リスト 1.11の定義をstyleブロックに追加してから、ページ下半分のリンクからインライン方式のスタイルを削除します。

追加後のテストページの完全なコードはリスト 1.12のようになるはずです。

最初よりもコードが随分すっきりしたと思いませんか?このようにコンテンツからスタイル指定を切り離すと、コードがうんと読みやすくなります。しかし勘のいい人は、ここで使った「対象を限定したスタイル指定」方法には問題があることにお気づきかもしれません。

つまりこういうことです。さしあたって今は問題は起きていなくても、今後このページにdivを追加したときに、たまたまその内側にリンクがあったら、意図に反してそのリンク文字まで緑色になってしまいます。つまり、ここで使ったdiv aというセレクタが大雑把すぎるのです。この問題については、この後の 1.5でCSSのidとクラスを使って、より詳細度の高いピンポイントのスタイル指定を追加する方法を扱う予定です。

1.4.1 演習問題

  1. これまで学んだ「他のオブジェクトの内側にあるリンクをスタイル指定の対象にする方法」を用いて、liの内側にあるリンクの色を変更してください。
  2. divの周囲にボーダー(枠線)を追加するのに用いられているのと同じスタイル指定方法を用いて、liの周囲にボーダーを追加してください。

1.5 CSSセレクタ

HTML編』を学んだ後、本チュートリアルをここまで進める間に学んだのは、今のところスタイル指定の対象を絞り込む基本的な方法だけでした。『HTML編』では、「要素を直接指定して」スタイルを追加する方法を学びましたが、実はこのように要素の種類を直接指定するナイーブな方法は効率が悪く、ちょっとしたことでスタイル指定が壊れてしまいます。本チュートリアルでは、これまでCSSをコンテンツから切り離して内部スタイルシートに配置する方法を用いましたが、divaといった大雑把なセレクタしか使われていません。このような大雑把なセレクタを使うと、当たり前ですがそのページ内にあるすべての同じ要素に一律に効いてしまうことが問題なのです。では、同じ要素すべてではなく「特定の要素」だけを狙い撃ちにしてスタイルを指定するにはどうすればよいでしょうか?

その方法は大きく2とおりに分かれます。

ひとつは「id(identification: 識別子)」セレクタを用いることで、ページ内の要素をたった1つだけ指定する方法です19

もうひとつは、「クラス(class)」セレクタを用いて、さまざまな要素をまとめて狙い撃ちする方法です。今度は、サンプルページのHTMLに後者の方法で要素指定を追加してみましょう。

idやクラスは、いずれも要素の「開始タグ」にのみ記述することにご注意ください(つまり閉じタグにはidやクラスを書きません)。また、idとクラスの書式は常に同じであることにもご注意ください。以下は、divタグにidとクラスを具体的に書いた例です。

<div id="foo" class="bar">
  .
  .
  .
</div>

idもクラスも、「キー」と「値」の組み合わせ、いわゆる「キーバリューペア」の書式で書かれていることがわかります。各キーの値は文字列(つまり引用符で囲まれる)であり、「id」や「クラス名」を表すラベルとして使われます。この場合、idというキーの値は"foo"classというキーの値は"bar"になります。

訳注: クラスの名前については「クラス名」と表記しますが、idはそれ自体が固有の名前なので、本チュートリアルでは「id名」とは表記せず単にidと表記しています(実際にはよく使われています)。

CSSは、idやクラス名の指定によって非常に大きな柔軟性を提供していますが、idやクラス名には以下のような機能上の制限や望ましい利用法がいくつかあります。

  • 制約: ひとつの要素にはidを1個しか使えません(同じ要素にidが複数あると動作が保証されなくなります)。
  • 制約: 名前の冒頭には数字を置けません(name1は有効ですが、1nameは無効であり、無視されてしまいます)。
  • オプション: 名前には「ダッシュ(-」「アンダースコア(_)」を使うこともできます(つまりfoo-bar-bazfoo_bar_baz、そしてFooBarBazのようなキャメルケースも使えます)20
  • 制約: idにはスペース文字を含められません。また、複数のクラス名を指定するときはスペース文字で区切ります(つまりid="foo bar"は無効ですが、class="foo bar baz"のように1つの要素で複数のクラスをスペース区切りで指定するのは有効です)21
  • 原則: 命名法は1つのプロジェクト内で統一すること(つまりダッシュ記号を区切りに使うと決めたら、そのプロジェクト内ではすべてそれに統一し、アンダースコア文字を混ぜるなどの不統一は避ける22

上述のようにダッシュ記号を実際に名前で使えることを確認するために、サンプルページにidやクラスをいくつか追加してみましょう。h2の直後にある最初のdiv開始タグにだけid="exec-bio"を追加し、そのセクションにあるdivには(最初のdivも含めて)すべてclass="bio-box"を追加します(リスト 1.13)。

リスト 1.13: サンプルページにCSSのクラスやidを追加する index.html
<!DOCTYPE html>
<html>
  .
  .
  .
  <body>
    .
    .
    .
    <h2>I'm an h2</h2>
    <div id="exec-bio" class="bio-box">
      <a href="https://example.com/">I'm a link</a>
    </div>
    <div class="bio-box">
      <a href="https://example.com/">I'm a link</a>
    </div>
    <div class="bio-box">
      <a href="https://example.com/">I'm a link</a>
    </div>
    <div class="bio-box">
      <a href="https://example.com/">I'm a link</a>
    </div>
  </body>
</html>

(このようなクラスの使い方はCSSにおける定番の良い手法ですが、idをこのような形で使うのは一般にはおすすめできません。ここで追加したidはあくまで動作をデモすることが目的です。これについては後に 2.2で詳しく解説します)

次にCSSブロックを更新し、今追加したidを新しいセレクタとして指定します。CSSでidを指定するには、セレクタでidの前に「番号記号#)」を置きます。CSSでクラスを指定するときは、セレクタでクラス名の前に「ドット(kode.)」を置きます。たとえば、#exec-bioというidを持つ要素の背景色を変更するには、以下のようなCSSスタイル指定を使えます23

#exec-bio {
  background-color: lightgray;
}

(なお、このlightgrayという値は文字どおり「明るい灰色」を表します24。これはCSSの「色名(color name)」の例です。色名について詳しくは後に 3.1で扱います)同様に.bio-boxクラスへの指定も追加すると25、以下のようなCSSになります。

.bio-box {
  border: 1px solid black;
}

この後確認しますが、上のCSSはリスト 1.9で追加した細くて黒いボーダーのスタイルを変えずにそのまま維持しています。しかし、このサイトのすべてのdivタグにスタイルが無条件に適用されるのではなく、class="bio-box"を持つdivタグにだけ適用されます。

最後に、クラス名とタグ名を以下の.bio-box aのように組み合わせると、「.bio-boxの内側にあるaタグだけ」を狙い撃ちしてスタイルを指定できます。

.bio-box a {
  color: green;
}

上のCSSはaタグのリンク文字を緑色に変えますが、緑色に変わるのは"bio-box"クラスを持つ要素の内側にある場合に限られます。このように、「基本的にクラスを使って要素を指定するアプローチ」の方が、リスト 1.11のときのような「クラスを使わずにタグ名だけを指定する大雑把なアプローチ」よりもずっときめ細かく制御できるようになります。

以上3つのスタイル指定をstyleブロックに追加し、不要になったスタイル指定を削除すると、リスト 1.14のようなマークアップになります。

リスト 1.14: クラスやidを対象とするCSSスタイル指定を追加する index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Test Page: Don't Panic</title>
    <meta charset="utf-8">
    <style>
      a {
        color: red;
      }
      #exec-bio {
        background-color: lightgray;
      }
      .bio-box {
        border: 1px solid black;
      }
      .bio-box a {
        color: green;
      }
    </style>
  </head>
  <body>
    .
    .
    .
    <h2>I'm an h2</h2>
    <div id="exec-bio" class="bio-box">
      <a href="https://example.com/">I'm a link</a>
    </div>
    <div class="bio-box">
      <a href="https://example.com/">I'm a link</a>
    </div>
    <div class="bio-box">
      <a href="https://example.com/">I'm a link</a>
    </div>
    <div class="bio-box">
      <a href="https://example.com/">I'm a link</a>
    </div>
  </body>
</html>

変更結果を保存してブラウザ表示を更新すると、画面の下半分にあるボーダーはこれまでとまったく同じですが、下半分の最初のリンクだけ明るい灰色の背景色が追加されているはずです(図 1.17)。

images/figures/selectors
図 1.17: クラスやidでスタイルを指定された要素

おめでとうございます!ここまでに、idやクラスを用いて特定の要素だけを狙い撃ちでスタイル指定する方法を学び、CSSの基礎知識もレベルアップしました。CSSの宣言を記述する方法やidやクラスの使い方を会得したので、次からはいよいよCSSのしくみの核心部分を解説します。

1.5.1 演習問題

  1. styleセクションのCSSに新しいidをひとつ追加し(名前は自分で決めること)、要素の背景色をorangeにするスタイルを指定したら、ページ内のリンクをひとつ適当に選んでそのidを追加し、結果をブラウザ画面で確認してみてください。
  2. styleセクションのCSSに新しいクラスをひとつ追加し(これも名前は自分で決めること)、セクションのCSSに新しいidをひとつ追加し(名前は自分で決めること)、要素の背景色をazureにするスタイルを指定したら、ページ内に4箇所ある.bio-boxの後ろに2番目のクラスとしてそのクラス名を追加し、結果をブラウザ表示で確認してみてください。今度はひとつのボックスだけ他と色が異なることがわかりますが、これについては今後 2.3で解説します。
  3. 本章での変更結果をGitでコミットし、GitHub Pagesにデプロイしてください。デプロイ先のGitHub Pagesでサイトが正しく表示されることも確認してください(キャッシュがクリアされるまで1〜2分ほどかかることもありますので、反映されるまでブラウザ表示を更新してみてください)。
1. 要素をブラウザ上でどのように配置するかなども定義に含まれます。
2. 辞書だけでスペイン語を学ぶのが大変なもうひとつの理由は、この図 1.1に隠されています。これはスペイン語ではなく、実際はカタルーニャ語で書かれています。
3. たとえばこんな人です。
4.技術的には」HTMLやCSSは宣言的な「マークアップ(markup)」であり、プログラミング言語の「コード(code)」ではありませんが、本チュートリアルでは特に、JavaScriptやRubyのようなプログラミング言語と同様にHTMLやCSSにも通用するコーディングの鉄則(繰り返しを避けるなど)を解説する場合に後者を用いることもあります。
5. 画像引用元: https://simple.wikipedia.org/wiki/File:Snowy-Owl.1.jpg(2017-05-01)、Copyright © 2011 by Bert de Tilly、クリエイティブ・コモンズ「表示 2.0 一般 (CC BY 2.0)」ライセンス条項に基づいて利用。
6. cascadeという言葉は元々「滝が何段にも積み重なること」「そのような滝のひとつの段」を意味しています(動画)。滝が上の段の水が下に落ちるように、CSSも上位のスタイル指定が下位の要素に伝搬します。
7. 画像引用元: https://www.flickr.com/photos/98317926@N04/14443589450(2017-05-01)、Copyright © 2014 by Tomi Lattu、クリエイティブ・コモンズ「表示 2.0 一般 (CC BY 2.0)」ライセンス条項に基づいて利用。
8. なお、現在transitionスタイル指定は既にすべての主要なブラウザでサポートされていますので、今後プレフィックス付きのスタイルを見かけたときに安全に削除できます
9. フロントエンド開発界隈で長く働いている人にこのあたりの昔話を聞いてみれば、IE6でスタイル指定の挙動が異なっていた2000年代前半の頃の、身の毛もよだつような話をいっぱい教えてくれることでしょう。ゲホ、ゲホ。
10. CanIUseは常に最新の情報が反映されており、多くのプロも使っている定番ツールのひとつです。ぜひ活用しましょう。
11. 画像引用元: https://commons.wikimedia.org/wiki/File:Figure_27_04_03.jpg(2017-05-01)、Copyright © 2014 by Rice University、クリエイティブ・コモンズ「表示 4.0 国際 (CC BY 4.0)」ライセンス条項に基づいて利用。
12. もしもInternet Explorer 6か7を使って何か開発して欲しいと依頼されるようなことがあったら、にっこり笑ってその場からダッシュで逃げるに限ります。Webサイトをこれらのブラウザで正しく表示することに頑張る価値はありません。まことにありがたいことに、これらのブラウザはこの世から無事消え去ってくれました
13. 画像引用元: https://commons.wikimedia.org/wiki/File:Swamp_water_landscape.jpg(2017-05-01)、パブリックドメイン
14. 画像引用元: https://commons.wikimedia.org/wiki/File:Battle_of_Shumen_Reenactment_2007.jpg(2017-05-01)、Copyright © 2014 by Daggerstab、クリエイティブ・コモンズ「表示 - 継承 3.0 非移植 (CC BY-SA 3.0)」ライセンス条項に基づいて利用。
15. Macユーザー向けのメモ:『CSS & Design編』を進めるうえでは特に問題にならないはずですが、できればシェルをBash(Bourne-again shell)に変更しておくことをおすすめします。 シェルをBashに切り替えるには、コマンドラインでchsh -s /bin/bashを実行し、パスワードを入力してから「ターミナル」アプリを終了し、再度起動すれば完了です。途中でいろいろなメッセージが表示されますが、無視しても大丈夫です。詳しくはLearn Enoughブログの記事「Using Z Shell on Macs with the Learn Enough Tutorials(英語)」をご覧ください。
16. 画像引用元: https://www.flickr.com/photos/joe57spike/5690570945(2017-02-18)、Copyright © 2011 by Joe Lodge、クリエイティブ・コモンズ「表示 2.0 一般 (CC BY 2.0)」ライセンス条項に基づいて利用。
17. DOMはそのまま「ドム」と読むのが普通です。英語的にはDOMとMom(マム)は韻を踏みます。
18. 簡単のため、リスト 1.8のようにコードの一部のみが引用されている場合は、インデントレベルが実際よりも浅くなることもあります。しかし(『HTML編』で解説したように)、このような場合は自力で適切なインデントレベルを設定してコードをきれいに保ってください。
19. identificationの略語は大文字の「ID」にするのが通例ですが、コンピュータの世界では小文字の「id」の方が一般によく使われます(なお英語圏では心理学用語の「自己同一性」紛らわしくなりますが)。理由は、現代のHTMLマークアップでは、大文字のDIVよりもdivのように小文字で表記する慣習が広く根付いているためです。
20. ここで言う「ダッシュ(-」は正確にはハイフンマイナスと呼ばれます。キーボード上のマイナス記号を押すことで入力されるマイナス記号にもこれが使われるので、基本的にはいわゆるマイナス記号と考えて構いません(間違えて日本語の長音「」を入力しないようご注意)。日本語圏ではほとんど意識されていませんが、Unicodeにはさまざまな長さのハイフンやダッシュ(短いen dashや長いem dashなど)が存在しており、アルファベット語圏を中心に実際に使われています。これらは見た目が似ていますので、特に外国語を扱う場合は取り違えないよう注意が必要です。
21. idやクラス名に日本語の文字などを使うことも一応可能ですが(ファイルがUTF-8でエンコードされている場合)、おそらくデメリットの方がはるかに大きくなる可能性が大きいので、やめておきましょう。
22. 現実のCSSでは、本チュートリアル同様foo-bar-bazのようにダッシュ記号を使う命名法がメジャーです(特にツールを用いて名前を自動生成する場合)。特別な理由がない限り、名前の区切りにはダッシュ記号を使いましょう。面白いことに、プログラミングの世界では変数名などにアンダースコア(_)区切りやキャメルケースがよく使われますが、HTMLやCSSの世界ではこれらを用いた命名は敬遠されています。おそらく、そうしておくことでプログラムでCSSの名前を扱うときに区別しやすいからでしょう。
23. 細かい話ですが、番号記号(# 井桁: 英語圏ではハッシュ記号とも呼ばれます)は、音楽の「シャープ記号」とは異なる記号です。しかし現実には俗にしばしば「シャープ」と呼ばれていますし、C#という言語名に使われているのは番号記号であるにもかかわらず「Cシャープ」と呼ばれています。
24. 日本人にはあまり関係ないかもしれませんが、CSSのこうした色名では米国風のスペル「gray」と英国風のスペル「grey」を両方サポートしています。aがAmerican、eがEnglishと覚えるとよいでしょう。
25. 本チュートリアルでは、クラス名を持つ要素を指すときに、それに対応するCSS記法(セレクタ)を多用します。つまり、単に.bio-boxと書いたときは「class="bio-box"を持つ要素を指す」ということです。
第1章 CSSのあらまし CSS & Design編