css3 can customize the width of the blocks. For example, we have a container inside which there are 3 blocks. The width of the first block is 100 pixels, and the widths of the 2nd and 3rd should stretch along the remaining width, and the width of the 3rd block should be 2 times larger than the 2nd. This task is easily solved with display: flex
.
<div style="display: flex; flex-direction: row; width: 100%;"> <div style="width: 100px; border: 1px solid black;">data 1</div> <div style="flex: 1; border: 1px solid black;">data 2</div> <div style="flex: 2; border: 1px solid black;">data 3</div> </div>
But I have problems when I want to do something similar with the table. The col
tag does not understand flex
, it needs to specify a specific number of pixels .. correct if I am wrong ..
<table border="1" style="width: 100%;"> <colgroup> <col width="100"> <col flex="1"> <!-- не понимает flex!!!! --> <col flex="2"> <!-- не понимает flex!!!! --> </colgroup> <tbody> <tr> <td>data 1</td> <td>data 2</td> <td>data 3</td> </tr> <!-- other data... --> </tbody> </table>
Therefore, I calculate the width of each column manually. Here it is important to understand that the width of the table is 100%
relative to the outer container. Those. if the div
is 250
pixels, then the sum of all columns should also be 250
pixels.
<!-- если этот контейнер равен 250 пикселей, то и таблица должна быть тоже равна 250px, (100 + 50 + 100) --> <div style="width: 250px;"> <table border="1"> <colgroup> <col width="100"> <col flex="1"> <!-- 50px --> <col flex="2"> <!-- 100px --> </colgroup> <tbody> <!-- data... --> </tbody> </table> </div>
Those. the width of the first column is static 100
pixels, while the width of the remaining 2 columns depends on the width of the outer container. The calculation algorithm in this function
function updateWidthColumns (table) { var parent = table.parentNode; var cols = table.querySelectorAll('col'); var width = 0, flex = 0; Array.prototype.forEach.call(cols, function (col) { var w = col.getAttribute('data-width'); if (w === null) {//flex flex += parseInt(col.getAttribute('data-flex')); } else { width += parseInt(w); } }); var segment = (parent.offsetWidth - width) / flex; Array.prototype.forEach.call(cols, function (col) { var w = col.getAttribute('data-width'); if (w === null) {//flex var flex = parseInt(col.getAttribute('data-flex')); col.style.width = (segment * flex) + 'px'; } else { col.style.width = w + 'px'; } }); }
Everything would be fine, but at some point in time the size of the external container may change. And the sizes of the columns need to be recounted. Therefore, you need to keep track of the size of the outer container. The first option is to bind the onresize
event to the window
Window.onresize = function () { updateWidthColumns(table); }
But the size of the external container can change without changing the browser window, so I decided to use an iframe
to track the width of the container.
Here is an example https://jsfiddle.net/wj3uxq0d/1/ It works, but is this the right solution?