Make Arbitrary Table Column Width Equal to Space Available - html

The scenario is I want a table column to consume all of the available with -- nothing more and nothing less. This is similar to using table td:last-child{width:100%} except the column many not be the last.
My sample code below demonstrates what I have so far.
The first table shows the result when the data fits comfortably.
The second table shows what happens when the column whose width I want to vary has too much data. What it does is it pushes the last column over. What I want it to do is to have a width still equal to the available space after accounting for the other columns and for the excess text to be treated as overflow, which means it should be hidden.
Please note that in the real-life scenario the table can be resized, so any solution that relies on setting the columns width to a value or percentage will probably not suffice.
Thanks in advance for any assistance.
<style>
.container {
position: relative;
width: 500px;
height: 200px;
display: inline-block;
font: 16px arial;
border: 1px solid steelblue;
background-color: lightgoldenrodyellow;
}
.variCell {
text-align: left;
width: 100%;
overflow: hidden;
white-space: nowrap;
}
.orderCell {
display: inline-block;
width: 65px;
text-align: right;
}
table {
position: absolute;
display: block;
margin-right: 10px;
border: none;
overflow: hidden;
width: 100%;
height: 100%;
cursor: pointer;
}
thead {
position: relative;
display: table-header-group;
height: 25px;
max-height: 25px;
background-color: #93aed2;
text-align: center;
font-size: 14px;
line-height: 25px;
white-space: nowrap;
}
tbody {
position: relative;
border: none;
overflow: hidden;
max-width: 100%;
max-height: 100%;
cursor: pointer;
}
</style>
<div class="container">
<table>
<thead>
<tr>
<td class="orderCell">
Col 1
</td>
<td class="variCell">
Col 2
</td>
<td class="orderCell">
Col 3
</td>
</tr>
</thead>
<tbody>
<tr>
<td class="orderCell">
1
</td>
<td class="variCell">
Please use available space only.
</td>
<td class="orderCell">
100
</td>
</tr>
</tbody>
</table>
</div>
<div class="container">
<table>
<thead>
<tr>
<td class="orderCell">
Col 1
</td>
<td class="variCell">
Col 2
</td>
<td class="orderCell">
Col 3
</td>
</tr>
</thead>
<tbody>
<tr>
<td class="orderCell">
1
</td>
<td class="variCell">
Please use available space only. Do not push the next column out of the table.
</td>
<td class="orderCell">
100
</td>
</tr>
</tbody>
</table>
</div>

