Hatena::Groupcss

#DocSeri { style: boxtile; } このページをアンテナに追加 RSSフィード

2006-10-12CSSコーディングのためのHTMLコーディング

はじめに はじめに - #DocSeri { style: boxtile; } を含むブックマーク はてなブックマーク - はじめに - #DocSeri { style: boxtile; } はじめに - #DocSeri { style: boxtile; } のブックマークコメント

CSSには様々なメリットがある。見栄えのコントロールがより柔軟かつ強力になり、またメンテナンス性が格段に向上しアクセシビリティも高まる。良いこと尽くめだ。

しかし、今までHTMLだけで見栄えをコントロールしていた人がいきなりCSS移行しようとするのは結構難しい。そこには大きな発想の転換が必要だ。

はてなダイアリーの構造などを参考にしながら、「CSSデザインするためのHTML」について書いてみたいと思う。

構造を意識する 構造を意識する - #DocSeri { style: boxtile; } を含むブックマーク はてなブックマーク - 構造を意識する - #DocSeri { style: boxtile; } 構造を意識する - #DocSeri { style: boxtile; } のブックマークコメント

HTMLは文書構造を記述するための言語である。見出しには順番に応じてh1〜h6までのタグを振り、文章は総てpで段落分けする。文中に箇条書きが登場するときはui/olやdlマークアップ

只の文書ならこれだけでも良いが、Webページの場合はこれだけでは要素が足りない。また、自在にデザインしようと思ったときにも、これだけでは要素数が不足してしまう。例えば-----メニュー部分はどんなタグで囲うべきか?リンクの機能としてのAタグは当然としても、それらの関係性や意味性をどうマークアップしたら良いのか。

XMLなら必要に応じてタグ自体を定義することもできるが、HTMLで使える要素は限られる。そこで使われるのが、意味を与えられていないタグdivとspan、及びCSS上で重要になる属性classidである。


classidは、言わばHTML存在しない分類を、個別にラベリングすることで実現する機能と言える。例えば前述したメニューなどは、HTML上にメニューを示すタグがない。そこでulリスト化するなりdivで括るなりしたところにclass="menu"などとラベリングすることで、それがメニューであることを示すようにする。

classidの違いは一般名詞固有名詞のようなもので、classが複数の箇所に利用されるようなラベリングに用いられるのに対し、idはあくまで1箇所にしか用いられない要素に対するラベリングである。先の例では、メニュー自体はclassで、メニュー内の各項目はidラベリングするのが適当だろう。


既にマークアップされている要素についてはそれぞれにラベリングすれば済むが、ときには適切な要素自体が存在しないこともある。例えば見出しといくつかの段落を纏めて一括りに扱うにはどうすれば良いだろうか。或いは見出しの一部に日付を挿入する場合は?

divとspanは、そのような「既存のタグでは対応できない」部分のマークアップに用いるためだけの「空のタグ」である。それは区切りであることを示すという以上の意味を持たず、classidによってラベリングされることを前提とした存在である。

その違いはdivがブロックレベル要素*1であるのに対しspanはインライン要素*2であるという一点のみ。

例えばはてなダイアリーの構造を見ると、日毎のタイトルを表すh2の中にspan class="date"によって日付けがマークアップされ、また日毎のタイトルとその下の同じ日のエントリ全体をdiv class="day"が囲い、またエントリ毎の見出しh3とエントリ内の段落を纏めてdiv class="section"が囲っているのが判る。


このように、ただHTMLマークアップするだけではなく、構造を考え単位を細かく区切ってラベリングしてゆくことで、この後のCSSによるデザインコントロールが容易になる。

*1:hxやpのように、独立したブロックとして扱われ、要素の前後に改行が行なわれるような要素

*2:文中に埋め込み可能な要素

トラックバック - http://css.g.hatena.ne.jp/DocSeri/20061012

2006-02-28

ダイアリーのデザイン手法(3):サイドバーのスタイル 14:30 ダイアリーのデザイン手法(3):サイドバーのスタイル - #DocSeri { style: boxtile; } を含むブックマーク はてなブックマーク - ダイアリーのデザイン手法(3):サイドバーのスタイル - #DocSeri { style: boxtile; } ダイアリーのデザイン手法(3):サイドバーのスタイル - #DocSeri { style: boxtile; } のブックマークコメント

はじめに、かんたんデザイン設定などで作られたサイドバーの基本的な構造を以下に示す。

  • div.sidebar(サイドバー全体の枠)
    • div.hatena-module(各モジュールごとの枠)
      • div.hatena-moduletitle(モジュールのタイトル)
      • div.hatena-modulebody(モジュール本体を格納する枠)

div.hatena-modulebodyの中にはそれぞれのモジュールによって違う中身が入る。

サイドバーに独自に要素を追加したい場合は、上記の構造を利用するとデザインが統一できる。

各モジュールの設定

枠部分のデザインは特にdiv.mainと変わるところはないと思うので割愛するとして、モジュールの構造分析に移る。

殆どのモジュールは番号無しリスト表示を利用した構造になっており、クラス名を除いてほぼ同じ構造となっているので、まとめて表にした。

モジュール名クラス名
アンテナモジュールhatena-antenna
リンク集モジュールhatena-urllist
トラックバック/コメントモジュールhatena-recentcomment
カテゴリーモジュールhatena-sectioncategory
最新タイトルhatena-section
RSSモジュールhatena-rss

これらは以下のような共通構造を持っている。

  • ul.クラス名(リスト外枠)
    • li(各項目)
      • a(リンク)

それ以外のモジュール構造は以下の通りである。

最新の画像
  • ul.hatena-photo(画像表示リスト枠)
    • li(各項目)
      • a(リンク)
        • img.hatena-photo(画像)

リスト構造は同様だがクラス名を持つimgが含まれるので別掲載とした。

pvモジュール
  • span.hatena-counter(数字)

唯一のinline要素モジュール。

日記の検索
  • form.hatena-searchform(検索キーワード送信フォーム)
    • input(文字入力欄)
    • input(「検索」ボタン)

検索窓。殆どの場合弄る必要はないと思う。

カレンダー
  • table.calendar(カレンダー全体の枠)
    • tr(表示月ナヴィゲーション部)
      • td.calendar-prev-month(先月)
      • td.calendar-current-month(今月)
      • td.calendar-next-month(次月)
    • tr(曜日表示部)
      • td.calendar-sunday(日曜)
      • td.calendar-weekday(平日)
      • td.calendar-saturday(土曜)
    • tr(日付表示部)
      • td.calendar-day(日付)
        • a(日記が書かれている場合のリンク)
          • (img)(calendar2photo使用時、日記に掲載した画像のサムネイル)

最も複雑な構造とクラスを持つカレンダーモジュール。

トラックバック - http://css.g.hatena.ne.jp/DocSeri/20060228

2006-02-27

ダイアリーデザイン手法(2):本文のスタイル 19:32 ダイアリーのデザイン手法(2):本文のスタイル - #DocSeri { style: boxtile; } を含むブックマーク はてなブックマーク - ダイアリーのデザイン手法(2):本文のスタイル - #DocSeri { style: boxtile; } ダイアリーのデザイン手法(2):本文のスタイル - #DocSeri { style: boxtile; } のブックマークコメント

続いてdiv.main内のスタイルを変更する。

div.main内には次のような要素が並ぶ。階層構造を解り易く説明するために箇条書きする。

これだけあるので大変そうだが、順を追って設定すればそう難しいことはない。

日ごとの区切り

日ごと・セクションごとに何らかの区切りがあると画面が締まる。

div.day/div.sectionにborderなどを設定する方法とh2/h3にbackgroundまたはborderを設定する方法がある。

div.day/div.sectionへのborder表示

hatenaテーマなどでも使われる、最も簡単な手法。

枠線で囲う場合、paddingなどなんらかの手段で本文と隙間を作らないと非常に読み難くなるので注意。

枠線を意識させたくない場合、背景に縦方向のグラデーションを敷くといった方法もある。

見出しスタイル

h2/h3に背景色や枠線を指定して区切りとすることもできる。

paddingで適度に内部要素との隙間を確保して、視認性を向上させると良い。

div.day/div.sectionにも枠線を指定した場合、h2/h3の外枠がdivの枠線とぴったり重なる方が見栄えが良いが、divにpaddingがあるとその分隙間ができてしまう。

divのpaddingを切って内部の角要素に個別指定する手もあるが、段落リスト引用・テーブルなど様々な要素を網羅するよりは、divのpaddingをそのままにしてh2/h3にそれと等しい量のマイナスマージンを設定する方が簡単。


また、好みの問題もあるが見出しにはletter-spacingで多少文字間を空け気味に配置すると上品に仕上がる。

角丸の見出し

見出し部分の角を丸める方法について。

