0

行ごとに 1 つの文として視覚的に表示される、いくつかの英語の文を含む HTML フォームがあります。これらの各文の途中には<select>ドロップダウンがあり、見栄えを良くするために左右の端を複数の行にまたがって揃える必要があります。

<div class="row">
    <div class="column col1"> <p> Choose something: </p> </div>
    <div class="column col2"> <select name="dropdown"> ... options ... </select> </div>
    <div class="column col3"> <p> and finish the sentence.</p> </div>
</div>
<div class="row">
    <div class="column col1"> <p> Choose something else: </p> </div>
    <div class="column col2"> <select name="dropdown2"> ... options ... </select> </div>
    <div class="column col3"> <p> and finish another sentence.</p> </div>
</div>
<div class="row">
    <div class="column col1"> <p> Choose last thing: </p> </div>
    <div class="column col2"> <select name="dropdown3"> ... options ... </select> </div>
    <div class="column col3">
        <p>
            and all dropdowns should be left- and right-aligned if
            there is space.  This longer third column should get broken
            onto a second line below the second dropdown if it can't fit
            immediately to the right of the other two.
        </p>
    </div>
</div>

ただし、これはレスポンシブ レイアウトであり、中央の列の幅のみを固定し、次の設計基準に従って 1 番目と 3 番目の列を自動的に拡大/縮小したい:

  • columnビューポートの幅に応じて、それぞれにできるだけ多くの要素をrow並べて配置する必要があります。
  • できるだけ多くのcol2要素を左揃えにする必要があります。

上記では、1 番目が 2 番目に優先されます。言い換えれば、両方の基準に対応するのに十分な幅のブラウザー ビューポートから始めると、次のようになります。

  1. ブラウザのビューポートの幅が縮小されると、縮小する最初の幅は 3 列目になり、col2配置が保持され、3 つの要素がすべてcolumn横並びで保持されます。
  2. 3 番目の列を最小幅に縮小するだけでは不十分な場合は、1 番目の列が縮小を開始する必要があります。これにより、ある時点で配置が崩れますが、要素は横並びのままになります。
  3. それでも十分でない場合は、col3幅が広すぎる行内のブロック全体col1を andcol2ブロックの下に移動する必要があります。はもはや ととcol3並んでいるわけではありませんが、この犠牲は、整列を復元できることを意味します。(この時点で は、文の先頭とドロップダウンの間の望ましくないギャップを防ぎます。)col1col2col2col1max-width

最初の 2 つのルールに基づくと、パーセンテージを使用するものは明らかに機能しません。そして、おそらく 3 番目の規則により、 を使用<table>するものも機能しません。

マージン/パディングは固定されていると見なすことができます。 は英語の文を壊してしまうため、要素overflow: hiddenに高さ制限を設けることはできません。<p>

無数の HTML/CSS の記事と SO の質問に目を通しましたが、これまでのところ、これを達成する方法を説明するものは何も見つかりませんでした。ここから始めて、いろいろと試してみてください。

CSS の HTML5 またはそれ以降の機能を含むソリューションは、JavaScript ベースのハックよりもはるかに好まれます。ソリューションが HTML を変更することは問題ありませんが、それが CSS のみで可能かどうか知りたいです。ありがとう!

4

2 に答える 2

1

JavaScript/JQuery のアプローチを採用して、アイデアを提供しますが、コード自体は提供しません。私のコード セクションは実際のコードではなく、何をする必要があるかを示しています。(CSS部分を除く)

最初に、ページ内のすべての要素の box-sizing を border-box に設定します。これは、この方法で要素のサイズを計算する方が簡単だからです。

*
{
    -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
    -moz-box-sizing: border-box; /* Firefox, other Gecko */
    box-sizing: border-box; /* Opera/IE 8+ */
}

これは、10px のパディングをサポートし、以前と同じように維持するために、.col2 の幅を 10px 増やす必要があることを意味します。

.col2
{
    width: 120px;
}

2 番目の列が常に最初の列の隣にあるのが最善であるため、その動作をサポートするために .col1 の最大幅を設定します。

.col1
{
    max-width: calc(100% - 136px); /*136 = 120 + 2*5 + 2*3*/
}

プロセス全体で、.row & .col3 幅には何も設定しません。行は縮小または拡大する可能性があり、.col3 は常に必要な正確な量のスペースを使用するため (.col1 および .col2 と整列しているか、別の行に配置されているかに関係なく)、実際には .col1 の幅のみを変更します。

ページが最初に読み込まれるとき、ボディのサイズが変更されるたびに、最適なレイアウトを見つける JavaScript 関数が呼び出されます。

function adjustToBestLayout()
{
    1.
    2.
    3.
    4.
}

