简体   繁体   中英

Max width for table with auto layout

I have a table with multiple columns and this table should not exceed a certain width y .

The columns of this table are automatically sized by the table-layout: auto.

But sometimes the columns get too big (the text should not be wrapped, it should be clipped) and sum up to a width bigger than y .

In this case i want the 'biggest' columns to become smaller until the widths of the columns don't exceed y anymore.

This means that i do not want to shrink alls columns by some factor but rather make the bigger columns "as small as neccessary".

Is this possible through some simple JS or even CSS?

Here an example:

I have 3 columns and a max total width y of 1000px.
Here the sizes of the content of the columns:

1: 100px 2: 1100px 3: 1300px

This should result in a table with those widths:

1: 100px 2: 450px 3: 450px;

Here some code:

HTML:

<div>
    <table>
        <tr>
            <td>SomeText</td>
            <td>SomeOtherTextSomeOtherTextSomeOtherText</td>
            <td>SomeLongerTextSomeLongerTextSomeLongerTextSomeLongerTextSomeLongerText</td>
        </tr>
    </table>
</div>

CSS:

div {
    border: 1px solid red; 
    width: 500px;
}

table {
    table-layout: auto;
    border: 1px solid grey;
}

td {
    border: 1px solid black;
}

fiddle: http://jsfiddle.net/6zJR4/2/

In this example the table is bigger than the containing div. What i would want is that the table respects the width of the containing div and the columns shrink. But not all columns should shrink with the same factor eg 30% smaller. But the bigger columns (maybe all columns would need to shrink in the end) shrink.

My approach: I want to let the browser calculate the 'ideal' sizes of the columns and then adjust the sizes by hand (=JS) to match the maximum width of the containing div.

How i am going to calculate the width of the different columns is not yet clear to me, i opened a mathoverflow question for that: https://math.stackexchange.com/questions/702067/how-to-find-a-set-of-ascending-natural-numbers-which-when-added-to-another-set-o

i hope there is a simpler solution.

Just use CSS to set TD (table data)

td {
    max-width: 800px;
}

Setting a max on table data will guarantee that no column exceeds that width (but may grow in height if overlap isnt specified)

If you want to have different max widths for differnt columns, make multiple classes:

 .col1 {
     max-width: 500px;
 }

 .col2 {
      max-width: 600px;
 }

etc. then just add a class to TD tag. If the table is dynamically created use JQuery to add the class:

 $( "td" ).addClass( "myClass yourClass" );

When the text is too long we can break them by this CSS property.

-ms-word-break: break-all;
word-break: break-all;

// Non standard for webkit
word-break: break-word;

in table cell td you can add this CSS.

td {
    border: 1px solid black;
    -ms-word-break: break-all;
     word-break: break-all;

     // Non standard for webkit
     word-break: break-word;
}

Here is the Demo http://jsfiddle.net/kheema/6zJR4/1/

After understanding the actual requirement it would be good to use a very tiny jquery plugin called Succinct can help you. here is the link. http://micjamking.github.io/succinct/

add width to your table and it would wrap contents inside table equal to div width, but it wont show excess text

Demo of what u need exactly

table.tbl{
    width:100%; /* this will make table equal to div width and clip excess contents*/
    table-layout: fixed;
}

and, to show excess text, word-break them

table.tbl{
    width:100%;
    table-layout: fixed;
    word-break:break-all;
}

demo here

I implemented my own solution:

Here is the code showed in an example:

JS:

function findOptimalDistribution(Z, z) {
    // Make a working copy
    var Y = Z.slice(0);

    // Add dummy element so the 'lowest' value is 1, increment z accordingly
    Y.unshift(1);
    z++;

    // calculate sum of Y
    var R = 0;
    for(var i = 0; i < Y.length; i++) {
        R += Y[i];
    }

    // R contains the remaining 'overlap' over z
    R -= z;

    // R <= 0 means the condition is already fullfiled
    if (R <= 0) {
        return Y.slice(1);
    }

    for(var i = Y.length - 1, u = 1; i > 0; i--, u++) {
        var c = (Y[i] - Y[i - 1]);

        var b = (R <= c*u);
        if (b) {
            c = Math.floor(R / u);
        }

        for(var j = Y.length - 1; j >= i; j--) {
            Y[j] -= c;
        }
        R -= c * u;

        // Subtract the remainder of R, that got 'lost' due to rounding (Math.floor)
        if (b) {
            for (var j = i; j < i + R; j++) {
                Y[j]--;
            }

            R = 0;
        }

        if (R == 0) {
            break;
        }
    }

    return Y.slice(1);
}

function findOptimalWidths(columns, max_width) {    
    columns.sort(function (a, b) {
        return a.width - b.width;
    });

    var X = columns.map(function(e) {           
        return e.width;
    });

    var optimal = findOptimalDistribution(X, max_width);

    for(var i = 0; i < columns.length; i++) {
        columns[i].width = optimal[i];
    }

    return columns; 
}

function resizeColumns(){
    var columns = [];
    $('table tr:first-child td').each(function(i, e) {
        var $e = $(e);

        $e.css('max-width', 'auto');
        columns.push({elem: $e, width: $e.outerWidth()});
    });



    columns = findOptimalWidths(columns, $('div').innerWidth());

    for(var i = 0; i < columns.length; i++) {
        columns[i].elem.css('max-width', columns[i].width);
    }
}

$(window).resize(function() {
    resizeColumns();
});

resizeColumns();

HTML:

<div>
    <table>
        <tr>
            <td style="background-color: violet;">
                Line
            </td>
            <td style="background-color: green;">
                LongerLineLongerLineLongerLine
            </td>
            <td style="background-color: yellow;">
               VeryLongLineVeryLongLineVeryLongLineVeryLongLineVeryLongLineVeryLongLineVeryLongLineVeryLongLine
            </td>
        </tr>
    </table>
</div>

CSS:

table {
    table-layout:fixed;
    border-collapse: collapse;
}

table td {
    overflow: hidden;
    box-sizing: border-box;
    text-overflow: ellipsis;
}

div {
    width: 100%;
    border: 1px solid red;
}

Link to the fiddle: http://jsfiddle.net/ujQh7/2/

I believe this is a good and intuitiv behaviour of a table with columns that get truncated.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM