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?

  • width can be set as a percentage - Grundy

1 answer 1

You can use the following approach: for a fixed column, insert a div with a width, and for relative columns, specify a width in percent

 function imitationChangePanelWidth() { var right = document.querySelector('.right'); var width = parseInt(right.style.width); if (width >= 300) width = 0; right.style.width = (width + 50) + 'px'; } setInterval(imitationChangePanelWidth, 2000); 
 body { margin: 0; padding: 0; } .flex-layout { display: flex; flex-direction: row; width: 100%; height: 100%; position: absolute; } .content { flex: 1; } table { border-collapse: collapse; } td { padding: 0; } 
 <div class="flex-layout"> <div class="content"> <div style="display: flex; flex-direction: row; width: 100%; height: 20px;"> <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> <div class="wrap" style="margin-top: 20px;"> <table border="1" style="width: 100%;"> <tbody> <tr> <td> <div style="width:100px;">data 1</div> </td> <td style="width:33%;">data 2</td> <td style="width:66%;">data 3</td> </tr> <!-- other data... --> </tbody> </table> </div> </div> <div class="right" style="width: 100px;"></div> </div> 

  • is it better, but can you make these rules in colgroup? type of such <colgroup> <col> <div style = "width: 100px;"> data 1 </ div> </ col> <col style = "width: 33%;"> <col style = "width: 66% ; "> </ colgroup> (but it certainly does not work) because in tbody I want to use only for data. I use reactjs - user2815962
  • @ user2815962, with the current approach, so that the width of a fixed column does not break, it must have a div with a fixed width. I do not see any connection between the styles and the fact that you use the handle - Grundy
  • I did what I need on the basis of your answer, I made the rules defining the width in thead, and the data is in tbody jsfiddle.net/wj3uxq0d/3 - this is exactly what I need :) - user2815962