I would suggest using table-layout:fixed for the table and white-space: break-word; for fixed columns and stop table from expanding.
.container {
position: relative;
width: 500px;
height: 200px;
font: 16px arial;
border: 1px solid steelblue;
background-color: lightgoldenrodyellow;
}
.variCell {
position: relative;
text-align: left;
width: 100%;
overflow: hidden;
white-space: nowrap;
}
.variCell span {
position: absolute;
top: 0;
left: 0;
right: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.orderCell {
display: inline-block;
width: 65px;
text-align: right;
}
table {
position: absolute;
display: block;
margin-right: 10px;
border: none;
overflow: hidden;
width: 100%;
height: 100%;
cursor: pointer;
}
thead {
position: relative;
display: table-header-group;
height: 25px;
max-height: 25px;
background-color: #93aed2;
text-align: center;
font-size: 14px;
line-height: 25px;
white-space: nowrap;
}
tbody {
position: relative;
border: none;
overflow: hidden;
max-width: 100%;
max-height: 100%;
cursor: pointer;
}
<div class="container">
<table>
<thead>
<tr>
<td class="orderCell">
Col 1
</td>
<td class="variCell">
Col 2
</td>
<td class="orderCell">
Col 3
</td>
</tr>
</thead>
<tbody>
<tr>
<td class="orderCell">
1
</td>
<td class="variCell">
<span>Please use available space only. Do not push the next column out of the table.</span>
</td>
<td class="orderCell">
100
</td>
</tr>
</tbody>
</table>
</div>

Related

How to restrict the height of an image in a table cell to the same as the adjacent cell, without JavaScript?

How can I make the image in the red box be no taller than the table to its right?
It is a high-resolution image that is downscaled using max-width: 100% on the image.
I've tried display: flex on #featured and display: block on #featured img but I must be missing something.
The desired behaviour is to set the image's height the same as #condition and center the image horizontally if it doesn't fill the width.
I want the image to print out on to physical paper by default (without the user changing printer settings), so using a background-image is out of the question.
The platform I am targeting has no support for JavaScript - I can only use HTML & CSS. I know it is sacrilege, but this particular platform has good support for table layouts and poor support for typical modern <div> layouts - so I'd prefer to keep it as a nested table layout.
table {
border-collapse: collapse;
border-spacing: 0;
border-style: none;
width: 100%;
}
#featured {
padding: 2% 1% 2% 2%;
text-align: center;
width: 47%;
}
#featured img {
border: 0.5em solid red;
max-width: 100%;
}
#condition {
padding: 2% 2% 2% 1%;
vertical-align: top;
width: 47%;
}
#condition table {
border: 1px solid #000;
}
#condition td {
border: 1px solid #000;
padding: 0.5em;
}
#product {
text-align: center;
}
<table>
<tr>
<td id="featured">
<a target="_blank" href="https://i.imgur.com/sNc50nG_d.webp?maxwidth=1520&fidelity=grand">
<img src="https://i.imgur.com/sNc50nG_d.webp?maxwidth=1520&fidelity=grand" alt="">
</a>
</td>
<td id="condition">
<table>
<tr>
<th>Category</th>
<th>Condition</th>
</tr>
<tr>
<td>Overall</td>
<td>Excellent</td>
</tr>
<tr>
<td>Box</td>
<td>Excellent</td>
</tr>
<tr>
<td>Game</td>
<td>Excellent</td>
</tr>
</table>
</td>
</tr>
<tr>
<td id="product" colspan="2">{Product ID}</td>
</tr>
</table>
JSFiddle
Put the image in an absolutely-positioned div and set its height to 100%.
Note that I'm using classes instead of IDs. CSS should be reusable when possible, and IDs must be unique in a document.
table {
border-collapse: collapse;
border-spacing: 0;
border-style: none;
width: 100%;
}
.featured {
width: 47%;
position: relative;
}
.featured-img {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
text-align: center;
}
.featured-img img {
height: calc(100% - 1em);
border: 0.5em solid red;
}
#condition {
vertical-align: top;
width: 47%;
}
#condition table {
border: 1px solid #000;
}
#condition td {
border: 1px solid #000;
padding: 0.5em;
}
#product {
text-align: center;
}
<table>
<tr>
<td class="featured">
<div class="featured-img">
<a target="_blank" href="https://i.imgur.com/sNc50nG_d.webp?maxwidth=1520&fidelity=grand">
<img src="https://i.imgur.com/sNc50nG_d.webp?maxwidth=1520&fidelity=grand">
</a>
</div>
</td>
<td id="condition">
<table>
<tr>
<th>Category</th>
<th>Condition</th>
</tr>
<tr>
<td>Overall</td>
<td>Excellent</td>
</tr>
<tr>
<td>Box</td>
<td>Excellent</td>
</tr>
<tr>
<td>Game</td>
<td>Excellent</td>
</tr>
</table>
</td>
</tr>
<tr>
<td id="product" colspan="2">{Product ID}</td>
</tr>
</table>
Seeming as you won't dispense with the outer <table>, I thusly present the nuclear option...
table#outer,
table#outer>tbody {
display: contents;
}
table#outer>tbody>tr:first-child {
display: flex;
align-items: stretch;
}
table#outer>tbody>tr>td#featured {
display: contents;
}
table#outer>tbody>tr>td#featured>a {
display: block;
flex-basis: 50%;
flex-grow: 0;
flex-shrink: 5;
position: relative;
}
table#outer>tbody>tr>td#featured>a>img {
/*
border: 0.5em solid red;
display: inline-block;
flex-basis: 50%;
flex-grow: 0;
flex-shrink: 5;
*/
position: absolute;
top: 0;
left: 0;
/* right: 0;
bottom: 0;*/
object-fit: contain;
width: 100%;
height: 100%;
object-fit: contain;
}
table#outer>tbody>tr>td#condition {
display: block;
flex-basis: 50%;
flex-grow: 1;
flex-shrink: 1;
}
td#condition>table {
border: 1px solid #000;
border-collapse: collapse;
border-spacing: 0;
border-style: none;
width: 100%;
}
#condition>table td {
border: 1px solid #000;
padding: 0.5em;
}
table#outer>tbody>tr:nth-child(2) {
display: flex;
justify-content: center;
}
table#outer>tbody>tr:nth-child(2)>td#product {
text-align: center;
}
<table id="outer">
<tr>
<td id="featured">
<a target="_blank" href="https://i.imgur.com/sNc50nG_d.webp?maxwidth=1520&fidelity=grand">
<img src="https://i.imgur.com/sNc50nG_d.webp?maxwidth=1520&fidelity=grand" alt="">
</a>
</td>
<td id="condition">
<table>
<tr>
<th>Category</th>
<th>Condition</th>
</tr>
<tr>
<td>Overall</td>
<td>Excellent</td>
</tr>
<tr>
<td>Box</td>
<td>Excellent</td>
</tr>
<tr>
<td>Game</td>
<td>Excellent</td>
</tr>
</table>
</td>
</tr>
<tr>
<td id="product" colspan="2">{Product ID}</td>
</tr>
</table>

How to text ellipsis with width auto / dynamically?

I have a table where I group all the orders of a user. The product name row is often very large, so the text comes out of the table and breaks the layout of the entire page.
To solve this I am using text ellipsis with a max-width: 200px;. This is fine on desktop, but when I switch to tablet or mobile the 200px width is no longer fine.
So I would have to change max-width every time according to the browser display width (mobile, tablet, portrait etc ..), this is insane.
So is there any way to make the width of text ellipsis work automatically? Or determine the width of the text ellipsis based on the row width percentage ?
To better explain the problem
I used a wide range of media queries for the convenience of the question. .product_name is 100% wide and that's what I want.
.product_name> a on the other hand has a fixed width of 200px, so even if the screen gets bigger or smaller, the product name is always displayed with the same width.
To solve this problem I would have to use different media queries and change the max-width of .product_name> a every time, which I want to avoid.
Is there a way to tell the max-width to automatically fit the width of td.product name ?
/*Global Container For Table*/
.global_container.order {
gap: 12px;
}
/* Table Width */
.product_number { width: 10%; }
.product_name { width: 35%; }
.product_data { width: 15%; }
.product_price { width: 10%; }
.product_status { width: 15%; }
.product_action { width: 15%; }
/* Table Heading */
.table_orders.heading > tbody > tr > td {
color: #4B525F;
font-weight: 600;
}
.table_orders.heading {
border: solid #e0e0e0;
border-width: 0px 0px 1px 0px;
padding: 0px 0px 12px 0px;
width: 100%;
}
/* Table Orders */
.table_orders {
text-align: left;
border: 0;
font-weight: 400;
color: #737477;
padding-top: 12px;
width: 100%;
}
td {
border: 0;
font-size: 13px;
}
/* Text Ellipsis */
.product_name {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 200px;
}
/*** Mobile Device Range ***/
#media only screen and (min-width: 280px) and (max-width: 1024px){
.table_orders.heading { display: none; }
/* Name Before Value */
.product_number::before { content: 'Ordine'; }
.product_name::before { content: 'Prodotto'; }
.product_data::before { content: 'Data'; }
.product_price::before{ content: 'Prezzo'; }
.product_status::before { content: 'Stato'; }
.product_action::before { content: 'File'; }
/* Items */
.product_name {
white-space: unset;
overflow: unset;
text-overflow: unset;
max-width: unset;
}
.product_name > a {
text-align: right;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
max-width: 200px;
}
td {
display: flex;
width: 100%!important;
flex-direction: row;
justify-content: space-between;
}
}
<table class="table_orders heading">
<tr class="table_row">
<td class="product_number">Order ID</td>
<td class="product_name">Product Name</td>
<td class="product_data">Date</td>
<td class="product_price">Total</td>
<td class="product_status">Status</td>
<td class="product_action">File</td>
</tr>
</table>
<table class="table_orders">
<tr class="table_row_items">
<td class="product_number">
<span>#12345</span>
</td>
<td class="product_name">
Product Name is very long long long long long long long long long long long
</td>
<td class="product_data">
<span>02/08/2022</span>
</td>
<td class="product_price">
<span>Order Total</span>
</td>
<td class="product_status">
<span>Purchuased</span>
</td>
<td class="product_action">
Show
</td>
</tr>
</table>
Use #media to change css based on screen size.
Example:
#media only screen and (max-width: 600px) {
.product_name {
max-width: 100px;
}
}
Code:
/*Global Container For Table*/
.global_container.order {
gap: 12px;
}
/* Table Width */
.product_number { width: 10%; }
.product_name { width: 35%; }
.product_data { width: 15%; }
.product_price { width: 10%; }
.product_status { width: 15%; }
.product_action { width: 15%; }
/* Table Heading */
.table_orders.heading > tbody > tr > td {
color: #4B525F;
font-weight: 600;
}
.table_orders.heading {
border: solid #e0e0e0;
border-width: 0px 0px 1px 0px;
padding: 0px 0px 12px 0px;
width: 100%;
}
/* Table Orders */
.table_orders {
text-align: left;
border: 0;
font-weight: 400;
color: #737477;
padding-top: 12px;
width: 100%;
}
td {
border: 0;
font-size: 13px;
}
/* Text Ellipsis */
.product_name {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 200px;
}
#media only screen and (max-width: 600px) {
.product_name {
max-width: 100px
}
}
<table class="table_orders heading">
<tr class="table_row">
<td class="product_number">Order ID</td>
<td class="product_name">Product Name</td>
<td class="product_data">Date</td>
<td class="product_price">Total</td>
<td class="product_status">Status</td>
<td class="product_action">File</td>
</tr>
</table>
<table class="table_orders">
<tr class="table_row_items">
<td class="product_number">
<span>#12345</span>
</td>
<td class="product_name">
Product Name is very long long long long long long long long long long long
</td>
<td class="product_data">
<span>02/08/2022</span>
</td>
<td class="product_price">
<span>Order Total</span>
</td>
<td class="product_status">
<span>Purchuased</span>
</td>
<td class="product_action">
Show
</td>
</tr>
</table>

