CSS 3 Tables - Algorithms by ntz11397


									                    CSS 3 Tables – Algorithms
W3C Editors Draft

                    This version:
                    Latest version:
                    Previous version:
                          Shuo Dong           <shuodong@microsoft.com>
                          Markus Mielke       <mmielke@microsoft.com>
                          Erika Doyle         <edoyle@microsoft.com>
                          Alex Mogilevsky     <alexmog@microsoft.com>

                    The intent of this document is to provide a set of detailed algorithms which describe certain table layout
                    behaviors that are common to most major browsers today and propose additional standard behaviors in
                    order to achieve full browser interoperability in table layout. The Table layout algorithm is one of the
                    most used and most difficult to understand features in HTML, as there are no common behavior
                    descriptions in either HTML or CSS. The goal of this document is to introduce a focused discussion
                    around a unified table behavior with the goal of getting agreement on a set of scenarios for integration
                    into the CSS 3 Tables specification.

                    This document is not complete but it tries to capture the most common scenarios in which browsers
                    have achieved interoperability. Our hope is that this document is seen as a starting point to provide at
                    least a partial definition of table layout behavior, ten years after its introduction into the market.

                    Captions in visual formatting model
                    Captions above or below a 'table' element are formatted very much as if they were a block element
                    before or after the table, except that (1) they inherit inheritable properties from the table, (2) they are
                    not considered to be a block box for the purposes of any 'compact' or 'run-in' element that may precede
                    the table, and (3) they use the width of the anonymous box as input for its available width calculations.

                    The width of the anonymous box is the border-edge width of the table box inside it, as described by CSS
                    2.1 section 17.4. Percentages on 'width' and 'height' properties of the table are relative to the
                    anonymous box's containing block, not the anonymous box itself.

                    This algorithm follows the CSS 2.1 specification of the ‘caption-side’ property, where the only possible
                    values are ‘top’, ‘bottom’ and ‘inherit’. CSS 3 will also add ‘left’ and ‘right’. Thus in the algorithm
                    presented here, the caption width will not affect the table auto layout algorithm in any way. However,

the output of the table auto layout algorithm may affect the sizing of table caption, since it determines
the anonymous table box size.

In the following example, the 'caption-side' property places captions on top of tables. The caption will be
as wide as the anonymous box of the table, and caption text will be left-justified.

caption { caption-side: top;
          width: auto;
          text-align: left }

Example of the visual model:

Note: CSS3 might want to define a property that enables the developer to use the table's parent width
instead of the anonymous box width as an input in the caption width algorithm.