その過程で、幅が依存するためにスクリプトを適用しない場合、現在のビューポート サイズ (.col2 は固定されているので役立ちます) での .col1 および .col3 要素の実際のサイズを知る必要があります。ビューポート サイズによって変更される場合があります。

そのため、関数に初めて入る場合は、スクリプトの介入なしで、きれいなレイアウトをそのまま「保存」します。その後、関数に入るたびに、調整された古いレイアウトをきれいなレイアウトに置き換え、最初から再調整します。

したがって、次のようになります。

1「きれいな」レイアウトに戻します。.col1 と .col2 は整列され、それぞれがそのコンテンツのサイズを正確に取得し、.col3 (コンテンツのサイズも正確に取得) は 2 つの可能な状態のいずれかになります。最初の 2 列または新しい行に配置されます。

2各列要素は、後で使用するために ActualWidth というプロパティに実際の幅を保存します

3行ごとに、AvailableWidth を計算し、後で使用するためにプロパティとして保存します。計算は次のようになります。

if(row.width >= row.col1.ActualWidth + row.col2.ActualWidth + row.col3.ActualWidth)
{
    //in this case, all columns are in the same line, and we possibly have space left
    row.AvailableWidth = row.width - (row.col1.ActualWidth + row.col2.ActualWidth + row.col3.ActualWidth);
}
else
{
    //in this case, the third column is in a different line,
    row.AvailableWidth = row.width - (row.col1.ActualWidth + row.col2.ActualWidth);
}

.col1 要素を同じ幅に引き伸ばすと、最適なレイアウトが見つかるので、小さな .col1 をレイアウト内のより大きな .col1 要素のサイズに引き延ばそうとします。ただし、.col3 要素を新しい行に移動させることなく、各 .col1 要素をその row.AvailableWidth 以下でのみ拡張できます。

4この計算により、.col1 要素に与える最適な幅を見つけます。各 .col1 について、他の .col1 をそのサイズに引き延ばした場合に整列される行数を数えます。そして最後に、最大数を獲得したものを採用します。したがって、各 .col1.ActualWidth (=CurrentWidth): このステートメントに対して true を返す行の数

0 <= CurrentWidth - row.col1.CurrentWidth <= row.AvailableWidth

その後、.col1 要素の幅を勝者の幅に固定します (前のステートメントに true を返す行のみ)。

ほら!

最後に: もし私があなただったら、「テーブルのような」やや「固定された」レイアウトを好みます。

于 2013-09-09T16:45:06.103 に答える
0

最終的に、次の CoffeeScript ソリューションを思いつきました。

fixSizes = ->
    col1_min = parseInt $(".col1").css("min-width")
    col1_max = parseInt $(".col1").css("max-width")
    console.log "min #{col1_min}, max #{col1_max}"
    $(".row").each (i, row) =>
        debug = false
        r = $(row)
        row_width   = r.width()
        col1_width  = r.find(".col1").width()
        col1_outer  = r.find(".col1").outerWidth(true)
        col2_outer  = r.find(".col2").outerWidth(true)
        col3_outer  = r.find(".col3").outerWidth(true)
        col1_spacing = col1_outer - col1_width
        space_for_col1 = row_width - col1_spacing - col2_outer - col3_outer
        if i == 1
            debug = true
        if debug
            console.log "row#{i} #{row_width}, col1 #{space_for_col1}, col1s #{col1_spacing}, col2 #{col2_outer}, col3 #{col3_outer}"
        col1 = r.find(".col1")
        col3 = r.find(".col3")
        if space_for_col1 < col1_min
            # Can't shrink col1 enough to fit all onto one line; break
            # col3 onto new line.
            col1.css("width", "#{col1_max}px")
            col3.css("clear", "left")
            if debug
                console.log "    break into two lines"
        else if space_for_col1 < col1_max
            # Shrink col1 to fix all onto one line.  Annoyingly we
            # need to shrink by an extra pixel in order to ensure that
            # col3 has enough room to go on the top line and doesn't
            # float directly underneath col2.  This is presumably due
            # to rounding errors, since the row width is a float (in
            # Chrome at least).
            col1.css("width", "#{Math.floor(space_for_col1)-1}px")
            col3.css("clear", "")
            if debug
                console.log "    shrink col1"
        else
            # No shrinking required, ensure col2 is aligned.
            col1.css("width", "#{col1_max}px")
            col3.css("clear", "")
            if debug
                console.log "    fix col1 to align col2"

jQuery ->
    fixSizes()
    $(window).resize ->
        fixSizes()

Chrome でウィンドウ幅を縮小するときの厄介なちらつきを除いて機能します。Javascript が十分に縮小して の右側に戻る前に、一瞬、col3のすぐ下に浮かびます。col2col1col2

ただ、これは醜い気がします。もっとエレガントなものがあるに違いないと感じずにはいられません。

于 2013-09-29T13:23:54.327 に答える