Table will not fill 100% of the Div. Thead, Tbody, Table all fill 100%. td and th won't

I've tried everything from other similar questions and nothing is working but I can't get my th's and td's to fill the table width.
The table takes up 100% width of containing div.
Thead takes up 100%.
Tbody takes up 100%.
Tr's take up 100%.
But the 4 th and td columns will only take up about 50% width.
I've set them to 25% as I always thought 4 x 25% would add up to 100% but apparently not in CSS.
I've tried adding display block in different places and tried loads of other things but nothing works.
This is what i did:
.booktable {
width: 100%;
overflow-y: scroll;
height: 55vh;
display: inline-block;
}
.booktable thead {
width: 100%;
display: inline-block;
}
.booktable tbody {
width: 100%;
display: block;
}
.booktable tr{
width: 100%;
display: block;
}
.booktable th{
width: 25%;
color: grey;
padding: 1vh;
font-size: 2vh;
border-bottom: 1px solid grey;
font-weight: bold;
position: sticky;
top: 0;
background-color: white;
}
.booktable td{
width: 25%;
font-size: 2.5vh;
text-align: center;
padding: 2vh;
color: grey;
}
<table class="booktable">
<thead>
<tr>
<th>Name</th>
<th>Category</th>
<th>Group</th>
<th>Balance</th>
</tr>
</thead>
<tbody>
<tr>
<td>Name</td>
<td>Cat</td>
<td>Group</td>
<td>Balance</td>
</tr>
</tbody>
</table>
Been trying display inline-blocks, blocks and position absolutes, relatives, table layouts, removing padding... nothing works.
Even doubling widths to 200% or 50% for td.
Didn't want to ask what must be a really simple answer and I have tried as much as I can but had to ask as I've been trying for hours!
Any help much appreciated.
You are overwriting all table specific display modes, so that's what's getting you in trouble try this:
.booktable {
width:100%;
overflow-y: scroll;
height: 55vh;
display: table;
}
.booktable thead {
width: 100%;
}
.booktable tbody {
width: 100%;
}
.booktable tr{
width: 100%;
}
.booktable th{
width: 25%;
color: grey;
padding: 1vh;
font-size: 2vh;
border-bottom: 1px solid grey;
font-weight: bold;
position: sticky;
top: 0;
background-color: white;
}
.booktable td{
width: 25%;
font-size: 2.5vh;
text-align: center;
padding: 2vh;
color: grey;
}
<table class="booktable">
<thead>
<tr>
<th>Name</th>
<th>Category</th>
<th>Group</th>
<th>Balance</th>
</tr>
</thead>
<tbody>
<tr>
<td>Name</td>
<td>Cat</td>
<td>Group</td>
<td>Balance</td>
</tr>
</tbody>
</table>
You need to set table width to 100% then all th,td will adapt 25% of the total width.
Here is the working example:
.booktable {
width: 100%
}
.booktable th, .booktable td{
width: 25%;
color: grey;
padding: 1vh;
font-size: 2vh;
border-bottom: 1px solid grey;
font-weight: bold;
position: sticky;
top: 0;
background-color: white;
}
.booktable td{
width: 25%;
font-size: 2.5vh;
text-align: center;
padding: 2vh;
color: grey;
}
<table class="booktable">
<thead>
<tr>
<th>Name</th>
<th>Category</th>
<th>Group</th>
<th>Balance</th>
</tr>
</thead>
<tbody>
<tr>
<td>Name</td>
<td>Cat</td>
<td>Group</td>
<td>Balance</td>
</tr>
</tbody>
</table>

