2013年6月3日月曜日

HTML の「ブロックレベル、インライン要素」内における改行は空白となる場合がある

1. 「ブロックレベル要素」と「インライン要素」の違い

HTML のタグには「ブロックレベル要素」と「インライン要素」がある。

7.5.3 ブロックレベル要素と行内要素 によると、

HTMLの要素のうち、BODY要素に出現し得る要素のあるものは「ブロックレベル」と呼ばれ、他のものは「行内」 (これは「テキストレベル」としても知られている)と呼ばれる。

大雑把に言えば、ブロックレベル要素とインライン要素-HTMLの基本 によると、

ブロックレベル要素には、以下のものがあります。

<address>、<blockquote>、<center>、<div>、<dl>、<fieldset>、<form>、<h1>-<h6>、
<hr>、<noframes>、<noscript>、<ol>、<p>、<pre>、<table>、<ul>

インライン要素には、以下のものがあります。

<a>、<abbr>、<acronym>、<b>、<basefont>、<bdo>、<big>、<br>、<cite>、<code>、<dfn>、
<em>、<font>、<i>、<img>、<input>、<kbd>、<label>、<q>、<s>、<samp>、<select>、
<small>、<span>、<strike>、<strong>、<sub>、<sup>、<textarea>、<tt>、<u>、<var>

この2つの要素には「配置のルール」が存在する。

ブロックレベル要素の中には、他のブロックレベル要素やインライン要素を配置することができます。

一方、インライン要素の中には、文字データや他のインライン要素を配置することができますが、 インライン要素の中にブロックレベル要素を配置することはできません。

(同上より)

詳しくは、HTML 4 Document Type Definition を参照。

<!--
    HTML has two basic content models:

        %inline;     character level elements and text strings
        %block;      block-like elements e.g. paragraphs and lists
-->

上記の読み方は、Document Type Definition – Wikipedia を参考に。

 

2. HTML における改行、空白文字の扱われ方

a. インライン要素に改行を入れてしまった場合

注意することは、「改行」や「空白文字」の扱われ方。

例えば、インライン要素である a タグの中に span タグを、次のように配置してみる。

<div>
	<a href="">
		<span>
			ほげ
		</span>
	</a>
</div>
<div>
	<a href=""><span>ぴよ</span></a>
</div>
<div>
	<a href=""><span>ふが</span></a>
</div>

SnapCrab_No-0239ブラウザ(Firefox 21)に表示される「ほげ ぴよ ふが」の文字は、一見変わらないように見える。しかし、ソースを表示すると、「ほげ」と入力した文字の周囲に空白が表示されている。

Firefox 上で文字をコピーし、テキストエディターに貼り付ければ、空白があるのが分かる。ただし、ブラウザによって、コピーされた内容が異なる。Google Chrome 27, IE 10 では全く違う。

このように「空白」が表示される理由は、「インライン要素」に「改行」が含まれているため。

ブロックレベル要素とインライン要素 - Web標準普及プロジェクト > インライン要素 によると、

要素中に改行が混じるとやや複雑な形で表示されます。 これはインライン要素によって生成されるボックスは改行によって複数に分割されることがあるためです。

この場合、整形するつもりで、誤ってインライン要素である span タグ内に改行を2つ入れてしまった。そのため、改行が空白に変換された。

		<span>
			ほげ
		</span>

 

b. 改行が空白になる仕様

改行が空白に解釈される理由は、仕様による。

9.1 空白類 によると、

HTMLでは、次に挙げる文字だけが空白類文字であると定義される。

  • ASCIIスペース (&#x0020;)
  • 水平タブ (&#x0009;)
  • 書式送り (&#x000C;)
  • ゼロ幅スペース (&#x200B;)

行区切り類もまた、空白類文字である。

9.3.2 行区切り類の制御

1つの行区切りは、1つの復帰 (&#x000D;)か、1つの改行 (&#x000A;)か、1つの復帰/改行組であると定める。すべての行区切り類は、空白類である。

 

3. ブロックレベル要素内における改行

ブロックレベル要素でも、改行に注意しなければならない。改行が空白となる場合がある。

落とし穴になる空白文字と改行文字 によると、

以下のHTMLファイル(かなり簡略化してある)は2段落のテキストを表示する。表示後の見かけは段落ごとに同じか、違うか。違う場合はどこが違うか。

1: <html>
2: <body>
3: <p>abcdef</p>
4: <p>abc
5: def</p>
6: </body>
7: </html>

何が問われているのかピンとこなかった人は、少し考えてみよう。

正解は、「表示後の見かけは違う」「相違点は2段落目のcとdの間に空白が挿入されている」というものだ。

なぜ、こういう動作になるのかは、英語テキストを頭に描いてみれば分かるだろう。例えば、以下の2行があったとしよう。

1: The Extensible Markup Language (XML) is a subset
2: of SGML that is completely described in this document.

1行目のsubsetと2行目のofを結合するときには、そのまま結合して"subsetof"としてはおかしくなる。ここは単語の区切りなので、空白文字を入れねばならない。つまり、HTMLでは、改行は空白文字に等しい扱いを受けているのである。ただしここで補足しておくと、日本語などの文字を区切る改行は、空白扱いしないのが現在のHTMLである。

 

改行が問題とならない場合

ただし、ブロックレベル要素を見やすいように整形しても「空白」が入らない。

[HTML] ソース上の改行・タブ・空白(スペース)の扱い――インライン要素とブロック要素 | Ouka Studio

インライン要素以外の要素(ブロックレベル要素など)では、開始タグと終了タグそれぞれの前後の改行・タブ・半角スペースは、すべて無視される

よって、以下の整形は問題とならない。インライン要素とは異なることに注意する。

<div>
	<a href=""><span>ぴよ</span></a>
</div>

HTML における「空白」の仕様は、以下を参照。

 

4. 画像における空白

a タグimg タグを組み合わせるときは、特に注意が必要。両者とも「インライン要素」に分類されるため、上記の span タグと同じ扱いにしなければならない。

<div>
	<a href="">
		<img src="http://goo.gl/FgON8" alt="メニュー1">
	</a>
</div>
<div>
	<a href=""><img src="http://goo.gl/1SIHV" alt="メニュー2"></a>
</div>
<div>
	<a href=""><img src="http://goo.gl/5WFw0" alt="メニュー3"></a>
</div>

Firefox 21 で表示したところ、1番目と2番めの画像の間に隙間ができてしまった。

SnapCrab_No-0242

ただし、ブラウザによって表示が異なる。Google Chrome 27 では隙間ができない。

IE 10 では、画像にアンカーが付いていることを示すために枠が表示され、その分全体の高さが長くなる。ただし、1番目と2番目の画像に隙間はないようだ。

SnapCrab_No-0246

これに対して、HTML ソースの改行を半角スペースにしない方法 : full of universe には、以下の2つ書き方が述べられている。

タグ「後」の改行が表示されるんだったら、タグ「中」で改行してしまえ、という方法。

改行なんてコメントアウトしてしまえ、という方法。

しかし、どうもすっきりしないなぁ。。

タグの属性ごとに改行して書くことがある。属性が 0 個だと考えて、次のように記述するのも… うーん。

<ul>
	<li
		>1</li><li
		>2</li><li
		>3</li><li
		>4</li><li
		>5</li>
</ul>

 

参考サイト