サブカテゴリーリストを定義型リストでマークアップする
Movable Type の、2階層のサブカテゴリーリストで、定義型リスト(dl/dt/dd:または定義リスト)によるマークアップを実現する方法です。ここでは Movable Type によるカスタマイズを記していますが、定義型リストの使い方の参考にもなると思います。
以前、ご質問を頂いたもので、本エントリーで情報展開しておきます。
1.完成例
親カテゴリーに dt 要素、子カテゴリーは全体を dd 要素で括った後、順不同リスト(ul/li)でリスト表示します。
<dl>
<dt>親カテゴリーA</dt>
<dd>
<ul>
<li>子カテゴリーA-1</li>
<li>子カテゴリーA-2</li>
<li>子カテゴリーA-3</li>
</ul>
</dd>
<dt>親カテゴリーB</dt>
<dd>
<ul>
<li>子カテゴリーB-1</li>
<li>子カテゴリーB-2</li>
<li>子カテゴリーB-3</li>
</ul>
</dd>
</dl>
ちなみに、上のリストを順不同リストで表現すると、次のようになります。
<ul>
<li>親カテゴリーA
<ul>
<li>子カテゴリーA-1</li>
<li>子カテゴリーA-2</li>
<li>子カテゴリーA-3</li>
</ul>
</li>
</ul>
<ul>
<li>親カテゴリーB
<ul>
<li>子カテゴリーB-1</li>
<li>子カテゴリーB-2</li>
<li>子カテゴリーB-3</li>
</ul>
</li>
</ul>
2.サブテンプレート
上記を実現するサブテンプレートは次のようになります。
<dl>
<MTTopLevelCategories>
<MTSubCatIsFirst><MTHasNoParentCategory><MTElse><dd><ul></MTHasNoParentCategory></MTSubCatIsFirst>
<MTIfNonZero tag="MTCategoryCount">
<MTHasNoParentCategory>
<dt><a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>"><MTCategoryLabel></a> [<$MTCategoryCount$>]</dt>
<MTElse>
<li><a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>"><MTCategoryLabel></a> [<$MTCategoryCount$>]
</MTHasNoParentCategory>
<MTElse>
<MTHasNoParentCategory>
<dt><MTCategoryLabel></dt>
<MTElse>
<li><MTCategoryLabel>
</MTHasNoParentCategory>
</MTIfNonZero>
<MTSubCatsRecurse>
<MTHasNoParentCategory>
<MTElse>
</li>
</MTHasNoParentCategory>
<MTSubCatIsLast><MTHasNoParentCategory><MTElse></ul></dd></MTHasNoParentCategory></MTSubCatIsLast>
</MTTopLevelCategories>
</dl>
余談ですが、定義型リストによるマークアップは、以前行われた「コーディングコンテストVol.1」で最優秀賞を獲得された、「TOTOCO.ORG」さんのマークアップで利用されていて、審査員の方から「dl要素の使い方が良い」と、高い評価を受けています。
下の画面がコンテストで最優秀賞を得たサイトです。ブラウザから[表示]-[ページのソース]でマークアップをみることができます。
例えば、グローバルナビゲーションは次のようなマークアップです(一部省略しています)。
<dl id="globalNav">
<dt>主なカテゴリー</dt>
<dd>
<ul>
<li><a href="index.html"><img src="nav_home_cr.gif" alt="ホーム" width="98" height="54" /></a></li>
<li><a href="service/index.html"><img src="nav_biz.gif" alt="事業内容" width="98" height="54" /></a></li>
<li><a href="products/index.html"><img src="nav_products.gif" alt="製品情報" width="98" height="54" /></a></li>
<li><a href="recruit/index.html"><img src="nav_recruit.gif" alt="採用情報" width="98" height="54" /></a></li>
<li><a href="about/index.html"><img src="nav_about.gif" alt="会社概要" width="98" height="54" /></a></li>
<li><a href="contact/index.html"><img src="nav_contact.gif" alt="お問い合わせ" width="99" height="54" /></a></li>
</ul>
</dd>
</dl>
dt 要素は、次のCSSで非表示になっています(セレクタ名は一部省略)。
dl#globalNav dt{
position:absolute;
overflow:hidden;
width:0;
height:0;
}
丁度この時執筆していた、「Movable Type WEBデザインの新しいルール」のグローバルナビゲーションのカスタマイズにも、この定義型リストによるマークアップを利用させていただきました。
XHTML の「タグ」と「要素」の違いと正しい使い方
先日公開した XHTML タグ一覧表示ツールの中の説明で、「<br /> は空タグではありません」というご指摘を頂きました。勉強不足だったことを反省して、改めて XHTML の「タグ」と「要素」の違いや使い方について調べてみました。
まず、W3C で公開されている「XHTML 1.0」の仕様は下記です。
- XHTML? 1.0 The Extensible HyperText Markup Language (Second Edition)
- XHTML? 1.0: 拡張可能ハイパーテキストマークアップ言語
上記の「4. Differences with HTML 4(HTML4との相違点)」に
Well-formedness is a new concept introduced by [XML]. Essentially this means that all elements must either have closing tags or be written in a special form?(整形式性は、[XML] によって導入された新しい概念である。本質的には、これは、すべての要素が終了タグを持つか(後述のとおり)特殊な形式で書かれるかしなければならず、?)
とあり、XML の仕様を参照するようになっています。「XML 1.0」の仕様は下記です。
和訳は「W3C勧告 1998年2月10日」版のものですが、以降で参照する部分に差分はないと思います。
XML 1.0 仕様の「3. Logical Structures(論理構造)」に解説がありますので、そこから理解した内容を記したいと思います。認識に誤りがありましたらご指摘ください。
要素(Element)
要素の論理構造 *1 は下記の通りです。
[39] element ::= EmptyElemTag
| STag content ETag [WFC: Element Type Match]
[VC: Element Valid]
ここから「要素」という用語が示すのは「空要素タグ(EmptyElemTag)」、または「開始タグ(STag)+要素の内容(content)+終了タグ(ETag)」ということになります。
例えば「body 要素」と言えば「<body>~</body>」全体を指します。
開始タグ(Start-tag)
開始タグの論理構造は下記の通りです。
[40] STag ::= '<' Name (S Attribute)* S? '>' [WFC: Unique Att Spec]
[41] Attribute ::= Name Eq AttValue [VC: Attribute Value Type]
[WFC: No External Entity References]
[WFC: No < in Attribute Values]
Name(名前)、または0個以上の属性名と属性値の対を '<' と '>' で括ったものが「開始タグ」です。「body 要素の開始タグ」と言えば「<body class="hogehoge">」を指します。
終了タグ(End-tag)
終了タグの論理構造は下記の通りです。
[42] ETag ::= '</' Name S? '>'
Name(名前)を '</' と '>' で括ったものが「終了タグ」です。「body 要素の終了タグ」と言えば「</body>」を指します。
要素の内容(Content of Elements)
要素の内容の論理構造は下記の通りです。
[43] content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)* /* */
ある要素の、開始タグと終了タグの間にあるテキストを、その要素の「内容」と言います。「<body>?<body>」で例えると、 "?" の部分が「body 要素の内容」となります。
空要素のためのタグ(Tags for Empty Elements)
空要素のためのタグの論理構造は下記の通りです。
[44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>' [WFC: Unique Att Spec]
Name(名前)、または0個以上の属性名と属性値の対を '<' と '/>' で括ったものが「空要素タグ(Empty-element tags)」です。「空要素タグ」は内容をもたない要素に使用することができます。
先の「要素」の論理構造より、要素は空要素タグに等しいので、「br 要素」と言えば、「<br />」全体を指します。
その他
補足として、XHTML? 1.0 The Extensible HyperText Markup Language (Second Edition)の「C. HTML Compatibility Guidelines(HTML互換性ガイドライン)」より引用しておきます(「XHTML? 1.0: 拡張可能ハイパーテキストマークアップ言語」より引用)。
C.2 空要素
たとえば <br /> や <hr />, <img src="karen.jpg" alt="Karen" /> といったように、空要素の末尾の / と > との前にスペースを1個組み込むこと。また、たとえば <br /> といったように、空要素には最小化タグ文法を使うこと。これは、XMLで許容されている代わりの文法 <br></br> は、多くの既存のユーザエージェントでは与えられる結果が一定しないからである。
C.3 要素最小化と空要素内容
内容モデルが EMPTY ではない要素に空インスタンスが与えられる場合(たとえば空のタイトルや段落)には、最小化形式は使わないこと(たとえば <p /> は使わず <p> </p> を使う)。
まとめ
用語とマークアップ例の対応は下記の通りです。赤色(または強調文字)が対応部分です。*2
- 要素:<body>~</body>
- 開始タグ:<body>?</body>
- 終了タグ:<body>?</body>
- 内容:<body>?</body>
- 空要素タグ:<br />
上記より、「タグ」という定義には3種類しか存在ないため、「body 要素の開始タグ」や「body 開始タグ」という用い方が適切で「body タグ」や「br タグ」という使い方は(仕様的に)適切でないように思われます。
しかし日本では「ウェブサイト」を「ホームページ」と呼ぶのが一般的である(あった?)ように、「要素」や「内容」の代わりに「タグ」を用いるのが定着した用法になってしまっています。
それは、google サジェストやキーワードアドバイスツールで「XHTML」を入力すると「タグ」が上位に表示されることからも明らかです。また「はてなダイアリー:キーワード:タグ」には「開始タグと終了タグをまとめて『タグ』と呼ぶ」と書かれています。たしかにそういう意味合いで使われているケースが多いのではないでしょうか。
このエントリーではそこに言及するつもりはありません。少なくとも私自身が過去の記事や初心者の方からの質問の回答で「タグ」を多用しています(「開始タグ・終了タグ」は最近使うようになりました)ので、まずは今回勉強した内容を記事に活かせるよう、気をつけたいと思います。
*1:論理構造の記法にはBNF(バッカス・ナウア記法)が使用されています。詳細は「BNF記法入門(1) ─XML関連仕様を読むために─」が参考になるでしょう。
*2:色覚障害等で色が識別できない場合は、サイト右上の「Styles」メニューにある Gray Scale をクリックしてください。赤色部分が二重下線で表示されます(IEではグレースケール表示になります)。
XHTMLタグ一覧表示ツール
XHTMLタグを書く時の参考用ドキュメントとして、シンプルなツールを作ってみました。
ページに表示されている要素(タグ)をクリック(またはマウスオーバー)すると、その下にクリックした要素の子要素と親要素、および属性を表示します。要素の意味や具体的な使い方については一切触れていません。
今のところ XHTML 1.0 Transitional と XHTML 1.0 Strict を対象にしています。XHTML 1.1 もそのうち追加する予定です追加しました。
XHTML 初心者の方向けに、ページ一番下にXHTMLの規則も列挙しています。
Flash のブログパーツを XHTML valid にする
ブログパーツやブログペットで Flash を利用されている方は多いと思いますが、Flash のコードには embed 要素が含まれており、この要素が含まれているページは XHTML valid となりません。
Another HTML-lint gateway でチェックすると下記のようなエラーになります。
7: line xx: <embed> は Mozilla、MSIE または doti 用のタグです。 → 解説 55
7: line xx: </embed> は Mozilla または MSIE 用のタグです。 → 解説 55
この問題についてご質問を頂いたので、ネットを調べていたところ、下記の記事がありました。
Hotwired Japan:ウェブ標準のフラッシュ・オブジェクト自在術:embedタグとobjectタグ/救世主JavaScript参上
要するに JavaScript を用いて Flash のコードを表示させればよい、ということです。
上記の記事に書かれている方法が分かりにくい場合、次のようにすると良いでしょう。ここでは Kinarie&May さんの Flash カレンダーを例に変更方法を説明します。
この Flash カレンダーは、配色やURL等の必要な情報を入力して Flash のコードを生成した後、下記のコードを Movable Type のテンプレートに直接貼り付けます。
修正前
<OBJECT classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000' codebase='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0' WIDTH='130' HEIGHT='130' id='calender' ALIGN=''> <PARAM NAME=movie VALUE='http://n_calendar200.swf?xmlURL=http://hogehoge.com&katachi=1&monthMoveColor=ff6600&entryDayColor=ffff99&todayColor=ff9900&title_d=1'> <PARAM NAME=quality VALUE=high> <PARAM NAME=bgcolor VALUE=#ffffff> <EMBED src='http://n_calendar200.swf?xmlURL=http://hogehoge.com&katachi=1&monthMoveColor=ff6600&entryDayColor=ffff99&todayColor=ff9900&title_d=1' quality=high bgcolor=#ffffff WIDTH='130' HEIGHT='130' NAME='calender' ALIGN='' TYPE='application/x-shockwave-flash' PLUGINSPAGE='http://www.macromedia.com/go/getflashplayer'></EMBED></OBJECT>
このコードをテンプレートにそのまま貼り付けると XHTML valid とならないため、下記のような修正を加えます。
修正後(青色を追加)*1
<script type="text/javascript">
<!--
document.write('<OBJECT classid=¥'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000¥' codebase=¥'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0¥' WIDTH=¥'130¥' HEIGHT=¥'130¥' id=¥'calender¥' ALIGN=¥'¥'> <PARAM NAME=movie VALUE=¥'http://n_calendar200.swf?xmlURL=http://hogehoge.com&katachi=1&monthMoveColor=ff6600&entryDayColor=ffff99&todayColor=ff9900&title_d=1¥'> <PARAM NAME=quality VALUE=high> <PARAM NAME=bgcolor VALUE=#ffffff> <EMBED src=¥'http://n_calendar200.swf?xmlURL=http://hogehoge.com&katachi=1&monthMoveColor=ff6600&entryDayColor=ffff99&todayColor=ff9900&title_d=1¥' quality=high bgcolor=#ffffff WIDTH=¥'130¥' HEIGHT=¥'130¥' NAME=¥'calender¥' ALIGN=¥'¥' TYPE=¥'application/x-shockwave-flash¥' PLUGINSPAGE=¥'http://www.macromedia.com/go/getflashplayer¥'></EMBED></OBJECT>');
//-->
</script>
ご覧の通り、Flash のコード全てを、JavaScript の document.write('?') という「?」に収めます。Flash のコードに含まれる全てのシングルクォート(')はエスケープ(¥ またはバックスラッシュを付与)してください。これは document.write で使用されるシングルクォートでないことを示すためです。
上記の修正を実施して正常に表示されるところまでは確認できました。表示されない場合はエスケープがきちんとできていない可能性があります。Firefoxの[ツール]-[JavaScriptコンソール]でエラーが発生していないか確認しましょう。
*1:色覚障害等で色が識別できない場合は、サイト右上の「Styles」メニューにある Gray Scale をクリックしてください。IEではグレースケール表示され、青色部分が下線表示、赤色部分が二重下線で表示されます。Firefox/Opera ではカラー表示のままですが下線表示に切り替わります。なお設定の都合上、リンクとテキスト表示が判断できなくなりますので予めご容赦ください。
ブロックレベル要素とインライン要素
ウェブスタンダードなエントリーを書くための基礎知識です。タイトルについて、他に詳しく書かれたサイトが色々ありますが、当サイトでもまとめて記しておきたいと思います。
HTML要素の構造
HTML文書は一つのhtml要素からなります。さらに html要素は head 要素と body 要素からなります。そして、body 要素の中で使える要素(タグ)は大きく「ブロックレベル要素」と「インライン要素」の二つに分類することができます。
ブロックレベル要素
「ブロックレベル要素」とは、見出し(h1?h6)・段落(p)・リスト(ul/ol )・テーブル(table)など、文書の基本的な構造を示すものです。その名の通り「ブロック(矩形)」として、要素の前後に改行を伴った表示がされます。
ブロックレベル要素の主なタグは次の通りです。
- p / h1?h6 / ul / ol / dir / pre / dl / div / noscript / blockquote / form / hr / table /fieldset / adress
インライン要素
「インライン要素」は強調文字(strong)・リンク(a)といったテキストに装飾をしたり機能をもたせる、あるいは改行(br)のようにテキスト内のある部分に対して何らかの意味づけをしたりする機能を持たせるものです。インライン要素の前後には改行は含まれません。*1
インライン要素の主なタグは次の通りです。
- i / b / u / s / em / strong / code / a / img / object / font / br / span / iframe / input / select / textarea / label / button / layer
なお単なるテキストもインライン要素に含まれます。
ブロックレベル要素とインライン要素の関係
ブロックレベル要素とインライン要素を記述するにあたって、次のような関係(制約)があります。エントリーの記述にあたって気をつけなければならないものを挙げておきます。
- ブロックレベル要素の内容に、他のブロック要素やインライン要素を含むことができます(例外あり)
- インライン要素の中にブロックレベル要素を含むことはできません
- p 要素はブロックレベル要素ですが、子要素としてインライン要素しかもつことができません
- div 要素・blockquote 要素は子要素としてブロックレベル要素しかもつことができません
その他
- ul / ol / dl / hr / table の各要素の内容モデルは決まっています(例えば ul は li )
- HTML4.0/XHTML1.0 Strict の場合、body要素の直接の子要素としてインライン要素を記述することはできません(Transitional はOK)
- li / dt / dd / td / tr 等は「内容モデル(ある要素の子要素になることができる要素)」として扱われるだけで、どちらの要素にも該当しません *誤解がありましたらご指摘ください
主な参考サイトは下記です。ありがとうございました。
- NEXTindex:HTML 文書とはなんだろうか
- The Web KANZAKI:ブロックレベル要素とインライン要素
- ぴよぴよ実験室:HTMLメモ(for 自分)
- とほほのWWW入門:HTMLのタグと要素
以上です。この続編として、Movable Type でウェブスタンダードなエントリーを書くためのカスタマイズ方法について記していきたいと思います。
*1:CSSの display プロパティでブロックレベル要素として表示することも可能です
BlogPeople の「List Me!」を valid にする
BlogPeople の「List Me!」を XHTML valid にするカスタマイズです。
BlogPeople のサービスのひとつに、他のブログピープル会員が簡単にあなたのサイト情報をリンクリストに追加することができる「List Me!(私を登録)」があります。当サイトでは下記のような形式のリンクになっています。
<a href="javascript:void(bloppop=window.open('http://www.blogpeople.net/addlink.jsp?n=1&u=http%3A%2F%2Fwww.koikikukan.com%2F&ti='+escape('<$MTBlogName encode_html="1"$>'),'blop','scrollbars=no,width=475,height=350,left=75,top=175,status=yes,resizable=yes'));">List Me!</a>
が、これをページに貼り付けるとThe W3C Markup Validation Serviceで以下のようなエラーと、これと似たようなメッセージが計12個表示されます。つまり「List Me!」を表示することで valid でなくなってしまいます。
Line xxx, column xx: cannot generate system identifier for general entity "u"
...//www.blogpeople.net/addlink.jsp?n=1&u=http%3A%2F%2Fwww.koikikukan.com%2F&ti=
これを回避するため、最初に考えたのは、リンクから一旦空のウィンドウを開き、そこから BlogPeople の JavaScript を起動するという案です(=メインページでエラーにならなければ良い)。
最初のリンクを下記のように書き換えてウィンドウ(ここでは bp.html)を開く
<a href="javascript:void(bloppop=window.open('http://www.koikikukan.com/bp.html','blop','scrollbars=no,width=475,height=350,left=75,top=175,status=yes,resizable=yes'));">List Me!</a>
↓
新しいインデックステンプレート(bp.html)を作り、この中で自動的に JavaScript を実行するように記述
<body onload="window.location.href = 'http://www.blogpeople.net/addlink.jsp?n=1&u=http%3A%2F%2Fwww.koikikukan.com%2F&ti='+escape('<$MTBlogName encode_html="1"$>');">
こういったテクニックを用いれば valid かつ正常に表示されるようですが、やや面倒です。
さて、The W3C Markup Validation Service のエラーをよくみると、後方に
Line xxx, column xx: entity was defined here
...://www.blogpeople.net/addlink.jsp?n=1&u=http%3A%2F%2Fwww.koikikukan.com%2F&ti
とあります。これが本来のエラーで、XHTMLではページ内の "&" を "&" と記述する必要があります。URLでも同様です(HTML 2.0の時からこの点も明記されていましたが、ブラウザは "&" のままでもきちんと処理するように求められていたこともあり、これでも機能していました *1)。
つまり「List Me!」のリンクは下記のように "&" の後ろに青色の "amp;" を追加するだけで valid になります。リンクをクリックした時のページ内容が元の設定の時と同じことも確認しています。
<a href="javascript:void(bloppop=window.open('http://www.blogpeople.net/addlink.jsp?n=1&u=http%3A%2F%2Fwww.koikikukan.com%2F&ti='+escape('<$MTBlogName encode_html="1"$>'),'blop','scrollbars=no,width=475,height=350,left=75,top=175,status=yes,resizable=yes'));">List Me!</a>
2005.07.25 追記
コメントでお分かりの通り、Ogawa::Memoranda さんよりアドバイス頂きまして、valid かつ JavaSript がOFFでも使えるスクリプトを提供して頂きました。この場をお借りして改めてお礼申し上げます。
元のスクリプトの代わりに下記のタグを表示したい位置に設定します(「List Me!」の文言以外は教えていただいたものをそのまま掲載させて頂いてます)。nofollow も付与されているというきめ細かさ。
<script type="text/javascript">
function popup_blop(url) {
var c = url.indexOf('ti=');
url = url.substr(0,c+3)+escape(decodeURIComponent(url.substring(c+3,url.length)));
window.open(url,'blop','scrollbars=no,width=475,height=350,left=75,top=175,status=yes,resizable=yes');
}
</script>
<a title="List Me!" href="http://member.blogpeople.net/addlink.jsp?n=1&u=<$MTBlogURL encode_url="1"$>&ti=<$MTBlogName encode_url="1"$>" onclick="popup_blop(this.href);return false;" onkeypress="popup_blog(this.href);return false;" rel="nofollow">List Me!</a>
*1:The Web KANZAKI:XHTMLの書き方と留意点より引用
XHTML 1.0 Transitional バナーを表示
The W3C Markup Validation Serviceが配布している「XHTML 1.0 Transitional」であることを示すバナーを右下に表示しました。valid であることを確認できているのは今のところトップページのみですので予めご了承ください。
先日買った Designing with Web Standards をようやく読破しまして、ウェブスタンダードなサイトを作ることの重要性を改めて認識致しました(CSSはハックを利用しているので valid ではありませんが)。ウェブスタンダードのスキルがほとんどない状態から1年余りでそれなりに身につけられたのはラッキーだったと思います。
ダジャレMovable Type のテンプレートやカスタマイズを中心に運営しているサイトですので、今後はできるだけウェブスタンダードに準拠する内容にできればと考えています。またこれまでに公開してきたエントリーでウェブスタンダードに準拠していない(またはそうであることを示唆していない)内容については適宜訂正していきたいと思います。
なお BlogPeople の List Me!! が Validation Service にひっかかっていたのですが、カスタマイズによってクリアできました。これについては追ってエントリーしたいと思います。