現在Mozilla-moz-border-radiusで角の丸めを先行実装しているが、他に対応ブラウザがないので使用を推奨しない。

4箇所の角を全て丸めることは困難だが、2箇所ならなんとかなると思うので例を示す。

左右の角を丸めた画像とそれに繋がるグラデーション画像を用意し、それぞれL.gif、R.gif、G.gifと名付けた。

/*日ごと見出し*/
div.day {
	background: url(G.gif) repeat-x;
	margin: 1em;
}
h2 {
	background: url(L.gif) no-repeat;
	padding: 0.5em;
}
h2 span.date {
	float: right;
	margin: -0.5em;
	padding: 0.5em;
	background: url(R.gif) no-repeat right top;
}
/*セクションごと見出し*/
div.section {
	background: url(G.gif) repeat-x;
	margin: 1em;
}
h3 {
	background: url(R.gif) no-repeat right top;
	padding: 0.5em;
}
h3 span.sanchor {
	margin: -0.5em;
	padding: 0.5em;
	background: url(L.gif) no-repeat;
	display: block;
	float: left;
}

尚、グラデーション画像は角丸の高さと同じだけベタ塗り部分を用意する。そうしないとスムーズに繋がらない。


内包する要素の違いで、h2とh3では角丸の表示方法が逆になっていることに注意。

また、上記の例では便宜的に日ごとの見出しもセクションごとの見出しも同じスタイルになっているが、実際に利用する際にはどちらか一方のみに限定した方が良いだろう。

本文のスタイル

一文字下げ

はてなダイアリーでは改行ごとにpで括られ、空行2行をbrで置き換える仕様になっている。文法的には逆の方が適切なのだが、こうなっているわけは日本語の表記との相性にある。

日本語の適切な表記としては改行ごとに頭一文字分インデントされるべきだが、text-indentでは段落毎の最初の一文字しかインデントできない。そこでpとbrの役目をわざと逆にしてあるのだ。

従って一字下げを行ないたい場合は、わざわざ全角スペースを挿入する必要はなく、p { text-indent: 1em; }で済む。

行間調整

デフォルトでの表示は、文字感と行間がほぼ同じになっている。これはかなり読み難いので、行間を広く取って読み易さを向上させる。

pにline-heightで1.5em程度の行高さを指定。好みによるが、2em以上広く空けると却って読み難いだろう。

最初の一文字を大きく

西洋の書物などに時々見られる様式で、最初の一文字が大きな飾り文字などで表示され、残りの文字がそれに回り込むというものがある。

飾り文字はちょっと無理*1だが、回り込みの再現は難しくないので紹介しておく。

「最初の一文字」を指定するには疑似要素:fitrst-letterを用いる。しかしp:first-letterとしてしまうと改行ごとに適用されて大変なことになるので、セクションの最初の要素のみに限定せねばならない。つまりh3直後のpのみを指定すれば良い。

h3とpは共にdiv.sectionの子要素なので、「同一階層の直後の要素を指定する」隣接セレクタ+が利用できる。h3+p:first-letter { font-size: 3em; float: left; }とでもすれば、それらしい表示ができるだろう。

内容がごく短かった時の後続要素の配置を考慮して、section終端のdiv.refererlistあたりにclera: leftを追加するのが望ましい。

続く

次はサイドバー編

*1:font-family:fantasyで装飾文字を指定できることになっているが、Mozillaでは設定されていないようだし、いずれにせよフォント種類は指定できない

トラックバック - http://css.g.hatena.ne.jp/DocSeri/20060227

2006-02-21

ダイアリーデザイン手法(1):タイトルへの画像表示とサイドバー並列レイアウト 10:59 ダイアリーのデザイン手法(1):タイトルへの画像表示とサイドバー並列レイアウト - #DocSeri { style: boxtile; } を含むブックマーク はてなブックマーク - ダイアリーのデザイン手法(1):タイトルへの画像表示とサイドバー並列レイアウト - #DocSeri { style: boxtile; } ダイアリーのデザイン手法(1):タイトルへの画像表示とサイドバー並列レイアウト - #DocSeri { style: boxtile; } のブックマークコメント

はてなダイアリーCSS編集するにあたって、ちょっとしたコツなどを書いてみる。

とりあえずpaddingmarginを消す

ブラウザによってデフォルト設定の異なるpaddingmarginを一度すべて0に設定、必要に応じて後から上書きして行く。

 * { margin: 0; padding: 0; }

トップに画像を表示するには

ダイアリーではタイトル画像を使えるので、それでやってしまうのが一番簡単。

