0

我有一个带有几个英文句子的 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. 随着浏览器视口宽度的减小,第一个缩小的宽度应该是第三列,保持col2对齐并保持所有三个column元素并排。
  2. 如果将第 3 列缩小到其最小宽度还不够,则第 1 列应该开始缩小,这会在某些时候破坏对齐,但仍使元素并排。
  3. 如果这还不够,col3任何行中仍然太宽的整个块都应该移到col1andcol2块下方。Now不再与andcol3并列,但这种牺牲意味着我们可以恢复对齐。(此时's将防止句子开头和下拉列表之间出现不希望的间隙。)col1col2col2col1max-width

根据前两条规则,显然任何使用百分比的方法都行不通。大概是由于第三条规则,任何使用的东西<table>都不起作用。

可以假定任何边距/填充是固定的。 会破坏英文句子,因此元素overflow: hidden不能有高度限制。<p>

我已经阅读了无数 HTML/CSS 文章和 SO 问题,但到目前为止还没有找到任何解释如何实现这一点的东西。这是您可以尝试的起点:

涉及 HTML5 或 CSS 中更新功能的解决方案比基于 JavaScript 的 hack 更受欢迎。解决方案可以更改 HTML,尽管我很想知道是否只能通过 CSS 实现。谢谢!

4

2 回答 2

1

采用 JavaScript/JQuery 方法,我将提供一个想法,而不是代码本身。我的代码部分不是真正的代码,而是说明需要做什么。(除了 CSS 部分)

首先,我们将page中所有元素的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+ */
}

这意味着 .col2 的宽度必须增加 10px 以支持 10px 填充并保持与以前一样。

.col2
{
    width: 120px;
}

最好第二列总是紧挨着第一列,因此我们将设置 .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.
}

在此过程中,如果我们不应用脚本,我们将需要知道当前视口大小中 .col1 和 .col3 元素的实际大小(.col2 是固定的,因此会有所帮助),因为它们的宽度取决于它们的内容,并且可能会在不同的视口大小中发生变化。

因此,如果这是我们第一次进入该函数,我们将按原样“保存”我们干净的布局,而无需脚本干预。之后,每次我们进入该功能,我们都会用干净的布局替换旧的调整布局,并从头重新调整。

所以它是这样的:

1带回“干净”的布局。现在在每一行中,我们都有以下内容: .col1 和 .col2 对齐,每个都取其内容的大小,并且 .col3 (也取其内容的大小)可以处于两种可能状态之一,他可以与两个第一列对齐,或在新行中。

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 元素进入新行,因此我们可以仅通过 row.AvailableWidth 或更少来拉伸每个 .col1 元素。

4通过这个计算找到给 .col1 元素的最佳宽度:对于每个 .col1,如果我们将另一个 .col1 拉伸到他的大小,我们将计算有多少行将对齐。最后我们将选择得分最高的那个。所以,对于每个 .col1.ActualWidth (=CurrentWidth):多少行返回 true 到这个语句

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

之后,我们将 .col1 元素的宽度固定为 wining 宽度(仅在对上一个语句返回 true 的行中)

瞧!

Finnaly:如果我是你,我更喜欢“Table-Like”有点“固定”的布局。

于 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 中缩小窗口宽度时会出现恼人的闪烁 -col3瞬间col2,在 Javascript 收缩col1到足以让它回到col2.

不过这感觉很丑。我不禁觉得一定有更优雅的东西。

于 2013-09-29T13:23:54.327 回答