65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 CSS 创建流畅的、多列的、垂直排序的列表

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.83/5 (23投票s)

2009年8月14日

CPOL

4分钟阅读

viewsIcon

86671

使用嵌套的浮动 div 创建一个流畅的、多列的、垂直排序的列表

引言

本文介绍了一种新颖的解决方案,用于创建动态的、多列的、垂直排序的列表,该列表可根据可用宽度流畅地换行,同时保留项目的排序。

背景

使用 HTML 创建单列垂直列表非常简单,只需要使用 ULLI 标签,甚至 BR 标签即可。通过一些服务器端代码,可以将列表分解成大小相等的块,然后将其插入到多列表格或一系列 divs 中,从而扩展到固定数量的列。然而,我们最近有一个需求,需要创建一个流畅的、多列的垂直列表,该列表通过按需换行来高效地利用可用空间。在网上搜索答案,得到的建议是使用 JavaScript 或等待 CSS3 列功能获得更广泛的支持!我们不想这样做,所以我们提出了我们认为是一种新颖的方法。

Using the Code

解决此问题的一种方法是使用固定宽度的 float

<div style="float:left;width:120px;">Archery<br />Ballooning<br />Biking</div>
<div style="float:left;width:120px;">Bungee Jumping<br />Coasteering<br />Dancing</div>
<div style="float:left;width:120px;">Driving<br />Gliding<br />Motor Racing</div>
<div style="float:left;width:120px;">Murder Mystery<br />Off-Roading<br />Paintballing</div>

width 足够时(由虚线矩形指示),此代码将呈现如下:

fluidverticallist/figure1.PNG

但是,当可用 width 变小时,列表会以一种方式换行,虽然水平排序可能保留,但垂直排序不会保留,直到完全换行。

fluidverticallist/figure2.PNG

fluidverticallist/figure3.PNG

fluidverticallist/figure4.PNG

此外,如果一些浮动的 divs 高度不同,即使是水平排序也会中断,因为换行的 floats 会被“智能地”放置。

fluidverticallist/figure5.PNG

问题在于我们无法控制 floats 的换行顺序。如果我们能以某种方式告诉第二个 float 在第四个 float 之前换行到第一个下方,而不是让第四个换行到第一个、第二个和第三个下方,那我们就成功了。然而,总是最后一个 float 被换行。

我们解决此问题的方法是使用嵌套的 floats,并设置 floats 的 widthmin-width 属性,以限制列表块的换行顺序。

我们原型化的 float 现在看起来是这样的:

<div style="float:left;width:50%;min-width:110px;"> CONTENT </div>

这些被嵌套在一起,使得每对相邻的列表项或项目块(每个都在一个浮动的 div 中)都被包含在一个超级的浮动的 div 中。

<div style="float:left;width:50%;min-width:110px;">
  <div style="float:left;width:50%;min-width:110px;">Archery
            <br />Ballooning<br />Biking</div>
  <div style="float:left;width:50%;min-width:110px;">Bungee Jumping
            <br />Coasteering<br />Dancing</div>
</div>
<div style="float:left;width:50%;min-width:110px;">
  <div style="float:left;width:50%;min-width:110px;">Driving
            <br />Gliding<br />Motor Racing</div>
  <div style="float:left;width:50%;min-width:110px;">Murder Mystery
            <br />Off-Roading<br />Paintballing</div>
</div>

这给了我们如下的 DOM 结构:

fluidverticallist/figure6.PNG

随着可用 width 的减小,百分比 widths 导致每个列收缩,直到列达到由 min-width 属性设置的下限 width。最先达到此阈值的 divs 是内部 divs(红色),因此当我们越过一个临界阈值时,外部 divs(蓝色)变得足够窄,以至于它们无法在不换行的情况下容纳内部 divs,所以我们看到如下效果:

fluidverticallist/figure7.PNG

fluidverticallist/figure8.PNG

正如你所见,垂直排序得到了保留。

这可以扩展到任何数量的初始列,只要它是 2 的幂,例如 4、8、16 或 32 列,这分别需要 2、3、4 和 5 个嵌套级别,其中每对 50% 宽度的浮动 divs 都被一个超级的 50% 宽度的浮动 div 包含。

使用 8 列的此方法实际应用的示例可在此处找到 (作者已删除死站链接)

服务器端要求

本文的主要目的是演示上述用于构建适应可用空间的“技巧”。为了说明服务器端要求,我们包含了一个 VB.NET 示例方法,该方法为具有 8 列的列表执行所需渲染。

Public Function HTMLMultiColumnList(ByVal listitems As List(Of String), _
                                    ByVal widthpixels As Integer) As String
    Dim output As New StringBuilder
    '
    ' Calculate the number of items required in each block, and the number of blocks 
    ' that will have an extra item to cope with the remainder.
    '
    Dim itemsperblock As Integer = CInt(Math.Floor((listitems.Count) / 8))
    Dim blockswithextraitems As Integer = listitems.Count - (itemsperblock * 8)
    '
    ' Build the sublists
    '
    Dim sublists(8) As List(Of String)
    Dim counter As Integer = 0
    For i As Integer = 0 To 8 - 1
        sublists(i) = New List(Of String)
        Dim itemsthisblock As Integer = itemsperblock
        If i < blockswithextraitems Then itemsthisblock += 1
        For k As Integer = 0 To itemsthisblock - 1
            If counter < listitems.Count Then
                sublists(i).Add(listitems(counter))
                counter += 1
            End If
        Next
    Next
    '
    ' Render the sublists with nested float divs
    '
    Dim divopen As String = String.Format( _
    "<div style=""float:left;width:50%;min-width:{0}px;"">", 
    widthpixels.ToString)
    Dim divclose As String = "</div>"

    For i As Integer = 0 To 7
      If i Mod 4 = 0 Then output.Append(divopen)
        If i Mod 2 = 0 Then output.Append(divopen)
          output.Append(divopen)
          output.Append(Join(sublists(i).ToArray, "<br />"))
          output.Append(divclose)
        If i Mod 2 = 1 Then output.Append(divclose)
      If i Mod 4 = 3 Then output.Append(divclose)
    Next

    Return output.ToString
End Function

关注点

此方法的一个问题是换行使用模 2 进行,即 8 列列表换行到 4 列,然后是 2 列,然后是单列。然而,在每个阶段,包含列表项的底层 divs 使用的宽度始终正好等于或大于可用宽度的 50%。虽然希望有一个能将 8 列换行到 7 列等的解决方案,但从视觉角度来看,这种方法效果相当好。

注意:请注意,上图中所示的边距和彩色边框不应使用。换行的 divs 必须没有边框或边距,否则 50% 的宽度值将不再正确。如果你想“装饰”列表项块,则应使用最内层浮动 divs 中的进一步标记,但是任何水平装饰都会在很大程度上削弱分开的块换行到彼此下方以产生连续垂直列表效果的目的。

使用 CSS 创建流畅的、多列的、垂直排序的列表 - CodeProject - 代码之家
© . All rights reserved.