HTMLとCSSをもっと深く知る

概要

これまではHTML/CSSの入門編。ここからは「これ知ってたらとりあえず現場出れる」の知識。

最初に用意するもの

  • いつも通り「161108」という名前でフォルダをつくる
  • 中身はいつもどおりこんな感じ
    • 161108(フォルダ)
      • index.html(ファイル)
      • assets(フォルダ)
        • css(フォルダ)
          • app.css(ファイル)
        • images(フォルダ)
          • 前回使った画像1枚入れる

※assetsの中にindex.htmlを入れないように注意!

今回やりたいレイアウト

f:id:dorak:20161108095633p:plain

要点:

  • 画像を横並びにしたい
  • 画像と、画像のタイトルが1グループ

これを実現するには、今までの知識ではできない。 ので、新しいことを覚えます。

まず、簡単に実現方法。 下記をまるっとコピペしちゃってください。画像のところは適宜自分のファイル名に置き換え!

  1. HTMLを編集
<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>プロフィールページ</title>
  <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/3.18.1/build/cssreset/cssreset-min.css">
  <link rel="stylesheet" href="assets/css/app.css">
</head>
<body>

  <div class="work-list cf">

    <div class="work">
      <div class="work-image">
        <img src="assets/images/1.jpg">
      </div>
      <p class="work-text">ねこのイラスト</p>
    </div>

    <div class="work">
      <div class="work-image">
        <img src="assets/images/2.jpg">
      </div>
      <p class="work-text">人のイラスト</p>
    </div>

    <div class="work">
      <div class="work-image">
        <img src="assets/images/3.jpg">
      </div>
      <p class="work-text">死神のイラスト</p>
    </div>

  </div>

</body>
</html>
  1. CSSを編集
.cf:before,
.cf:after {
    content: " "; /* 1 */
    display: table; /* 2 */
}

.cf:after {
    clear: both;
}

.cf {
    *zoom: 1;
}

* {
  box-sizing: border-box;
}

html {
  background: #ddd;
}

.work-list {
  margin: 160px auto;
  width: 600px;
}

.work {
  padding: 0 16px;
  float: left;
  width: 33.333333%;
}

.work-image {
  width: 100%;
}

.work-image img {
  width: 100%;
}

.work-text {
  text-align: center;
}

ただimgタグを並べただけではこうなりません。 何故並ばないか。 それはHTMLの成り立ちがふかーく影響しています。

HTMLのタグを覚える

HTMLのタグとは、

div
p
meta
img
span

みたいなやつで、<p>こんにちは</p>みたいなやつでした。 実はこのHTMLタグって種類があります。

それが「ブロック要素」と「インライン要素」。

タグには「種類」がある

なぜタグに種類があるかというと、そもそもHTMLがどうしてできたのか、に遡ります。

要点は

  • HTMLは、もともと研究論文などを共有したいという要求から産まれた
  • なので、論文を書くためのプログラム言語
  • 論文の成り立ちを考えれば、HTMLタグの種類が分かる

そもそも研究者がデザインされていない文章(科学論文とか)を共有するためです。なので、ワードみたいに文章が作れれば十分でした。 そういったことから、HTMLをつくったエンジニアは、タグをブロック要素とインライン要素で分けました。 ブロック要素は、いわゆる文章の段落です。文書のかたまりです。 インライン要素は、文章の中の単語や文章を装飾するためのもの(赤字にしたり、太字にしたり、斜体にしたり)です。

f:id:dorak:20161108101141j:plain

ワードとかで文章を作った人はよく思い出してみてください。 段落同士が並ぶことはあまりなかったと思います。

ということで、ブロック要素は段落なので、ブラウザの横幅いっぱいに広がります。 HTML的には、幅いっぱいに広がるので、前後の要素がそのブロック要素と並ぶことはありません。 Photoshopで言うなら、キャンバス幅いっぱい四角をつくってるようなものです。

インライン要素は、コンテンツ分の幅しかありません。 <span>はろー</span>というタグがあった時、はろー分しか幅が与えられないです。何故かと言うと、段落の中の文章や単語を装飾するための要素だからです。 繰り返しになりますが、ブロック要素は、たとえ<div>はろー</div>という文章が極端に短いものでも、div自体が段落なのでブラウザの幅とイコールの幅を持ちます。

つまりブロック要素 = 段落

ブロック要素は、div, pなど。

つまりインライン要素 = 文の一部(単語とか)

インライン要素は、a, img, spanなど。

手を動かして確認してみよう

話を戻して、なぜimgタグを並べただけでは並ばないのかを見ていきます。

まずは、これまでの知識でやってみる

  1. index.htmlを開く
  2. index.htmlのbodyタグの中身を全部消す
  3. app.cssを開いて、中身を全部消す
  4. bodyタグの中身に以下を入力する
<div class="work-list">
  <img src="assets/images/1.jpg">
  <img src="assets/images/2.jpg">
</div>

f:id:dorak:20161108111127p:plain

これは、ただ画像を入れただけ。ちゃんと並んでるけど、今回は、画像に加えて画像のタイトルを入れたいので、これだと不十分。なので、上のHTMLに対して画像のタイトルを入れる。

<div class="work-list">
  <img src="assets/images/1.jpg">
  <p>ねこのイラスト</p>
  <img src="assets/images/2.jpg">
  <p>人のイラスト</p>
</div>

f:id:dorak:20161108111217p:plain

はい。さっきまでさっきまで並んでいたのに、並ばなくなってしまった。 何故かと言うと、この画像を思い出して欲しいです。 f:id:dorak:20161108101141j:plain