Table: Minimize column width (multiple colspans)

I have this:
and want this (second column using less space):
Is there a way without introducing absolute values or fixed columns? I don't mind any other hacks like wrappers or invisible columns as long as the content sizes dynamically.
HTML
table {
border-collapse: collapse;
height: 100%;
background-color: blue;
white-space: nowrap;
}
.wrapper {
width: 40%;
font-family: avenir;
height: 100vh;
}
td > div {
color: white;
background-color: darkblue;
padding: 5px;
display: inline-block;
}
td {
padding: 0px;
border: 1px dotted white;
}
.w1px {
width: 1px;
}
.h-100 {
height: 100%;
}
<div class="wrapper">
<table>
<tr>
<td class="w1px"><div>Item1</div></td>
<td><div>Item2</div></td>
<td><div>Item3</div></td>
</tr>
<tr>
<td colspan="3"><div>Item Spanning All Three Above</div></td>
</tr>
<tr>
<td colspan="2"><div>Item Spanning Two</div></td>
</tr>
<tr class="h-100">
</tr>
</table>
</div>

multiple tables with the same TD width

To format these 2 tables I have a css sheet. The top table is a filter/sort selection. The second is a scrollable data table.
div#scrollTableContainer {
width: auto;
margin: 20px; /* just for presentation purposes */
border: 1px solid black;
}
#tHeadContainer {
background: #CC3600;
color: black;
font-weight: bold;
}
#tBodyContainer {
height: 750px;
overflow-y: scroll;
}
td:first-child {
min-width: 5%; /* EDIT */
max-width: 5%;
border-left:0;
}
td:first-child + td {
min-width: 4%;
max-width: 4%;
}
td:first-child + td + td {
min-width: 4%;
max-width: 4%;
}
<div id="scrollTableContainer">
<div id="tHeadContainer">
<table border="1" align="center" width="100%" cellpadding="0" cellspacing="0">
<tr>
<th bgcolor="<%=bgc0%>">USED</th>
<th bgcolor="<%=bgc0%>">STATUS</th>
</tr>
</table>
</div>
<div id="tBodyContainer">
<table border="1" align="center" id="tBody" class="TableData">
<td> stuff </td>
<td> More stuff </td>
</table>
</div>
</div>
Neither of the 2 tables are aligning column wise so that the Title/Header columns do not match the tables columns below. It also shows almost the same in chrome/IE, but firefox is a complete shamble.
Im at a loss to get this right guys, any help will be appreciated.
div#scrollTableContainer {
width: auto;
margin: 20px;
/* just for presentation purposes */
}
#tHeadContainer {
background: #CC3600;
color: black;
font-weight: bold;
}
#tBodyContainer {
height: 750px;
}
th:first-child, td:first-child {
min-width: 15%;
max-width: 15%;
width: 15%;
}
td:first-child+td {
min-width: 4%;
max-width: 4%;
}
td:first-child+td+td {
min-width: 4%;
max-width: 4%;
}
<div id="scrollTableContainer">
<div id="tHeadContainer">
<table border="1" align="center" width="100%" cellpadding="0" cellspacing="0">
<tr>
<th bgcolor="<%=bgc0%>">USED</th>
<th bgcolor="<%=bgc0%>">STATUS</th>
</tr>
</table>
</div>
<div id="tBodyContainer">
<table border="1" align="center" width="100%" cellpadding="0" cellspacing="0">
<td> stuff </td>
<td> More stuff </td>
</table>
</div>
</div>
You want to align the columns of both table vertically right?
If that is so, I have a solution for you
I have changed your css and u missed tr in second table.
https://jsfiddle.net/9ccwkoav/
div#scrollTableContainer {
width: auto;
margin: 20px; /* just for presentation purposes */
border: 1px solid black;
}
#tHeadContainer {
background: #CC3600;
color: black;
font-weight: bold;
}
#tHeadContainer th{
width:50%;
}
#tBodyContainer {
height: 750px;
overflow-y: auto;
}
.TableData{
width:100%;
}
.TableData td{
width:50%;
}
This should do the trick. Notice that there will be a little margin because of the scroll bar of the second table, but you can easily change it by adding a tab in the first array with the width of the scrollbar. Hope it will help
#scrollTableContainer {
width : 96%;
margin : auto;
border : 1px solid #ccc;
}
#tHeadContainer {
background-color : green;
width : 100%;
}
#tBodyContainer {
width : 100%;
height : 750px;
overflow-y : scroll;
}
#tHeadContainer table, #tBodyContainer table {
border-collapse : collapse;
width : 100%;
}
td, th {
border : 1px solid black;
}
tr {
width : 100%;
}
th:first-child, td:first-child {
min-width : 15%;
max-width : 15%;
width : 15%; /* Tweak this value to change the first column width */
}
<div id="scrollTableContainer">
<div id="tHeadContainer">
<table>
<tr>
<th>USED</th>
<th>STATUS</th>
</tr>
</table>
</div>
<div id="tBodyContainer">
<table>
<tr>
<td>Stuff</td>
<td>Some other stuff</td>
</tr>
</table>
</div>
</div>