<li>を横に並べて表示する時の回り込み解除

[統計] HTMLからXHTMLへの移行を進めていますか?



0   名前: ながらみ : 2005/08/19 18:04
お世話になります。
-----
<ul>
<li>リスト1</li>
<li>リスト2</li>
(以下続く)
</ul>
<div>ここから違うセクション</div>
-----
というリストをCSSで
-----
ul { width: 30em; list-style: none; margin: 1em 0 }
li { width: 10em; height: 1.5em; float:left }
-----
などとして、横に並べて表示する手法がありますよね。

floatによる回り込みを解除する為、</ul>の後に続く要素
上のHTMLで言うと<div>に
clear:bothプロパティを指定していたのですが
回り込みは解除されるものの、<ul></ul>と<div>との間隔が
適切でない(狭い)ように見えます。
上の例ですと、上下に1emのマージンがとられてほしいのですが
上部は適切なマージンがあるものの、下部は0.5em程度しかマージンがとられません。
パディングでも試しましたが、結果は同様です。

ulは本来、内包する要素のサイズに合わせてサイズを変えるものではない
ということから生じる現象でしょうから
ulにheightを指定すれは解決します。
しかし、今回のケースでは必ずしもリスト行は1行とは限らず、
折り返しになる場合もあるため、heightの値を定めることはできません。

<li>リスト2</li>の後に<br style="clear:both">を置くことで、
指定どおりの表示(上下に1emのマージン)とはなりますが
<ul>直下には確か、<li>しか置けないのでしたよね。
CSSを読み込まない環境下で見た時、余計な空行が出来てしまうのも
少々気になります。

折り返しになるリストを内包しても、次にくる要素との間隔が
適切に空けられる方法は、他にありますでしょうか。

1   名前: Pid : 2005/08/19 18:04
浮動ボックスは通常の流し込みから切り離され,現在行の左または右に専用のボックスを形成する(後続要素はこのボックスを避けて配置される)とともに,「本来配置されるはずだった場所」にはあたかも何も存在しなかったように扱われます。試しに border を引いてみれば,li が浮動ボックスとして通常の流し込みから切り離された結果,「中身を失って」ぺしゃんこになってしまった ul のボックスがよく見えます。

「ぺしゃんこの」ul と div の間に li 浮動ボックスが次々と配置されるため,ボックス配置としては li 浮動ボックスの次に div ボックスが来ます。つまり,すでに ul と div の間隔は 1em 以上空いており,

> 下部は0.5em程度しかマージンがとられません。

と仰っているのは ul と div の間隔ではなく,(li の padding) + (li の margin) + (div の padding) 分の余白なのです。

> 折り返しになるリストを内包しても、次にくる要素との間隔が適切に空けられる方法

こういう場合,私は float ではなく { display: inline; } の方が好きです。テキストを途中で折り返されたくなければ { white-space: nowrap; } を合わせて指定します。ただし,この方法では各項目の幅を合わせるのが難しくなりますが。

2   名前: ながらみ : 2005/08/19 18:04
分かりやすく有為なご説明を有難うございます。

>> 下部は0.5em程度しかマージンがとられません。
>
> と仰っているのは ul と div の間隔ではなく,(li の padding) + (li の margin) + (div の padding) 分の余白なのです。

そうなのですよね。ご説明頂いたおかげで、腑に落ちました。
私も、本来であればご提示の{ display: inline }が至適と思うのですが
幅を揃えたいというのがあり、floatを用いました。

リストの最後に、<li>***</li>などの適当な項目を加え、
この<li>をclass="fix"などとして
li.fix { display: block; clear: both; height: 0.5em; width: 1px; visibility: hidden }
と定義付ける…という方法をとってみましたが、
見栄えは整うもののちょっと無理矢理な方法ですね。

li.fixを{ content: "あ"; display: block; clear: both; height: 0.5em; width: 1px; visibility: hidden }
として回り込み解除する方法に出会ったので、試してみたのですが
何故か変化がありませんでした。
試しにvisibility: hiddenを外してみたところ、clearはされてはいるものの
次のdivの領域と、重なってしまっているようです(Mozilla系、Safari)。
方法としては前述の適当な項目を加える方法よりスマートにも思うので
もう少し調べ、試行錯誤してみようと思います。

宜しければまた、ご意見などお聞かせ頂けるとうれしいです。

3   名前: Pid : 2005/08/19 18:04
> li.fixを{ content: "あ"; display: block; clear: both; height: 0.5em; width: 1px; visibility: hidden } として回り込み解除する方法

というのは,ul:after { content: "あ"; display: block; clear: left; visibility: hidden; height: 1em; } のことでしょうか。これは確かに便利ですね (^^)。ただ,WinIE は未だ :after と content に対応していないので,WinIE 対応を考えるなら

> リストの最後に、<li>***</li>などの適当な項目を加え

以外に方法が無いように思います。

----------

妥協案ですが,ul 側ではなく,div 側の padding で調節するのが無難かもしれません。

ちなみに,『リストの最後に、<li>***</li>などの適当な項目を加え』と似たような方法ですが,私は hr 要素をよく使います(CSS 非対応のブラウザで区切り線は効果的ですし,CSS 対応ブラウザでは非表示にしておけば良い)。以下のように hr 要素で clear すれば,(ul の margin は無理ですが)div の margin-top なら効くようになります。

<ul>...</ul>
<hr title="セクション区切り" />
<div>...</div>

hr { margin: 0; padding: 0; clear: left; visibility: hidden; }

----------

ちなみに,

> 幅を揃えたい

ということであれば,ul { display: table-row; } li { display: table-cell; } という手もあります。ul 要素の幅をもとに,全 li 要素を自動的に等幅にしてくれます。ただ,これも WinIE は非対応ですが。

一覧へ戻る