ただしテーマ作成時やグループではそうも行かないので、背景に画像差し込むことになる。

尚、画像は可能な限り左右方向のサイズに融通を利かせる(横方向繰り返しなり背景色同一化グラデーションなり)のが望ましい。これはユーザビリティを考慮して横幅を可変にするため。

h1の背景として表示

h1の背景とする方法の利点は解り易さ。h1ブロックがそのまま画像表示部となるので直感的に理解し易く、また調整がh1のみで完結する利点がある。

heightに画像高さを指定して下が切れないように、また背景を繰り返し表示しないように指定。

h1 { background: url(画像URL) no-repeat; height: 画像高さ; }

ちなみにこの方法ではh1テキスト表示位置がヘッダーテーブルとウィンドウ枠にぴったりくっついてしまう。適度に間を空けるにはh1paddingを指定すれば良いのだが、その場合指定したpadding量だけh1全体のサイズが広がることに注意。

画像背景色と地続きになるよう作成するなどすればこの辺りはあまり気にしなくて良い。

bodyの背景として表示

bodyの背景とする利点は、本文との一体感である。例えば比較的大きな画像を、下が徐々に背景色と同一となるようなグラデーションに加工して背景とし、上にタイトル部や本文を重ねてしまうような構造が考えられる。h1背景型でもpositionなどによる重ねで同様の表示ができないわけではないが、明らかにbody背景の方が楽に処理できる。


表示の際にはh1margin-bottomなどで画像の濃い部分が本文に重ならないよう高さを稼ぐ。またbackground-positionウィンドウ最上部からの幅を調節してヘッダーテーブルに重ならないようにする。

body { background: url(画像URL) no-repeat 0 60px; }
h1 { margin-bottom: 画像の高さ; }

このとき、h1を一時的にdisplay:noneして位置を調節しておく。これは、フォントサイズの異なる環境に対応するため。

調節が終わったらh1を再度表示、フォントサイズを指定する*1。このとき、文字サイズ分下がり過ぎてしまうことになるので、div.hatena-bodyのposition指定でh1の文字サイズ分引き上げて元の位置に直す。

本文とサイドバーの並列配置

ブログの構造としては非常にありふれた、右または左にサイドバーを配置するレイアウトのためのテクニック。

positionとfloatの2パターンがあるが、ここでは表示位置のずれが起き難いposition法を解説する。

位置基準枠の設定

div.hatena-bodyにposition:relativeを設定する。これはこの下の要素にpositionを指定する場合の基準点にするため。この設定をしておかないとウィンドウ枠自体を基準にしてしまい、都合が悪い。

body背景イメージの関係でdiv.hatena-body自体の位置を調節する場合を除き、それ以上の設定は必要ない。

本文の表示位置

div.mainの位置調整はmarginで行なう。サイドバーを設置したい方向のmarginを、予定している幅より少し大きめに空ける。

div.mainの幅は固定しないのが望ましい。

サイドバーの表示位置

div.sidebarにはposition:absoluteを指定、topを0とする。これでdiv.mainと頭を揃えることができる。

左に表示する時はleft:0;右ならright:0を指定。

続いてwidthにdiv.mainのmarginより少し小さな値を設定すれば、二つの枠が綺麗に並ぶ。

応用として、div.sidebarクラス名を替えて二つ用意し、それぞれにleft:0とright:0を指定、div.mainの左右マージンを空ければ3段表示も可能。ただし本文がかなり狭まるので注意して扱うこと。

続く

続きは次の日に。

*1:異なる閲覧環境のためにptやpxでサイズを固定しないこと。常にemや%,若しくはxx-small〜xx-largeによる可変サイズ指定を推奨する

トラックバック - http://css.g.hatena.ne.jp/DocSeri/20060221

2005-12-05

はてなモジュールCSS構造 16:39 はてなモジュールCSS構造 - #DocSeri { style: boxtile; } を含むブックマーク はてなブックマーク - はてなモジュールCSS構造 - #DocSeri { style: boxtile; } はてなモジュールCSS構造 - #DocSeri { style: boxtile; } のブックマークコメント

はてなモジュール一覧とその構造についてキーワードストックしておこうと思い立つ。

既に個別の画面については解説があった筈だが、多分モジュールを一覧してその構造を取り出すような情報はなかったと思う。


ついでに各要素を網羅したテンプレートも用意しようか。

トラックバック - http://css.g.hatena.ne.jp/DocSeri/20051205