imgだけだったらインライン要素なので並んでいたけど、pタグはブロック要素なので、幅いっぱいに広がってしまう特徴を持っています。例えるなら段落だから。なので、

これだと、うまく並ばない。 なぜなら、画像とタイトルがグループになっていないから。 なので、グループをつくる

<div class="work-list">

  <div class="work">
    <img src="assets/images/1.jpg">
    <p>ねこのイラスト</p>
  </div>
  
  <div class="work">
    <img src="assets/images/2.jpg">
    <p>人のイラスト</p>
  </div>

</div>

はい。 どうでしょう。 見た目が変わりません。

f:id:dorak:20161108111217p:plain

何故か。 並ばせたいのは,.workクラスがついている要素。 けど、workクラスがついた要素は、divなのでブロック要素。 つまり、段落なので、幅いっぱいに広がるのです。

ということは、段落状態を解除して並ばせる必要があります。

それはCSSで指定します。その名もfloat: left;

さっそくやってみましょう。

app.cssを開いてください。まずは以下をコピペ。

.cf:before,
.cf:after {
    content: " "; /* 1 */
    display: table; /* 2 */
}

.cf:after {
    clear: both;
}

.cf {
    *zoom: 1;
}

* {
  box-sizing: border-box;
}

html {
  background: #f4f4f4;
}

次に、並ばせたい要素に対してfloat: left;を指定してあげましょう。 書く場所はファイルの一番下。

.work {
  float: left;
}

はい、どうでしょう。 並びましたか。 以下のようになってるはずです。

f:id:dorak:20161108111804p:plain

さてここまできたらあとは簡単です。

もともとやりたかったのがこれ↓なので、

f:id:dorak:20161108095633p:plain

さくっとやってみましょう。

まずは、画像と画像の間に余白をとりましょう。 さっき.workクラスの指定を書いたので、付け加えるだけでOKです。

.work {
  float: left;
  padding: 0 16px;
}

f:id:dorak:20161108112212p:plain

はい余白があきました。

次。 画像たちを中央に揃えてあげましょう。 中央に揃えるのは、work-listクラスに対してtext-align: center;...と言いたいとこですが、text-align: centerはインライン要素に対してのみ有効な指定です。work-listはdivなのでブロック要素なので効きません。なぜなら、ブロック要素は画面いっぱいに広がるので、すでに中央になってるようなもんです。

f:id:dorak:20161108112958j:plainf:id:dorak:20161108113004j:plain

じゃあどうやって揃えてやるかというと、画面幅よりも小さいサイズにしてあげて、左右に均等に余白をつくればいいんです。

f:id:dorak:20161108113004j:plain

どう書くか。

.work-list {
  width: 60%;
  margin: 0 auto;
}

これでOKです。

f:id:dorak:20161108122413p:plain

どうでしょう。微妙に真ん中に寄ってません。 これはなんでかというと...

f:id:dorak:20161108124006p:plain

これを見てください。 オレンジ色の部分が余白、青い部分がコンテンツの幅です。今は、.work-listの幅が全体に対して60%に設定されてるのでこんな感じの幅になってます。青い部分を見てもらって分かるように、.work-list自体はもう中央に寄ってます。

なんで中央に寄ってない(ように見える)のかと言うと、 中の画像の大きさが、足しても.work-list分の幅に足りないからです。

ということで、足して100%にしてあげましょう。

中の画像の大きさは.workなので、CSSは以下。

.work {
  float: left;
  padding: 0 16px;
  width: 50%;
}

はい。width: 50%;を足しました。これなんで50%かわかりますか? 今は画像のグループが2つなので50%です。足して100%。すると、.work-listの大きさと同じになります。 画像が4つだった場合はwidthをいくつにすればいいでしょうかね? はい、てことでどうでしょうか。見事真ん中になりました。 いやー真ん中にするって大変ですね。Photoshopなどもこんなことを内部でやってるんですよ。

f:id:dorak:20161108125104p:plain

はい。てことで、 今回は色々HTMLを深く学びました。 今度は、何も見ずにこれを実装してみてください。

f:id:dorak:20161108095633p:plain

回答

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>プロフィールページ</title>
  <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/3.18.1/build/cssreset/cssreset-min.css">
  <link rel="stylesheet" href="assets/css/app.css">
</head>
<body>

  <div class="work-list cf">

    <div class="work">
      <div class="work-image">
        <img src="assets/images/1.jpg">
      </div>
      <p class="work-text">ねこのイラスト</p>
    </div>

    <div class="work">
      <div class="work-image">
        <img src="assets/images/2.jpg">
      </div>
      <p class="work-text">人のイラスト</p>
    </div>

    <div class="work">
      <div class="work-image">
        <img src="assets/images/3.jpg">
      </div>
      <p class="work-text">死神のイラスト</p>
    </div>
  </div>

</body>
</html>
.cf:before,
.cf:after {
    content: " "; /* 1 */
    display: table; /* 2 */
}

.cf:after {
    clear: both;
}

.cf {
    *zoom: 1;
}

* {
  box-sizing: border-box;
}

html {
  background: #f4f4f4;
}

.work-list {
  margin: 160px auto;
  width: 600px;
}

.work {
  padding: 0 16px;
  float: left;
  width: 33.333333%;
}

.work-image {
  width: 100%;
}

.work-image img {
  border: 16px solid #fff;
  width: 100%;
}

.work-text {
  text-align: center;
}