I am rewriting a web application that visually represents data and would like to make the result fill the available width automatically (the previous version had a few user selectable scaling factors). I have simplified the layout to this:
.bar {
height: 25px;
background: green;
color: white;
}
<table>
<thead>
<tr>
<th></th>
<th>column #1</th>
<th>column #2</th>
</tr>
</thead>
<tbody>
<tr>
<td>row #1</td>
<td>
<div class="bar" style="width:50px">
cell #1
</div>
</td>
<td>
<div class="bar" style="width:150px">
cell #2
</div>
</td>
</tr>
<tr>
<td>row #2</td>
<td>
<div class="bar" style="width:100px">
cell #3
</div>
</td>
<td>
<div class="bar" style="width:75px">
cell #4
</div>
</td>
</tr>
</tbody>
</table>
The width of the bars should be adjusted so that the table as a whole fills the horizontally available space (the left column should keep its width and ideally the height of the table should not be altered). The amount of columns as well as the amount of rows will vary.
I have full control over the generated html, so the solution may use a different markup (just note that the calculated bar widths are not limited to a few values).
It is important that the relative lengths of the bars are not changed. In this example, the bar in cell #4 should always be 50% longer than the one in cell #1. It should be possible to have text inside the bars and it should not be stretched (therefore, I could not solve my problem with CSS transformations).
The solution may use JavaScript. I think that I could make it work using only JavaScript by measuring the left over space and then scaling each bar manually, but this seems fragile and difficult to maintain to me (the given example is simplified).
Is there an elegant solution? I found it quite hard to search for this problem, so I might have overlooked something (usually I never need to ask questions as others have had similar problems before).
Edit: It seems that I wrote too much text and the actual question became unclear. I am looking for a solution that scales the bars inside the table from the given code snippet so that the table takes up all the available vertical horizontal (too hasty edit) space. The caveat is, that the contained bars should keep their relative lengths.
You can accomplish what you want with just a little bit of JavaScript and a slightly modified CSS file. This will calculate the number of columns (minus the initial column) and will distribute their width evenly.
<style>
.bar {
height: 25px;
background: green;
color: white;
}
table{
width: 100%;
}
table tbody tr td:first-child{
width: 20%;
}
table tbody tr td{
width: 40%;
}
</style>
Then your HTML
<table>
<thead>
<tr>
<th></th>
<th>column #1</th>
<th>column #2</th>
</tr>
</thead>
<tbody>
<tr>
<td>row #1</td>
<td>
<div class="bar" data-value="50">
cell #1
</div>
</td>
<td>
<div class="bar" data-value="100">
cell #2
</div>
</td>
</tr>
<tr>
<td>row #2</td>
<td>
<div class="bar" data-value="80">
cell #3
</div>
</td>
<td>
<div class="bar" data-value="75">
cell #4
</div>
</td>
</tr>
</tbody>
</table>
Then some simple JavaScript:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
$(document).ready(function(){
var v, b, n, max = 0;
var t = $('table');
var w = t.width();
// Set equal width for all columns
var c = (80/(t.find('thead tr th').length-1));
// Set widths of internal bars relative to the max value
$('.bar')
.parent()
.css({width: c + "%"})
.end()
.each(function(){
// Determines max value
v = parseFloat($(this).attr('data-value'));
if(v>max){
max = v;
}
})
.each(function(){
// Sets each bar to be a percent width based on max value
b = $(this);
n = (((parseFloat(b.attr('data-value')) / max) * 100));
b.css({width: n + "%"})
});
});
</script>