Bug(バグ) #1578
完了[.recentList dl] や [.commentList dl] などで float の回り込み解除の対処がされていないため、レイアウトが崩れる
100%
説明
Overview (概要)¶
コミュニティトピックの一覧ページ(コミュニティトピック一覧、コミュニティ最新書き込み)では、次のようなリストが表示される。
| 2010年9月10日 11:05 | a(0) (dummy2) | | 2010年7月23日 13:30 | name(0) (dummy9) | | 2010年7月23日 13:30 | name(0) (dummy9) |
上記のようなリストで、言語が英語に設定されてるような場合に、日付部分の表記が長くなって日付が折り返してしまうことがある。
日付が折り返すとは次のような状態である。言語を英語に設定した場合に必ず折り返すわけではなく、ブラウザの種類やフォント、文字サイズによって結果は異なる。同様に、言語が日本語であってもこの問題が発生する可能性はある。
| September 10, 2010 11:05 A | a(0) (dummy2) | | M | | | July 23, 2010 1:30 PM | name(0) (dummy9) | | July 23, 2010 1:30 PM | name(0) (dummy9) |
日付が折り返したとき、上記のように左側と右側のレイアウトが保持されるべきであるが、CSSの記述が十分ではないためにレイアウトが崩れてしまっている。
実際のレイアウトが崩れた表示は、次の画像を参照してください。
また、コメント(note-8) http://redmine.openpne.jp/issues/1578#note-8 でもこの問題について説明を示しています。
Range of problems (問題となる箇所)¶
トピックリストに限らず、同様のリスト(同様の原因を含みうる箇所)では同じ問題が発生する可能性があります。
このチケットでは、確認できている箇所 ".recentList dl" と ".commentList dl" を少なくとも修正することとします(もしも同様の問題が別の箇所で起こることが確認された場合は、このチケットが完了していなければこのチケットで、既にクローズされた場合は新しいチケットで対応することを予定しています)。
Causes (原因)¶
CSSの記述が不十分である(「コミュニティトピックの一覧ページ」を問題として示していますが、この原因は opCommunityTopicPlugin ではなく opSkinBasicPlugin のCSSです)。
アイテム一つは dl 要素で、日付部分を dt 要素、トピックタイトル部分を dd 要素でマークアップしている。
<div class="****List"> <dl> <dt>左側(日付部分)</dt> <dd>右側(タイトルなど)</dd> </dl> <dl> <dt>左側(日付部分)</dt> <dd>右側(タイトルなど)</dd> </dl> ... (dl要素がアイテム数だけ繰り返される) </div>
dt { float: left; width: DT_WIDTH; }, dd { margin-left: DT_WIDTH; } のようにCSSを記述しているが(※)、この記述だけで意図したレイアウトになるには、「左側の方が右側よりも常に高さが小さい」という条件が必要になる。
※ 実際の margin-left プロパティ値は DT_WIDTH に padding 値などを加えた値です。
これを考慮して dd 要素には min-height: 5.5em や height: 1.2em といった記述があるが、この値は不十分であり、日付が折り返したりすることを想定していない。
根本的には、日付が折り返す可能性ではなく、「左側の方が右側よりも高さが大きい」という場合の可能性を考慮すべきである。
Way to fix (修正内容)¶
dl 要素の子要素の中で、float している dt 要素が最も高さが大きくなる場合(左側が高くなる場合)に、アイテム全体の高さが保たれるように、dl 要素に clearfix 相当の指定を行う。
また、レイアウトが崩れる問題とは別に、左側と右側の境界線(中央の線)が、左側が高くなる場合にも dl 要素の高さいっぱいに 1px で表示されるように、 dt, dd に border の指定を行う。
具体的な修正内容はコメント(note-6) http://redmine.openpne.jp/issues/1578#note-6 に示しています。
ファイル
Minoru Takai さんが約14年前に更新
- 修正前のCSS
.recentList dl { border: 1px solid #CCCCCC; margin-bottom: 5px; } .recentList dt { float: left; width: 170px; padding: 5px; text-align: center; } .recentList dd { zoom: 1; margin-left: 180px; padding: 5px; border-left: 1px solid #CCCCCC; } * html #Body .recentList dd { height: 1.2em; }
- この問題を解消するために想定されるスタイル記述
.recentList dl { overflow: hidden; clear: both; border: 1px solid #CCCCCC; margin-bottom: 5px; } .recentList dt { float: left; width: 170px; padding: 5px; border-right: 1px solid #CCCCCC; text-align: center; } .recentList dd { zoom: 1; margin-left: 180px; padding: 5px; border-left: 1px solid #CCCCCC; } * html #Body .recentList dd { height: 1.2em; }
- dl { overflow: hidden; clear: both; } を追加
- dt { border-right: 1px solid #CCCCCC; } を追加
- dt の幅が {margin=0 + border=1(right) + padding=5+5 + width=170} = 181 となるが dd の margin-left は 180 とする
- dt { border-right } と dd { border-left } を重ねることで、どちらのボックスが高くなっても境界線が想定通り表示されるようにする
- 閲覧が想定されるブラウザで想定通りの表示となるか要確認
recentList だけでなく、commentList なども同様の修正を施す必要がありそう。同様の箇所が他にも無いか併せて確認する必要がある。
Minoru Takai さんが約14年前に更新
- 題名 を [.recentList dl] で float の回り込み解除の対処がされていないため、レイアウトが崩れる から [.recentList dl] や [.commentList dl] などで float の回り込み解除の対処がされていないため、レイアウトが崩れる に変更
Minoru Takai さんが13年以上前に更新
どのように修正するか¶
修正するCSSファイルの対象となるのは plugins/opSkinBasicPlugin/web/css/main.css です。
- HTML構造を簡単に示す:
<div class="****List"> <dl> <dt>左側(日付部分)</dt> <dd>右側(タイトルなど)</dd> </dl> <dl> <dt>左側(日付部分)</dt> <dd>右側(タイトルなど)</dd> </dl> ... (dl要素がアイテム数だけ繰り返される) </div>
- これに対して今回適用させるCSSを簡単に示す:
dl { /** overflow, clear, zoom * いわゆる clearfix に相当する指定を行う必要があるが、 * dt,dd内のテキストが溢れた場合のことを考えると、ここでは * overflow: hidden を与えることが妥当だと判断した。 * * overflow プロパティ値が visible でなければ、ここでは dl 要素が子要素の高さを確保するため * dl に対して clear: both の指定は不要である。 dl 要素が高さを確保しない場合や dl 要素内で * クリアランスがされない場合でも dt 要素が回りこまないようにここでは clear 指定を残している。 * * zoom は IE6/7 に対してだが、便宜的にプロパティ単位での記述とした。 * ※スラッシュを先行させる記述 "/property: value" は IE6/7 に対するCSSハックです。 */ overflow: hidden; clear: both; /zoom: 1; } dt { float: left; width: {DT_WIDTH}px; padding: 5px; border-right: 1px solid #CCCCCC; } dd { /** margin-left プロパティ * 10px は dt の横paddingの合計値。 * dt の border-right: 1px 分はここには含めず、 * dt{border-right} と dd{border-left} を重ねる。 */ margin-left: {DT_WIDTH}+10px; border-left: 1px solid #CCCCCC; } * html #Body .recentList dd { text-indent: -3px; /* IE6の不具合に対処:後述 */ }
- IE6 および IE7 の不具合に対処するため、次のことを行っている
- dd 要素は hasLayout 値が false になるようにする
- これが true になると dt{border-right} と dd{border-left} を重ねることができなくなる
- IE6 ではブロックレベル要素 X, Y に対し、 X{float:left; width:**;} Y{margin-left:**;} のように float+margin で横並べをし、要素Yの hasLayout 値が false であると、要素XとYの間に隙間はできないが、要素Yの中の(全てのブロックレベル要素の中の)インラインの1行目が 3px ほど右側(書字方向)にずれるという不具合がある。この見栄えを整えるために IE6 のみ text-indent プロパティを指定している。この問題は IE7 では生じない。
- IE6 へのスタイル記述を(プロパティ単位ではなく)セレクタ単位のCSSハックで行っていることに深い理由はない。CSSのコーディング規約が特に定められていない現状では特に制約はなく、どのように記述してもよいと考えられる。
- dd 要素は hasLayout 値が false になるようにする
CSS の差分¶
/*============================================================================== * recentList *----------------------------------------------------------------------------*/ .recentList dl { + overflow: hidden; + clear: both; border: 1px solid #CCCCCC; margin-bottom: 5px; + /zoom: 1; } .recentList dt { float: left; width: 170px; padding: 5px; + border-right: 1px solid #CCCCCC; text-align: center; } .recentList dd { - zoom: 1; margin-left: 180px; padding: 5px; border-left: 1px solid #CCCCCC; } * html #Body .recentList dd { - height: 1.2em; + text-indent: -3px; } /*============================================================================== * commentList *----------------------------------------------------------------------------*/ .commentList dl { + overflow: hidden; + clear: both; border: 1px solid #CCCCCC; margin-bottom: 10px; + /zoom: 1; } .commentList dt { float: left; - width: 70px; - padding-top: 5px; + width: 60px; + padding: 5px; + border-right: 1px solid #CCCCCC; text-align: center; } .commentList dd { - zoom: 1; - min-height: 5.5em; margin-left: 70px; border-left: 1px solid #CCCCCC; } * html .commentList dd { - height: 5.5em; + text-indent: -3px; } #LayoutC .commentList dt { - width: 110px; + width: 100px; }
Minoru Takai さんが13年以上前に更新
- ステータス を Accepted(着手) から Pending Review(レビュー待ち) に変更
- 進捗率 を 0 から 50 に変更
更新履歴 eaa0c01bc057da7c8645250069bc7f8dae3dde19 で適用されました。
Minoru Takai さんが13年以上前に更新
- ファイル t1578_before.png t1578_before.png を追加
- ファイル t1578_after.png t1578_after.png を追加
この問題に対して、行うべき動作テストについて示しておきます。
修正前と修正後の違い¶
- アイテムの一覧ページには、枠線で囲まれた1つのアイテムが複数表示されています。
- ひとつのアイテムには、左側(日付部分)と右側(本文部分)があります。
- 修正前:左側の高さが大きくなると、アイテムの高さを飛び抜けて崩れます
- 修正後:左側の高さが大きくなっても、アイテム自体の高さが大きくなります
この問題を発生させるには(テストするには)¶
この問題は、次の条件が満たされたときに発生します。
- 左側のボックスの高さが、右側のボックスの高さよりもある程度大きくなる場合
この条件を発生させる一つのケースが、「日付部分が英語表記である場合に1行に収まらず、文字列が折り返してしまう」状況です。しかし英語設定であることは、この問題を発生させる本質的な条件ではありません。つまり、テストケースとして日本語設定である場合や英語設定である場合を用意することは適切ではありません。
現実的にこの問題が発生するのは、ブラウザ側で文字サイズを上げたり、幅広のフォントを用いたり、文字列全体が長くなる場合(英語設定で月表記が長い場合)などですが、テストのためであれば、文字サイズを意図的に大きく設定してしまうことが有効です。
この問題を発生させる(修正ができているかをテストする)ためには、次のことを行うと状況の再現が容易にできます。
- テスト環境のSNSの管理画面から、カスタムCSSで次のスタイル記述を追加してください。
.recentList dt { font-size: 20px; } .commentList dt { font-size: 40px; }
- あるいは、ブラウザの設定で文字サイズを大きくしてください。
テスト手順、テストすべき項目¶
上記は、このチケットで挙げられている問題を発生させる方法ですが、その問題が発生しないことを確認してもテストは十分ではありません。左側が高い場合だけでなく、それ以外のケースで表示に問題がないかもテストする必要があります。
テスト手順:インストール後のOpenPNE3系に対して次のことを行います。
- テスト手順: recentList
- コミュニティを1つ作成する
- そのコミュニティでトピックを2個以上作成する
- このとき、トピックタイトルの文字数が短いもの(普通なもの)と、極端に長いものを用意してみてください。
- 極端に長い文字列のサンプル:メロスは激怒した。必ず、かの邪智暴虐(じゃちぼうぎゃく)の王を除かなければならぬと決意した。メロスには政治がわからぬ。メロスは、村の牧人である。笛を吹き、羊と遊んで暮して来た。けれども邪悪に対しては、人一倍に敏感であった。きょう未明メロスは村を出発し、野を越え山越え、十里はなれた此(こ)のシラクスの市にやって来た。メロスには父も、母も無い。女房も無い。十六の、内気な妹と二人暮しだ。
- このとき、トピックタイトルの文字数が短いもの(普通なもの)と、極端に長いものを用意してみてください。
- トピック一覧ページにアクセスする
- コミュニティ側のページ communityTopic/listCommunity/1 か、
- マイホーム側のページ communityTopic/recentlyTopicList のどちらでもよいです。
- 表示結果を確認する
- テスト手順: commentList
- (任意の)コミュニティトピックを開く
- コミュニティトピックのページ communityTopic/1 を開く
- コメントを2個以上作成する
- コメントの表示結果を確認する
- (任意の)コミュニティトピックを開く
テストすべき項目:次のケースの場合に、以下の確認項目が満たされているかをテストする必要があります。
- テストケース
- (case-1) 左側が高い場合(左側が2行以上で、右側が1行の場合)
- 次のCSSを管理画面から適用してください
.recentList dt { font-size: 20px; } .commentList dt { font-size: 40px; }
- 次のCSSを管理画面から適用してください
- (case-2) 右側が高い場合(左側が1行で、右側が6行程度以上の場合)
- 文章が特別長い記事のアイテムを確認します。
- コメント一覧ページ (commentList) の動作を確認する際は、上記で追加したCSSを外した方がよいかもしれません。
- (case-3) 左側も右側も1行の場合(どちらが高いということがない場合)
- 文章が短い記事のアイテムを確認します。
- 上記で追加したCSSを外す必要があります。
- (case-1) 左側が高い場合(左側が2行以上で、右側が1行の場合)
- テスト項目
- (check-1) レイアウト崩れがない(前述の画像参照)
- (check-2) 左側と右側のボックスの境界線(真ん中の縦の線)が 1px で表示されている
備考¶
- テスト手順では、トピックのみしか示していませんが、より十分な検証をしたければイベントも同様に確認してください。
- 実装者的には、トピックもイベントも同一のテンプレートなので、片方の検証で十分だと認識しています。
- (case-3) については、case-1 と case-2 が同時に問題なければ case-3 は問題ないことが導出できるのですが一応テストケースとして示しています。
- (case-2) について、右側が6行程度と書いたのは、 dd 要素(右側)に対して height プロパティ値が em 単位(文字サイズに比例)で与えられていたため、文字サイズを上げるのではなく実際に長文を入力したほうが正確な検証ができるためです。
- (check-2) については、今回の修正で、左側と右側のどちらが高くても、境界線が思ったとおり(境界線として 1px で)表示されるような修正を施しています。ボックスを 1px だけ重ね合わせるという方法を用いており、各種ブラウザの不具合に注意しないと意図しない表示となる可能性があるため、ここで確認項目として示しています。
Shinichi Urabe さんが13年以上前に更新
- ステータス を Pending Review(レビュー待ち) から Rejected(差し戻し) に変更
本チケットの説明の修正内容欄に修正内容を追記してください
Minoru Takai さんが13年以上前に更新
- ステータス を Accepted(着手) から Pending Review(レビュー待ち) に変更
チケットの Description を書き換えました。
Shinichi Urabe さんが13年以上前に更新
- ステータス を Pending Review(レビュー待ち) から Pending Testing(テスト待ち) に変更
- 進捗率 を 50 から 70 に変更
確認した点¶
- IE6/IE7のみ適用させるスラッシュハックについては一般的に使われる手法であるとのことでもんだいないと判断
- float 回りこみ解除の記述はこのCSS内でも使っている一般的な手法だと判断しますので、問題ないと判断
- CSSの記述について特に決まりはないが、前後の記述と差異ないので問題ないと判断
- 最新リストボックスとコメントリストボックスで充分に修正はまかなえていると考えるので修正漏れはないと判断
- チケットの説明欄についても不備はない
- opSkinClassicPlugin と異なるfloatの回りこみ解除の記述であるが、(borderの指定も若干異なる)問題はないと判断
上記の点を踏まえてコードチェックはOKと判断します