tags:

views:

629

answers:

4

I have multiple floating div tags and I want to have them stack on top of each other from left to right so that they look like text in a newspaper. The difficulty is that if I float the divs then they go from left to right and if I don’t do this then they simply stack on top of each other. Is there a way to get them to stack evenly from left to right?

 <div>
        <br />
        <br />
        <style type="text/css">
            .mainpanel
            {
                display: block;
                border-left-width: 1px;
                border-left-color: Black;
                border-left-style: double;
                padding: 3px;
                float: left;
            }
        </style>
        <div style="" class="mainpanel">
            <div style="width: 245px; float: left; padding: 5px;">
                1
            </div>
            <div style="width: 245px; float: left; padding: 5px;">
                2
            </div>
            <div style="width: 245px; float: left; padding: 5px;">
                3
            </div>
            <div style="width: 245px; float: left; padding: 5px;">
                4
            </div>
            <div style="width: 245px; float: left; padding: 5px;">
                5
            </div>
            <div style="width: 245px; float: left; padding: 5px;">
                6
            </div>
            <div style="width: 245px; float: left; padding: 5px;">
                7
            </div>
            <div style="width: 245px; float: left; padding: 5px;">
                8
            </div>
            <div style="width: 245px; float: left; padding: 5px;">
                9
            </div>
        </div>
    </div>
A: 

I think this is outside CSS's defined responsibilities. You may have to dynamically generate it. Create a new <div> for a column element. Stack <div>s inside the columns individually. Then float the columns from left to right.

M456
+1  A: 

Maybe you should specify height such as a maximum limit and have no surprizes

Izabela
+1  A: 

For cross-browser-compatibility and with pure CSS? I don't think, and I'd love to be proven wrong, it's possible.

If you don't mind rendering differences then you could use -moz and -webkit options:

div#multicolumn1 {
        -moz-column-count: 3;
        -moz-column-gap: 10px;
        -webkit-column-count: 3;
        -webkit-column-gap: 10px;
        column-count: 3;
        column-gap: 10px;
}

div#multicolumn1 { -moz-column-count: 3; -moz-column-gap: 10px; -webkit-column-count: 3; -webkit-column-gap: 10px; column-count: 3; column-gap: 10px; }

<div id=multicolumn1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas iaculis nisl nec nunc. Nam id lacus et lectus molestie tristique. Nunc vel risus consequat nisi vehicula cursus. Proin metus augue, cursus vitae, feugiat quis, porttitor ac, elit. Nulla et dui in mi laoreet auctor. Ut imperdiet nisl ut sem. Maecenas sodales magna eu neque. Nulla sagittis. Donec nec eros quis ligula condimentum scelerisque. Ut venenatis orci non odio. Duis mauris velit, sagittis sit amet, fringilla vel, ornare id, ipsum. Aenean et purus. Curabitur in massa. Morbi egestas nibh sed libero. Cras volutpat. Cras vitae nulla id urna consequat bibendum. Nunc bibendum ultricies orci. Cras id lorem. Pellentesque vel nisi. Nulla ligula eros, aliquet sed, vestibulum non, ultrices id, odio. </p>
</div>

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas iaculis nisl nec nunc. Nam id lacus et lectus molestie tristique. Nunc vel risus consequat nisi vehicula cursus. Proin metus augue, cursus vitae, feugiat quis, porttitor ac, elit. Nulla et dui in mi laoreet auctor. Ut imperdiet nisl ut sem. Maecenas sodales magna eu neque. Nulla sagittis. Donec nec eros quis ligula condimentum scelerisque. Ut venenatis orci non odio. Duis mauris velit, sagittis sit amet, fringilla vel, ornare id, ipsum. Aenean et purus. Curabitur in massa. Morbi egestas nibh sed libero. Cras volutpat. Cras vitae nulla id urna consequat bibendum. Nunc bibendum ultricies orci. Cras id lorem. Pellentesque vel nisi. Nulla ligula eros, aliquet sed, vestibulum non, ultrices id, odio.

With luck, and presumably only in Webkit or Mozilla browsers, this should render on screen. For anyone using IE, well, you'll probably see why it's not cross-browser compatible, sadly.

There is a CSS3 proposal, though, so here's hoping: http://www.w3.org/TR/css3-multicol/.

Edit: props to Peter-Paul Koch, of http://www.quirksmode.org from which the above example was lifted in, more or less, its entirety. The source article is here: http://www.quirksmode.org/css/multicolumn.html.

David Thomas
...okay, the 'Lorem ipsum...' paragraph rendered as columns in the preview box. But not in the actual page. Hmm. Ah, well...it still works okay for Webkit (Midori) and Firefox (3.x) anyway. But not Opera (9.63, at least)...
David Thomas
A: 

