Thursday, May 5, 2011

How do I get data to flow from one div tag into another and balance the height between the two?

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>
From stackoverflow
  • 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.

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

  • 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)...
  • 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.

0 comments:

Post a Comment