Considerations for the caption width algorithm

    1. Caption has either auto width or specified width in pixels (all other units can be converted into
    2. Padding, margin and border should behave like a normal block box and are covered by the CSS
       Box Model calculations.


    1. Table used width
    2. Caption specified width (if any)

Caption's used width

Naming conventions
Name                                   Explanation

captionSpecifiedWidth                  Input provided by the width property.

captionUsedWidth                       Output that determines the width of the caption algorithm.

contentMinWidth                        The minimal unit of breakable text (mostly the smallest word in the caption).

tableUsedWidth                         Input provided by table auto layout algorithm. This is the width actually used
                                       by the table.

The caption sizing algorithm can be summarized like this (ignoring possible constraints set by the ‘min-
width’ and ‘max-width’ properties) 1:

IF captionSpecifiedWidth exist
     captionUsedWidth = captionSpecifiedWidth
     captionUsedWidth = tableUsedWidth

   1. If captionSpecifiedWidth < contentMinWidth, caption's content may stick out of the caption's
      box (overflow will then apply).
   2. When captionSpecifiedWidth > tableUsedWidth, caption and its content may stick out of table's
      inner box - wider than the table.
   3. If tableUsedWidth < contentMinWidt also overflow will occur. This is the same as with normal
      block level elements
   4. Specified Percentage width will be calculated based on tableUsedWidth


Test Case                                               Gran       Firefox     Opera       Safari     Internet
http://www.glowsoft.com/tests/                          Paradiso                                      Explorer
    1.   captionUsedWidth = captionSpecifiedWidth       Yes        Yes         Yes         Yes        No
    2.   captionUsedWidth = tableUsedWidth              Yes        Yes         Yes         No         No

In the absence of a specified width, the caption is sized to the tableUsedWidth, which in general follows
the behavior of block level elements as described in 10.3.3 in the CSS2.1 specifications:

'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' +
'margin-right' + scrollbar width (if any) = tableUsedWidth

If 'width' is not 'auto' and 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-
width' + scrollbar width (if any) (plus any of 'margin-left' or 'margin-right' that are not 'auto') is larger
than the width of the tableUsedWidth, then any 'auto' values for 'margin-left' or 'margin-right' are, for
the following rules, treated as zero.

 If all of the above have a computed value other than 'auto', the values are said to be "over-constrained"
and one of the used values will have to be different from its computed value. If the 'direction' property
of the containing block has the value 'ltr', the specified value of 'margin-right' is ignored and the value is
calculated so as to make the equality true. If the value of 'direction' is 'rtl', this happens to 'margin-left'

If there is exactly one value specified as 'auto', it’s used value follows from the equality.

If 'width' is set to 'auto', all other 'auto' values become '0' and 'width' follows from the resulting

If both 'margin-left' and 'margin-right' are 'auto', their used values are equal. This horizontally centers
the element with respect to the edges of the tableUsedWidth.

The "scrollbar width" value is only relevant if the user agent uses a scrollbar as its scrolling mechanism.
See the definition of the 'overflow' property.

Automatic Table Layout Algorithm Overview
The design of the following algorithm is based upon the CSS 2.1 recommended algorithm
(http://www.w3.org/TR/CSS21/tables.html#width-layout), the HTML 4.1 recommended algorithm
(http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.5.2 ), and an interoperability analysis of
Internet Explorer 7, Firefox 3 Alpha, Opera 9, and Safari 3 Beta. The goal of this design is to stick to the
CSS 2.1 and HTML 4.1 recommendations as close as possible while also accommodating the common
behaviors of the major browsers.

 This specification uses a “pseudo algorithm” to help describe the behavior for auto table layout
calculations. Whenever this document uses the term ‘algorithm’, it is really referring to this “pseudo
algorithm”. Each browser is of course free to provide its own algorithm, and need not implement the
pseudo algorithm literally as it is described here.

The algorithm uses several types of inputs: the intrinsic characteristics of table cells (i.e., the minimum
and maximum widths of their content), the value of each cell’s column-spanning (‘colspan’) attribute (if
any is set), and the specified ‘width’, minimum width (‘min-width’) and maximum width (‘max-width’) of
each table cell and the table itself. The output of the algorithm is the final used width of the table and
each of its columns.

Naming Conventions
Name                           Explanation
cellContentMaxWidth            cell’s max width computed from content (Intrinsic Max width)
cellContentMinWidth            cell’s min width computed from content (Intrinsic Min width)
cellMaxWidth                   cell’s max width
cellMinWidth                   cell’s min width
cellSpecifiedMaxWidth          cell’s specified max width (pixel width)
cellSpecifiedMinWidth          cell’s specified min width (pixel width)
cellSpecifiedWidth             cell’s specified pixel width
columnAutoTotalMaxWidth        auto column’s total max width
columnAutoTotalMinWidth        auto column’s total min width
columnAutoTotalUsedWidth       auto column’s total used width
columnMaxWidth                 column’s max width
columnMinWidth                 column’s min width
columnNonPercentTotalPercent   non percent column’s remaining percentage calculated from
                               specified percent column
columnPercentTotalPercent      specified percent column’s total percent
columnPercentTotalUsedWidth    specified percent column’s total used width
columnPixelTotalMaxWidth       specified pixel column’s total max width
columnPixelTotalMinWidth       specified pixel column’s total min width
columnPixelTotalUsedWidth      specified pixel column’s total used width
columnSpecifiedPercent         column’s specified percent width
columnSpecifiedWidth           column’s specified width (accumulated specified width from
                               cells in the same column)
columnUsedWidth                column’s used width
percentagePreferedTableWidth   table width preferred by specified percent column
Preferred width                Formatting the content without breaking lines other where
                               explicit line beak occur
tableAvailableWidth            table’s available width
tableMaxWidth                  table’s max width (accumulated max width from each column)
tableMinWidth                  table’s min width (accumulated min width from each column)
tableSpecifiedMaxWidth         table’s specified max width (pixel width)
tableSpecifiedMinWidth         table’s specified min width (pixel width)
tableSpecifiedWidth            table’s specified width (pixel width)
tableUsedWidth                 table’s used width

List of scenarios handled by this algorithm
This document is considering the following author inputs into the algorithm:

Cell                       Pixel                     Percentage                Auto
min-width                                           N/A*                      
max-width                                           N/A*                      
Width                                                                        
* Due to the current lack of implementations, percentage values are not defined

Col/ColGroup               Pixel                       Percentage                  Auto
min-width                   Cascaded **                 Cascaded                   Cascaded
max-width                   Cascaded                    Cascaded                   Cascaded
Width                       Cascaded                    Cascaded                   Cascaded
** A Cell value will overwrite Col value, which will overwrite ColGroup as part of the cascade. This is an
alternative proposal to the current CSS2.1 definition

Table                      pixel                       Percentage                  Auto
min-width                                                                        
max-width                                                                        
Width                                                                            

The output will be:
     The table’s final used width
     Each column’s final used width

This will enable the following scenarios:

       Table with the above specified inputs
       Column-spanning scenarios, where the width on column spans can be expressed in pixels, auto
        or percentages
       Simple nested table scenarios, as long as the intrinsic content width can be determined

Scenarios that are not fully supported yet by this algorithm:

       Overlapping spans (these work but do not produce an “exact” result)
       Border ‘width’(not taken into account, as it should be an easy addition)
       Cel padding (especially in percent)
       Cellspacing

Algorithm Summary
Table auto layout calculation is achieved with the following steps.

    1. Calculate each cell’s minimum width and maximum (preferred) width by examining the cell’s
       content and its width/min-with/max-width properties.
    2. Identify the minimum, and maximum (preferred) and specified width of each column in the
       table by finding the largest minimum width and largest maximum and specified widths among
       all cells in the column In this step, the algorithm first goes over all cells with colspan equal to
       one and then distributes the impact of all cells with colspan > 1 to each column the cell is
       spanning to.
    3. With each column’s minimum width and maximum (preferred) width, calculate the table’s
       minimum width and maximum (preferred) width
    4. Determine the table’s final used width by attempting to satisfy each column’s preferred width
       as much as possible.
    5. Decide how to distribute the table’s final used width among all the columns. During this
       process, columns with specified percentage width are given first priority, followed by the
       columns with specified pixel width. Columns with unspecified width (or width set to ‘auto’) get
       the remaining width.
    6. Distribute any rounding errors introduced during distribution in the previous step and adjust
       each column’s width accordingly. This is currently not part of this proposal.

What follows is the proposed algorithm in finer detail.

Step 1: Calculate each cell’s minimum and maximum (preferred) width
This step calculates table width limitation and preference at the cell level. These values are computed
for each cell based on its content (intrinsic) min/max width, its specified width (if any), and its specified
‘min-width’ and ‘max-width’ (if any). In summary, cell minimum width is calculated according to this

cellMinWidth = max(cellContentMinWidth, cellSpecifiedMinWidth) 2

And cell maximum width is calculated according to this function:

cellMaxWidth = max(cellMinWidth, min(cellSpecifiedMaxWidth, cellSpecifiedWidth (or
cellContentMaxWidth if no cellSpecifiedWidth exists)))3

The cell’s minimum width is calculated before the cell’s maximum width, so that the minimum width can
set a lower limit for the maximum width.

In the cellMaxWidth calculation, when the cell has a specified width, the algorithm lets the specified
width override the cell’s content/intrinsic max width because cellSpecifiedWidth and
cellContentMaxWidth are both about the cell’s preferred width and specified width has higher priority
than intrinsic max width.

cellContentMinWidth/cellContentMaxWidth will be calculated based on CSS2.1 Spec. The algorithm
doesn’t try to specify how to calculate them here. These calculations are following the regular CSS2.1
block model calculations (see 10.3.5 and 10.3.7 for comparison).

Each cell’s minimum width sets the lower limit for that cell. (A cell can never be narrower than its
minimum width.) This is a design decision drawn from a backwards compatibility / interoperability
analysis. It could be argued that ‘display: table-cell’ does have an overflow property and that it is thus
not necessary to always honor minimum width. The algorithm here, however, suggests ignoring
overflow property on table cell and respect minimum width for best backward compatibility and
readability. This of course, is open for discussion.


Test Case                                                       Gran          Firefox       Opera           Safari        Internet
http://www.glowsoft.com/tests/                                  Paradiso                                                  Explorer
     1.   cellMinWidth = cellContentMinWidth                    Yes           Yes           Yes             Yes           No
     2.   cellMinWidth = cellSpecifiedMinWidth                  Yes           No            No              Yes           No


Test Case                                                       Gran          Firefox       Opera           Safari        Internet
http://www.glowsoft.com/tests/                                  Paradiso                                                  Explorer
     3.   cellMaxWidth = cellContentMaxWidth                    Yes           Yes           Yes             Yes           Yes
     4.   cellMaxWidth = cellSpecifiedWidth                     Yes           Yes           Yes             Yes           Yes
     5.   cellMaxWidth = cellSpecifiedMaxWidth                  Yes           No            No              Yes           No
     6.   cellMaxWidth = cellMinWidth                           No**          No            No              No**          No
** Gran Paradiso Alpha and Safari honor the specied ‘min-width’ when it is smaller than content minimum width and overflow the content.

Each cell’s maximum width sets the preferred width of the cell (which the algorithm then tries its best to
satisfy). The maximum/preferred width is not an upper limit of the cell because other cells in the same
column and the table’s overall preferred width could cause the cell to be assigned a width exceeding this

Specified percentage ‘width’, ‘min-width’ and ‘max-width’ are not taken into consideration here because
the goal is to find only unit value minimum and maximum width. Percentages will be dealt with in the
following steps, where each column’s minimum, maximum and specified width is calculated.

At the current stage, the algorithm hasn’t considered any border/padding/margin or
cellpadding/cellspacing. They will impact the calculation of cellMinWidth / cellMaxWidth according to
the CSS box model. These inputs can be added later to the algorithm.

Step 2: Identify the minimum, maximum (preferred) and specified width
of each column

In this step, the algorithm collects the limitation and preference on a cell level and aggregates them up
to the column level. The goal is to have the minimum, maximum (or preferred width) and specified with
of each column. To simplify the calculations and better understand behavior, the algorithm defines
three types of columns:

1. auto column: all cells in the column have either ‘width: auto’ or no specified width

2. specified pixel column: at least one cell in the column has a specified width in pixels and no cells
   have specified width in percent. (Specified widths can be cascaded or inline.)

3. specified percent column: at least one cell in the column has a specified width in percent

This step can be summarized in three equations:

            1. columnMinWidth = max (cellMinWidth of all cells in the column)
            2. columnMaxWidth = max(cellMaxWidth of all cells in the column)
            3. columnSpecifiedWidth = max(cellSpecifiedWidth of all cells in the column)

Note that in step 3, a specified percentage cell has a higher priority than a specified pixel cell. That
means one specified percentage width cell will make the column a specified percent column even all the
other cells have specified pixel width. For specified pixel column, columnSpecifiedWidth is max of cell’s
specified pixel width. For specified percent column, columnSpecifiedWidth is the max of the cell’s
specified percentage, the algorithm doesn’t convert percentage to pixel value in this step. Only non-
negative percentage value are taken into consideration. It may happen that the percentage value
exceeds 100%, or the sum of all column’s specified percentage value exceeds 100%. Cases like these will
be handled in a subsequent step.

When applying the algorithm, the column’s minimum width sets the lower limit on column’s used width.
This means the column can never be smaller than its minimum width, in order to prevent overflow of
the text into neighboring cells. This is a design decision to enable better readability. The column’s
maximum width defines the preferred width of a column, which this algorithm tries to honor when
there is no specified width or the specified width cannot be satisfied. The specified width is taken as the
author’s desired width of the column and need to be balanced across all cells in this column.

Calculating the minimum, maximum and specified width for a column that only spans one cell is
straightforward and follows the simple rules outlined above. Multiple spanning columns, which are
calculated next, require more work. The proposed algorithm handles cell with colspan > 1 one by one
without any optimization of overlapped colspan. The result may not be optimum. The working group
may decide to design a better algorithm so that the rendering of the overlapped colspan will be optimal.

The algorithm first checks to see if any cells spanning multiple columns will affect the min/max/specified
widths of the columns they span. In cases like these, it must distribute the impact of the multi-column
cell to all of the columns it spans. There are several ways how this can be done. The method outlined in
this spec was chosen based on browser interoperability. In general, the algorithm will distribute the
impact evenly or proportionally with each column’s max width, (max width – min width) or min width
depending on the case. When the algorithm distributes the impact of the multi-column cell, the
column’s min/max width are the solely contributors to the distribution. The impact of a multi-column
cell’s specified pixel width will be calculated into its columns’ max (or preferred) width . The impact of a
multi-column cell’s specified percentage width will be distributed proportionally to each non-percentage
column that is spanned by the multi-column cell.

When calculating the impact of the multi-column cell on the columns, the algorithm adjust min width
first, max width second and percentage last. This follows the guidelines for min/max width calculations
of CSS2.1 Chapter 10.4 (http://www.w3.org/TR/CSS21/visudet.html#min-max-widths). This enables max
width to be restricted by min width. The distribution of specified width in percentage will now depend
on the newly adjusted min/max values.

As in step 1, the algorithm doesn’t yet consider any border/padding/margin or cellpadding/ cellspacing.
These inputs should impact the calculation of columnMinWidth/ columnMaxWidth/
columnSpecifiedWidth according to CSS box model, and can be added in future version of this

Step 3 Calculate tableMinWidth/tableMaxWidth
This step calculates the table’s minimum-width which is the lower limit of the table and table’s
maximum width, which is the preferred width.

At this stage, the algorithm simply adds up the previously calculated column’s min/max width to get the
table’s min/max width. Note that the table’s preferred width (max width) only takes pixel value. This is
the preferred table width from the auto columns and specified pixel columns. The percentage column
preferred table width will be calculated in later steps of this algorithm.

The CSS border, padding, and margin properties and HTML cellpadding and cellspacing attributes will all
have an impact on the calculation of this step, and should be detailed in a future version of this

Step 4: Determine the table’s final used width
In order to determine the table’s final used width, the algorithm needs to calculate the “ideal” width of
the table—the width which would provide each column with its preferred width without violating any
constrains. To do this, table columns are categorized into one of three types (this is identical to step 2
but repeated here for better understanding):

    Pixel columns—columns in which one or more cells has a specified width in pixels and all other cells
    either have no specified width or have a specified width of ‘auto’

    Percent columns—column in which at least one cell has a specified width in percentage

    Auto columns—columns in which all cells have either no specified width or have a specified width of

For each of these column types, the minimum and maximum (preferred) widths (of each column of the
given type) are accumulated. At this step, the algorithm is simplifying the problem here by “pretending”
that the table has only three columns which are referred to below as columnPixelTotal,
columnPercentTotal and columnAutoTotal, and each of these columns has a minimum width and
preferred width. Because it is making a demand on how wide it should be in relation to the rest of the
table, calculating the columnPercentTotal ‘s preferred width in pixels requires the additional step of
calculating its preferred width for the entire table. This is achieved by identifying the percent column
which demands the largest width of the table (largest column maximum width to column specified
percentage ratio), and using its preferred table width as the overall columnPercentTotal’s preferred
table width.

With a clear picture of the limitations and preferences of each of the three types of columns, the table’s
final used width can now be determined from the following guidelines:

    1. When the table has a specified width, use this number as the final table used width,
       unless it is smaller than table’s minimum width. In that case, take the table’s minimum
       width as the table’s used width. If the table has a specified width in percentage, convert
       this to a pixel value based on the table’s available width.

         tableUsedWidth = max(minimum width, specified width)4


Test Case                                         Gran        Firefox    Opera        Safari     Internet
http://www.glowsoft.com/tests/                    Paradiso                                       Explorer
    7.   tableUsedWidth = tableSpecifiedWidth     Yes         Yes        Yes          Yes        Yes
    8.   tableUsedWidth = tableMinWidth           Yes         Yes        Yes          Yes        Yes

    2. In general, when the table has auto (or non-specified) width, use the shrink-to-fit rule to
       determine table’s used width:

         tableUsedWidth = min(max(minimum width, available width), preferred width)5

         There are three specific cases to address, each with a different way of determining the
         table preferred width:

             i.    When there are no specified percent columns, the preferred table width is
                   simply the tableMaxWidth calculated from last step

            ii.    When there are specified percent columns, these columns will have a preference
                   for table’s used width. Percentage columns have higher priority than other
                   columns, the algorithm needs to find the percentage column with the greatest
                   width demands of the table, and use its preferred table width as the final table’s
                   preferred width. Non-percent columns have the remaining percentage and their
                   preference should also be considered. That is if the non-percent columns’ total-
                   max-width-to-percentage ratio is greater than that of this number calculated
                   from percent columns, then use that larger width instead. (Anything larger than
                   the largest percentage column ratio can automatically satisfy that ratio as well).

           iii.    Because the algorithm does not allow the sum of specified percentages to be
                   larger than 100%, a special case might arise where the percent columns are
                   demanding the full table width (100%) but there are also non-percent columns
                   which require at least their minimum width. In this case, the table’s preferred
                   width could never be satisfied. The algorithm treats table’s preferred width as
                   infinitely large and put it in the shrink-to-fit formula. (Table’s used width would
                   have to be assigned either its minimum width or available width (whichever is

    3. This algorithm strictly follows the ‘min-width’/’max-width’ rule defined in section 10.4
       of the CSS 2.1 spec to adjust the table’s used width by its specified ‘min-width’ and
       ‘max-width’ as needed. When these values are in percentages, the algorithm converts
       them to a pixel value based on the table’s available width.


Test Case                                                  Gran       Firefox   Opera   Safari   Internet
http://www.glowsoft.com/tests/                             Paradiso                              Explorer
    9. tableUsedWidth = tableMinWidth                      Yes        Yes       Yes     Yes      Yes
    10. tableUsedWidth = tableAvailableWidth               Yes        Yes       Yes     Yes      Yes
    11. tableUsedWidth = tableMaxWidth (preferred width)   Yes        Yes       Yes     Yes      Yes

        In other words, if tableUsedWidth is larger than the specified max width, use ‘max-
        width’as specified width and recalculate tableUsedWidth.

        If tableUsedWidth is smaller than the specified min width, use ‘min-width’ as specified
        width and recalculate tableUsedWidth.

    4. When the sum of specified percent exceeds 100%, the algorithm recommends that the
       browser ignore all specified percentages coming after the sum reaches 100% and regard
       them as having 0% specified percent width. (These columns will still be rendered, but
       not given their specified percentages).

    5. When there are only specified percent columns and the sum of the percent is smaller
       than 100%, the algorithm recommends that the browser alter the column percentages
       proportionally to make their sum equal to 100%.

    6. Border, margin and padding will have an impact on this step (as is specified in the CSS
       box model, and this needs to be accounted for in a future version of this document.

Step 5: Distribute the table’s final used width among all of the columns

During the process of distributing the table’s used width among all the columns, it is likely that not
every column will get its preferred width—the table’s final used width may not be big enough
to allow for that. To handle these cases, the algorithm first attempts to satisfy the preferred
widths of specified percent columns without sacrificing the minimum width of non percent
columns. If that is possible, it then tries to satisfy the preferred widths of specified pixel
columns without sacrificing the minimum width of auto columns.

The algorithm uses a two-step distribution process. First, the table’s used width is divided
among each of the three types of columns (specified percent, specified pixel and auto). This
step yields the total used width of the specified percent columns, the total used width of the
specified pixel columns and the total used width of the auto columns. Second, the total used
width for each column type is distributed among all the columns of that type.

    1. The algorithm first calculates the total used width of specified percent columns.

        percentColumnTotalUsedWidth = min (percent column total preferred width*,
        (tableUsedWidth – non-percent column’s total min width))

        *Percent column total preferred width = tableUsedWidth x percent column’s total percent

   The total minimum width of the non-percent columns (i.e., specified pixel and auto
   columns) constrains the maximum total width of percent columns. In other words, the
   algorithm guarantees that every non-percent column will get at least its minimum width
   before any percent column preferred widths are satisfied.

   Notice that the algorithm does not consider percent column’s minimum width when
   determining percentColumnTotalUsedWidth. When assigning each percent column’s
   used width, the minimum width is considered. As a result, the algorithm may need to
   adjust percentColumnTotalUsedWidth according. Hence it is necessary that the
   algorithm determines each percent column’s used width before determine pixel/auto
   column’s total used width.

2. The total used width of percent columns is distributed proportionally among each of the
   percent columns (i.e., according to each column’s specified percent) unless the
   computed result is smaller than the column’s minimum width. In these cases, the
   column is assigned its minimum width.

   columnUsedWidth = max(columnMinWidth, percentColumnTotalUsedWidth x
   columnSpecifiedPercent / percentColumnTotalSpecifiedPercent)

   As a consequence of this adjustment, the total used width of percent columns must be
   increased, which means that the non-percent columns must give up some of their
   width. When there is no remaining width to take from the non-percent columns
   (without giving them less than their minimum widths), width must be taken from
   percent columns. In this case, the difference should be taken from percent columns
   evenly without scarifying their minimum width.

3. After determining the widths of percent columns, the algorithm then calculates the total
   used width of specified pixel columns according to this equation:

   columnPixelTotalUsedWidth = min (columnPixelTotalMaxWidth,
   columnNonPercentTotalUsedWidth – columnAutoTotalMinWidth)

   Note that the columnPixelTotalMaxWidth is the preferred total width. The algorithm
   takes the preferred total width unless it would cause auto columns to get less than their
   minimum width.

4. Auto columns get the remaining width of table used width

   columnAutoTotalUsedWidth = columnNonPercentTotalUsedWidth –

5. When dividing up the width among individual auto columns and pixel columns, the
   algorithm chooses from one of four methods of distribution:

          i.    MIN : Used when the total width to distribute is equal to the total minimum
                width of all the columns of that type. Each column gets its minimum width.

          ii.   MAX: Used when the total width to distribute is equal to the total maximum
                width of all the columns of that type. Each column gets its maximum (preferred)

         iii.   MAX_ADDITION: Used when the total width to distribute is larger than the total
                maximum width of all the columns of that type. Each column gets its maximum
                width plus some extra width. The extra width is divided among columns
                proportionally according to their maximum widths.

         iv.    MIN_ADDITION: Used when the total width to distribute is larger than total
                minimum width but smaller than the total maximum width. Each column gets its
                minimum width plus some extra width. The extra width is divided among
                columns proportionally according to the difference between their maximum-
                minus-minimum widths.

Step 6: Distribute any rounding errors
At this stage the UA only has to deal with rounding errors that have arisen as part of multiplications/
divisions and other adjustments during the calculations. These kinds of errors occur when the sum of
the all columns’ used widths is not equal to the table’s used width. This document does not
propose guidelines on how to implement rounding errors. The Working Group might decide to
give a preferred treatment of rounding errors as part of this document.

Appendix A: Auto-table algorithm in pseudo code

Step 1: Calculate each cell’s minimum and maximum (preferred) width
FOR EACH row in the table
      FOR EACH cell in the row
            calculate cellContentMinWidth/cellContentMaxWidth
                    cellMinWidth = cellContentMinWidth
                    cellMaxWidth = cellContentMaxWidth

                    IF cellSpecifiedMinWidth exists AND cellSpecifiedMinWidth > cellMinWidth
                            cellMinWidth = cellSpecifiedMinWidth

                    IF cellSpecifiedWidth exists and in pixel
                            cellMaxWidth = cellSpecifiedWidth

                    IF cellSpecifiedMaxWidth exists AND cellSpecifiedMaxWidth < cellMaxWidth
                            cellMaxWidth = cellSpecifiedMaxWidth

                    IF cellMaxWidth < cellMinWidth
                            cellMaxWidth = cellMinWidth

Step 2: Identify the minimum, maximum (preferred) and specified width of
each column
columnMinWidth = 0
columnMaxWidth = 0
columnSpecifiedWidth = Not Set

Step 2.1 accumulate from colspan ==1 cells only
FOR EACH column in the table
      FOR EACH colspan ==1 cell in the column
            IF cellSpecifiedWidth exists
                    IF columnSpecifiedWidth not set
                            colunnSpecifiedWidth = cellMaxWidth
                            IF cellSpecifiedWidth is in pixel and columnSpecifiedWidth is in pixel
                                    columnSpecifiedWidth = max(cellMaxWidth, columnSpecifiedWidth)
                            ELSE IF cellSpecifiedWidth is in percent and columnSpecifiedWidth is in percent
                                    columnSpecifiedWidth = max(cellSpecifiedWidth, columnSpecifiedWidth)
                            ELSE IF cellSpecifiedWidth is in percent and columnSpecifiedWidth is in pixel
                                    columnSpecifiedWidth = cellSpecifiedWidth
                            ELSE //cellSpecifiedWidth is in pixel and columnSpecifiedWidth is in percent
                                    do nothing

             columnMinWidth = max(cellMinWidth, columnMinWidth)
             columnMaxWidth = max(cellMaxWidth, columnMaxWidth)

             columnMaxWidth = max (columnMaxWidth, columnMinWidth)

Step 2.2 adjust columnMinWidth, columnMaxWidth, columnSpecifiedWidth by colspan > 1
FOR EACH column in the table
      FOR EACH colspan > 1 cell in the column
            Do the following steps

Step 2.2.1 Calculate columnSpannedTotalMinWidth, columnSpannedTotalMaxWidth,
columnPercentSpannedTotalPercent, etc
FOR EACH column spanned by the cell
      columnSpannedTotalMinWidth += columnMinWidth
      columnSpannedTotalMaxWidth += columnMaxWidth

      IF colspan cell has specified percent width
              IF column is specified percent
              ELSE //column is non percent
                      columnNonPercentSpannedTotalMaxWidth += columnMaxWidth

Step 2.2.2 Adjust columnMinWidth
IF cellMinWidth > columnSpannedTotalMinWidth
        minWidthToDistribute = cellMinWidth – columnSpannedTotalMinWidth
IF cellMaxWidth > columnTotalSpannedMaxWidth
        maxWidthToDistribute = cellMaxWidth – columnSpannedTotalMaxWidth

IF minWidthToDistribute > 0
      minWidthDistributed = 0

      FOR EACH column covered by the cell
            IF maxWidthToDistribute > 0 // proportionally with max width
                   columnMinWidthToDistribute = minWidthToDistribute x columnMaxWidth /
            ELSE IF columnTotalMaxWidth – columnTotalMinWidth > 0 // proportionally with max-min
                   columnMinWidthToDistribute = minWidthToDistribute x (columnMaxWidth -
                   columnMinWidth) / (columnSpannedTotalMaxWidth – columnSpannedTotalMinWidth)
            ELSE IF columnTotalMinWidth > 0 // proportionally to min
                   columnMinWidthToDistribute = minWidthToDistribute x columnMinWidth /
            ELSE // evenly
                   columnMinWidthToDistribute = minWidthToDistribute / columnSpannedCount

             minWidthDistributed += columnMinWidthToDistribute
             columnMinWidth += columnMinWidthToDistribute

             IF columnMinWidth > columnMaxWidth
                    columnMaxWidthOld = columnMaxWidth

                    columnMaxWidth = columnMinWidth
                    maxWidthDistributed += columnMaxWidth – columnMaxWidthOld

      IF minWidthDistributed < minWidthToDistribute // distribute rounding errors to last column
            columnLastMinWidth += minWidthToDistribute – minWidthDistributed
            IF columnLastMinWidth > columnMaxWidth
                   columnMaxWidthOld = columnMaxWidth
                   columnMaxWidth = columnMinWidth
                   maxWidthDistributed += columnMaxWidth - columnMaxWidthOld

Step 2.2.3 Adjust columnMaxWidth
maxWidthToDistribute -= maxWidthDistributed
columnTotalMaxWidth += maxWidthDistributed
maxWidthDistributed = 0
IF maxWidthToDistribute > 0
      FOR EACH column covered by the cell
            IF columnSpannedTotalMaxWidth > 0 //proportionally
                    columnMaxWidthToDistribute = maxWidthToDistribute x columnMaxWidth /
            ELSE // evenly
                    columnMaxWidthToDistribute += maxWidthToDistribute / columnSpannedCount

             columnMaxWidth += columnMaxWidthToDistribute
             maxWidthDistributed += columnMaxWidthToDistribute

      IF maxWidthDistributed < maxWidthToDistribute //distribute rounding errors to last column
            columnLastMaxWidth += maxWidthToDistribute – maxWidthDistributed

Step2.2.4 Adjust columnSpecifiedWidth
IF colspan cell has specified percent width
        cellRemainingPercent = cellSpecifiedPercent – columnPercentSpannedTotalPercent
        IF cellRemainingPercent > 0 AND columnNonPercentSpannedCount > 0
                percentDistributed = 0
                FOR EACH column
                       IF column is non-percent
                              IF columnNonPercentSpannedTotalMaxWidth > 0
                                     columnSpecifiedPercent = cellRemainingPercent x columnMaxWidth /
                                     columnSpecifiedPercent = cellRemainingPercent /

                           percentDistributed += columnSpecifiedPercent

             IF percentDistribued < cellRemainingPercent // distribute rounding errors to the last column
                    columnLastSpecifiedPercent += cellRemainingPercent – percentDistributed

Step 3 Calculate tableMinWidth/tableMaxWidth
tableMinWidth = sum(columnMinWidth)
tableMaxWidth = sum(columnMaxWidth)

Step 4: Determine the table’s final used width
Step4.1 Calculate auto column/specified-pixel column ‘s total min/max width and specified
percent column’s total percent and preferred table width
columnPixelTotalMinWidth = sum ( columnMinWidth of specified pixel columns)
columnPixelTotalMaxWidth = sum(columnMaxWidth of specified pixel columns)

columnPercentTotalPercent = sum(columnSpecifiedPercent of specified percent columns)
percentagePreferedTableWidth = max (columnMaxWidth /columnSpecifiedPercent of specified percent columns)

columnAutoTotalMinWidth = sum ( columnMinWidth of auto columns)
columnAutoTotalMaxWidth = sum ( columnMaxWidth of auto columns)

Step 4.2 Calculate tableUsedWidth
IF tableSpecifiedWidth exist
        tableUsedWidth = max(tableMinWidth, tableSpecifiedWidth)
        IF there is no specified percent column
               tableUsedWidth = min(tableMaxWidth, max(tableMinWidth, tableAvailableWidth))
        ELSE // there is specified percent column
               columnNonPercentTotalPercent = 100 – columnPercentTotalPercent

             IF columnNonPercentTotalPercent == 0 and there are non-percent column
                    tableUsedWidth = max(tableMinWidth, tableAvailableWidth)
             ELSE //columnNonPercentTotalPercent > 0 OR there are only percent column
                    IF columnNonPercentTotalPercent > 0
                           IF columnPixelTotalMaxWidth + columnAutoMaxWidth /
                           columnNonPercentTotalPercent > percentagePreferedTableWidth
                                  percentagePreferedTableWidth = (columnPixelTotalMaxWidth +

                          tableUsedWidth = min(percentagePreferedTableWidth, max(tableMinWidth,

IF tableSpecifiedMaxWidth exist AND tableSpecifiedMaxWidth < tableUsedWidth
         tableUsedWidth = max(tableMinWidth, tableSpecifiedMaxWidth)

IF tableSpecifiedMinWidth exist AND tableSpecifiedMinWidth > tableUsedWidth
         tableUsedWidth = tableSpecifiedMinWidth

Step 5: Distribute the table’s final used width among all of the columns
Step 5.1 Calculate specified-percent column’s total used width
IF all columns are percent
         columnPercentTotalUsedWidth = tableUsedWidth
ELSE IF no column are percent
         columnPercentTotalUsedWidth = 0
         columnPercentTotalPreferedWidth = tableUsedWidth x columnPercentTotalPercent / 100
         columnNonPercentTotalMinWidth = columnPixelTotalMinWidth + columnAutoTotalMinWidth
         columnPercentTotalMaxWidth = tableUsedWidth – columnNonPercentTotalMinWidth
         columnPercentTotalUsedWidth = min(columnPercentTotalMaxWidth, columnPercentTotalPreferedWidth)

Step 5.2 Calculate specified percent column’s used width
columnPercentTotalUsedWidthDiff = 0

FOR EACH column in the table
      IF it is a specified-percent column
                columnUsedWidth = columnPercentTotalUsedWidth x columnSpecifiedPercent /
                IF columnUsedWidth < columnMinWidth
                        columnPercentTotalUsedWidthDiff += columnMinWidth – columnUsedWidth
                        columnUsedWidth = columnMinWidth

Step 5.3 Calculate non-percent column’s total used width
columnNonPercentTotalUsedWidth = tableUsedWidth - columnPercentTotalUsedWidth
IF columnPercentTotalUsedWidthDiff > 0
       IF columnNonPercentTotalUsedWidth – columnPercentTotalUsedWidthDiff >
              columnNonPercentTotalWidth -= columnPercentTotalUsedWidthDiff
              columnPercentTotalUsedWidthDiff -= columnNonPercentTotalWidth –
              columnNonPercentTotalWidth = columnNonPercentTotalMinWidth

Step 5.4 Calculate specified-pixel column and auto column’s total used width
IF there is specified pixel column
       IF there is auto column > 0 // has auto column
               columnPixelTotalUsedWidth = min (columnPixelTotalMaxWidth, columnNonPercentTotalUsedWidth
               – columnAutoTotalMinWidth)

              columnAutoTotalUsedWidth = columnNonPercentTotalUsedWidth – columnPixelTotalUsedWidth
       ELSE // no auto column
              columnAutoTotalUsedWidth = 0
              columnPixelTotalUsedWidth = columnNonPercentTotalUsedWidth

ELSE // no specified pixel width column
       columnPixelTotalUsedWidth= 0

       IF there is auto column

             columnAutoTotalUsedWidth = columnNonPercentTotalUsedWidth
             columnAutoTotalUsedWidth = 0

Step 5.5 Decide distribution method for specified pixel column and auto column
IF columnAutoTotalUsedWidth > columnAutoTotalMaxWidth
       enumAutoDistribution = DISTRIBUTION_MAX_ADDITION
ELSE IF columnAutoTotalUsedWidth == columnAutoTotalMaxWidth
       enumAutoDistribution = DISTRIBUTION_MAX
ELSE IF columnAutoTotalUsedWidth == columnAutoTotalMinWidth
       enumAutoDistribution = DISTRIBUTION_MIN
ELSE // columnAutoTotalMinWidth < columnAutoTotalUsedWidth < columnAutoTotalMaxWidth
       enumAutoDistribution = DISTRIBUTION_MIN_ADDITION

IF columnPixelTotalUsedWidth > columnPixelTotalMaxWidth
       enumSpecifiedPixelDistribution = DISTRIBUTION_MAX_ADDITION
ELSE IF columnPixelTotalUsedWidth == columnPixelTotalMaxWidth
       enumSpecifiedPixelDistribution = DISTRIBUTION_MAX
ELSE IF columnPixelTotalUsedWidth == columnPixelTotalMinWidth
       enumSpecifiedPixelDistribution = DISTRIBUTION_MIN
ELSE // columnPixelTotalMinWidth < columnPixelTotalUsedWidth < columnPixelTotalMaxWidth
       enumSpecifiedPixelDistribution = DISTRIBUTION_MIN_ADDITION

Step 5.6 Calculate auto column and specified pixel column’ columnUsedWidth
FOR EACH column in the table
      IF it is auto column
                SWITCH enumAutoDistribution
                       CASE DISTRIBUTION_MIN
                             columnUsedWidth = columnMinWidth
                       CASE DISTRIBUTION_MAX
                             columnUsedWidth = columnMaxWidth
                             columnUsedWidth = columnMaxWidth + (columnAutoTotalUsedWidth -
                             columnAutoTotalMaxWidth) x columnMaxWidth/columnAutoTotalMaxWidth
                             columnUsedWidth = columnMinWidth + (columnAutoTotalMaxWidth –
                             columnAutoTotalUsedWidth) x (columnMaxWidth – columnMinWidth) /
                             (columnAutoTotalMaxWidth – columnAutoTotalMinWidth)
      ELSE IF specified in pixel
                SWITCH enumSpecifiedPixelDistribution
                       CASE DISTRIBUTION_MIN
                             columnUsedWidth = columnMinWidth
                       CASE DISTRIBUTION_MAX
                             columnUsedWidth = columnMaxWidth
                             columnUsedWidth = columnMaxWidth + (columnPixelTotalUsedWidth –
                             columnPixelTotalMaxWidth) x columnMaxWidth /columnPixelTotalMaxWidth
                             columnUsedWidth = columnMaxWidth + (columnPixelTotalMaxWidth –
                             columnPixelTotalUsedWidth) x (columnMaxWidth - columnMinWidth) /
                             (columnPixelTotalMaxWidth – columnPixelTotalMinWidth)


To top