While using CSS 3 would be nice I realize that at the moment this is not practical and that the standard is not being used yet. So, to resolve my problem I have taken to measuring the size of the content in my code behind and then adding a flag to the table which indicates if the column should be broken. This can be used with either Div tags or table cells. After using Div tags I switched to table cells because they were more consistent in display properties and also in how they render in email messages. In your aspx page place a repeater or list control inside of the first cell or div tag that the content should be rendered in:

<table cellpadding="2" cellspacing="0">
<tr valign="top" >
<td  runat="server" id="TopTD">
       <asp:ListView ID="List" runat="server">
            <LayoutTemplate>
                <asp:PlaceHolder ID="itemPlaceHolder" runat="server"></asp:PlaceHolder>
            </LayoutTemplate>
            <ItemTemplate>
             <asp:literal runat="server" id="divdivide"
             visible='<%# eval("BreakFields") %>' Text='<%# eval("DivTag")%>'></asp:literal>
<%# eval("Content")%>
            </ItemTemplate>
            <ItemSeparatorTemplate>
        </asp:ListView>
   </td>
</tr>
    </table>
</div>

In your code behind you need four things, a function to measure your content a table in which to stuff your content a property with the size of your columns a property with the number of columns to show

Measurement function:

Function stringSize(ByVal strTarget As String, ByVal strFont As String, ByVal sngFontSize As Single) As SizeF
        strFont = "Arial, Sans-Serif"
        Dim bitImg As New Bitmap(1, 1)
        Dim g As Graphics = Graphics.FromImage(bitImg)
        Dim f As New Font(strFont, sngFontSize)
        Dim size As SizeF
        g.PageUnit = GraphicsUnit.Pixel
        size = g.MeasureString(strTarget, f)

        Dim I As Int32

        If Not String.IsNullOrEmpty(strTarget) Then
            Dim Re As New Regex(vbCrLf)
            I = Re.Matches(strTarget).Count
        End If
        If ColumnWidth > 0 Then
            size.Height = (size.Height * (Math.Ceiling(size.Width / ColumnWidth))) + (I * 20)
            size.Width = ColumnWidth
            Else
            size.Height = (size.Height * (Math.Ceiling(size.Width / DefaultSize))) + (I * 20)
            size.Width = DefaultSize
        End If
        g.Dispose()
        bitImg.Dispose()
        f.Dispose()

        Return size
    End Function
Public ColumnWidth() As Int32

When you are getting your data to display you need to put it into a table and measure it.

Dim DT As New DataTable
DT.Columns.Add("Content", GetType(Int32))
DT.Columns.Add("Height", GetType(Int32))
DT.Columns.Add("BreakFields", GetType(Boolean))
Dim Row As DataRow
For Each itemtodisplay
Row = DT.NewRow
      Row("Content") = itemtodidisplay
      Row("Height") = 0
      Row("Height") += Fix(stringSize(itemtodisplay, "Arial", 10).Height)
      Row("Height") += 10
      HeightCounter += Row("Height")
      DT.Rows.Add(Row)
Next
BindItems(DT, Top, StartDate)

Use this to actually create the table to bind to the list control

Private Sub BindItems(ByVal DT As DataTable)
        If ColumnCount <= 0 Then
            ColumnCount = 1
        End If

        Dim I As Int32
        Dim HeightBreak As Int32 = (HeightCounter / ColumnCount) + 40
        Dim CurrentCol As Int32 = 1
        Dim Curheight As Int32
        I = 0
        Dim width As Int32
        If ColumnWidth > 0 Then
            width = ColumnWidth
        else
            width = DefaultSize
        End If
        If ColumnWidth > 0 Then
        TopTD.Width = width + 6
        DT.Columns.Add("DivTag", GetType(String))
        DT.Columns.Add("DivStyle", GetType(String))
        For Each Row In DT.Rows
            Row("DivStyle") = "width:" & width & "px; text-align:left;padding-bottom:3px;"
            If (Row("Height") + Curheight) > HeightBreak + 50 _
            And I > 0 _
            And ColumnCount > 1 _
                And CurrentCol < ColumnCount Then
                Row("BreakFields") = True
                Row("DivTag") = "</td><td width=" & width + 6 & ">"
                CurrentCol += 1
                Curheight = 0
            Else
                Row("BreakFields") = False
            End If
            I += 1
            Curheight += Row("Height")
        Next

        StoryList.DataSource = DT
        StoryList.DataBind()
    End Sub
Middletone
Would the person who downvoted this care to explain why they disagree wiht this. It has most certainly wokred for me.
Middletone