Consider the following code:
HTML:
<table>
<tr>
<td><img src="http://watduck.jpg.to" /></td>
</tr>
</table>
CSS:
table { width: 10% }
img { max-width: 100% }
The image should obviously be a 10th the width of the window, which is exactly what it is in every browser except IE, where it simply falls back to its original size.
However, consider this:
HTML:
<div><img src="http://watduck.jpg.to" /></div>
CSS:
div { width: 10% }
img { max-width: 100% }
which IE does get right, and displays at a 10th of the window width.
So, here's the question: what causes this behavior, and what could possibly be done to force IE to respect the table's width?
Tested in IE8 & IE9 (don't care about IE7 and below).
If you specify table-layout: fixed; in the table css it works.
There seems to be some contradictory terminology in the standard regarding table layouts. In particular, table-layout: auto; says this:
The column width is set by the widest unbreakable content in the cells
Since the images content is unbreakable, it sets the width of the cell to the size of the content. The max-width seems to be overriden by it.
Related
Updated shorter question:
Applying max-width on an image inside a table cell:
max-width:50PX does one thing, works as expected
max-width:100% does another thing, works as expected
max-width:max(50PX,30vw) also works as expected
BUT, max-width:max(50PX,100%) does totally different and unexpected thing
My guess from the helpful response and links from #temani-afif is that the parent cell sees its child has a max-width:max(%,px) and IGNORES the image entirely when figuring out its own width because of the percentage in the max() function. And in doing so, the image and the table cell separately determine their width leading to overflow.
The table cell in this example says, "I am 40px wide."
The image says, "max(100%, 50px) = max(40px, 50px) = 50px" → Overflow
I don't think there is way around this under these constraints.
Original question:
I'm the owner of a browser extension that modifies Gmail. Part of that is to put a max-width on messages and inline images.
.email-body {
width: 800px;
}
.email-body img {
max-width: 100%;
height: auto;
object-fit: scale-down;
}
This works pretty well. It not only prevents massive inline images from being wider than the message, but it also shrinks images in tables so the table does not exceed the max-width on the body of the message.
But this breaks when the table cell is artificially small (HTML emails often have bad HTML). In this case, images are unintentionally shrunk, sometimes made invisible.
Example: 100px IMG in a 40px TD
For instance, the following code will result in the image being shrunk down to 10px wide with the added max-width:100% (which makes sense as 100% = the container's width = 40px):
<table><tr>
<td style="width:40px;">
<img style="width:100px; max-width:100%;" />
</td>
</tr></table>
First attempt: px not % for max-width
Ok, easy to fix. As this is most often a problem for smaller images, if I use a pixel value (50px) for the max-width, it works fine (the image is the full 100px, and the TD grows to match that).
<table><tr>
<td style="width:40px;">
<img style="width:100px; max-width:50px;" />
</td>
</tr></table>
But I don't want to always use a 50px max-width. I want to let a large image span the entire email width while images in tables are still held to the width of their container.
Second attempt: max-width: max(px, %)
I want to use 100% unless it is smaller than some fixed width (say 50px). That should be easy, right? img { max-width: max(50px, 100%); }
<table><tr>
<td style="width:40px;">
<img style="width:100px; max-width: max(50px, 100%);" />
</td>
</tr></table>
Image no longer matches the cell? The 100% inherits from the container (40px). So the max-width is effectively max(50px, 40px) with 50px being the larger number. The image is correctly sized at 50px wide BUT the cell is not expanded beyond 40px this time resulting in overflow and overlap with the content in the next TD.
Any ideas?
You can play with the code here:
https://jsfiddle.net/leggett/rqp5uko1/2/
The explanation about such logic behavior is a bit tricky but to fix it you can consider min-width like below:
tr,td {
border:1px solid red;
}
Not Good
<table><tr>
<td style="width:40px;">
<img src="https://picsum.photos/id/1/200/200" style="width:100px; max-width: max(50px, 100%);" >
</td>
</tr></table>
Good!
<table><tr>
<td style="width:40px;">
<img src="https://picsum.photos/id/1/200/200" style="width:100px; max-width: 100%;min-width: 50px" >
</td>
</tr></table>
This is working on Chrome/Edge:
<style>
.o {
width: 1px;
white-space: nowrap;
}
</style>
<table style="width:100%; position: relative; border-collapse: collapse">
<tr>
<td class="o">text no wrap</td>
<th>Head</th>
<td class="o">text no wrap</td>
</tr>
</table>
white-space: nowrap; ... stops wraping
width: 1px; ... auto expend content to minimum needed width
This are the problems:
internet explorer: auto-expand width not working. (customers still use them, although i don't like ie)
So there is a wrap if width is set. Without width tds are to big (empty space) because of the missing minimize to content.
cross-browser: if content is too big, without wrapping, it expands table-witdh over 100%. Better would be a "only wrap if really needed".
side information: i cannot use a fixed layout, because content is filled from a database
You need to respect HTML structure in IE. And not just set randomly your style and table.
And it seems to work fine the same way in all browser for me. ie is indicating : width: 79.98px when you inspect and check the calculated value. So auto expand works on ie 11
You might have more css or html but just as you gave. IE11 is making the job as per capture:
Please see this JSFIDDLE
td.rhead { width: 300px; }
Why doesn't the CSS width work?
<table>
<thead>
<tr>
<td class="rhead">need 300px</td>
<td colspan="7">Week #0</td>
<td colspan="7">Week #1</td>
<!-- etc..-->
</tr>
<tr>
<td class="rhead"></td>
<td>S</td><td>M</td><td>T</td><td>W</td><td>T</td><td>F</td><td>S</td>
<td>S</td><td>M</td><td>T</td><td>W</td><td>T</td><td>F</td><td>S</td>
<!-- etc... -->
</tr>
<thead>
</table>
Also, what are the effects of position:fixed, absolute etc have on td widths if any? I am looking for a reason more than a fix. I am hoping to understand how it works.
This may not be what you want to hear, but display: table-cell does not respect width and will be collapsed based on the width of the entire table. You can get around this easily just by having a display: block element inside of the table cell itself whose width you specify, e.g
<td><div style="width: 300px;">wide</div></td>
This shouldn't make much of a difference if the <table> itself is position: fixed or absolute because the position of the cells are all static relative to the table.
http://jsfiddle.net/ExplosionPIlls/Mkq8L/4/
EDIT: I can't take credit, but as the comments say you can just use min-width instead of width on the table cell instead.
You're better off using table-layout: fixed
Auto is the default value and with large tables can cause a bit of client side lag as the browser iterates through it to check all the sizes fit.
Fixed is far better and renders quicker to the page. The structure of the table is dependent on the tables overall width and the width of each of the columns.
Here it is applied to the original example: JSFIDDLE, You'll note that the remaining columns are crushed and overlapping their content. We can fix that with some more CSS (all I've had to do is add a class to the first TR):
table {
width: 100%;
table-layout: fixed;
}
.header-row > td {
width: 100px;
}
td.rhead {
width: 300px
}
Seen in action here: JSFIDDLE
The reason it doesn't work in the link your provided is because you are trying to display a 300px column PLUS 52 columns the span 7 columns each. Shrink the number of columns and it works. You can't fit that many on the screen.
If you want to force the columns to fit try setting:
body {min-width:4150px;}
see my jsfiddle: http://jsfiddle.net/Mkq8L/6/
#mike I can't comment yet.
The reason, is, because you did not specify the width of the table, and your whole bunch of td's are overflowing.
This for example, i've given the table a width of 5000px, which I thought would fit your requirements.
table{
width:5000px;
}
It is the exact same code you provided, which I merely added in the table width.
I believe what is happening, is because your TD's are way past the default table width. Which you could see, if you pull out about 45 of your td's in each tr, (i.e. the code you provided in your question, not jsfiddle) it works exactly fine
Try this it work.
<table>
<thead>
<tr>
<td width="300">need 300px</td>
Try to use
table {
table-layout: auto;
}
If you use Bootstrap, class table has table-layout: fixed; by default.
My crazy solution.)
$(document).ready(function() {
$("td").each(function(index) {
var htmlText = "<div style='width:300px;'>" + $(this).text() +"</div>";
$(this).html(htmlText);
});
});
Use table-layout property and the "fixed" value on your table.
table {
table-layout: fixed;
width: 300px; /* your desired width */
}
After setting up the entire width of the table, you can now setup the width in % of the td's.
td:nth-child(1), td:nth-child(2) {
width: 15%;
}
You can learn more about in on this link: http://www.w3schools.com/cssref/pr_tab_table-layout.asp
If table width is for example 100%, try using a percentage width on td such as 20%.
Wrap content from first cell in div e.g. like that:
HTML:
<td><div class="rhead">a little space</div></td>
CSS:
.rhead {
width: 300px;
}
Here is a jsfiddle.
You can also use:
.rhead {
width:300px;
}
but this will only with with some browsers, if I remember correctly IE8 does not allow this. Over all, It is safer to just put the width="" attribute in the <td> itself.
I'm looking for a 3 column css layout, with 1 fixed section at the middle and 2 fluid sidebar around it:
http://www.uploadup.com/di-UEFI.png
middle has 250px width (for example) and sidebars have (at minimum) 150px width. if browser width was longer than 550px (250+300), sidebars should have a longer width. (and middle always is 250px)
What is the CSS can do it? with compatibility in all browsers.
note: i saw this page, but i don't know how to change it for my wish
You can try to use inline-blocks for it. They are used rather rarely, but sometimes they are pretty good for layouts.
So, look at this: http://jsfiddle.net/kizu/UUzE9/ — with inline-blocks you can create layouts with any number of fixed and fluid columns. The algorithm:
At first, you add the padding equal to the sum of all the fixed columns to the wrapper. In your case — 250px.
Then, you add min-width to the wrapper equal to the sum of all the fluid columns' min-width.
Then, you add white-space: nowrap to the wrapper, so the columns won't jump.
And then just add the all columns that you need.
If you need support for IE7 and lesser, there are some additional things to know except for common inline-block fix:
You must return white-space: normal to the inner child of a column, or the columns won't stay on one line.
There can appear a phantom scroll in IE, maybe there is a better way to remove it, but I just use overflow: hidden on some wrapper.
Enjoy :)
To make this work in IE6/7 without JavaScript, the easiest way to do this is with a table.
I know, I know. It's not that bad in this case, all considered.
See: http://jsfiddle.net/thirtydot/Q2Qxz/
Tested in IE6/7 + Chrome, and it will just work in all other modern browsers.
HTML:
<table id="container" cellspacing="0" cellpadding="0">
<tr>
<td id="left">fluid</td>
<td id="mid">fixed</td>
<td id="right">fluid</td>
</tr>
</table>
CSS:
html, body {
margin: 0;
padding: 0;
border: 0
}
#container {
border: 0;
table-layout: fixed;
width: 100%
}
#container td {
vertical-align: top
}
#mid {
width: 250px;
background: #ccc
}
#left {
background: #f0f
}
#right {
background: #f0f
}
If you don't use one of the ready templates out there,
You can start by three div floated left, the middle with width: 250px and the outside ones with
min-width: 150px
You might want to replace it with the <section> tag, just give it a display: block
This may seem like a blast from the past but due to project constraints I am stuck with quirks mode and tables...
The tables that i'm dealing with have a single image in each cell where all the cells should be the same size. The tables width and height are set as percentages of a parent container.
The problem is the images don't resize down, they stay at their original size seemingly no matter what I do. Then the table doesn't adhere to its set size, it has resized to hold all of the images. In standards mode I believe 'width: 100%' on the image gets closer to what I want to achieve.
I'm considering a javascript solution which loops over each image calculating what their size should be and resizing manually. But this is probably going to cause a bit of a loading time at the start which isn't ideal.
Edit:
I have written a basic example at JSBin. What I want to achieve is to be able to set the size of the table and have the images resize, whether growing or shrinking to their cell.
The 4th jsbin revision uses the dummy images.
I think I've solved this.
I've tested this demo in Chrome, Firefox, Internet Explorer, Safari, Opera; they all render consistently.
I had to add a wrapper div in each cell. I know this isn't awesome, but it had to be done to make it work in Chrome.
I added table-layout: fixed to make it work in Internet Explorer.
Live Demo
CSS:
#mycontainer {
width: 300px;
height: 300px;
border: 1px solid red;
}
#mytable {
height: 50%;
width: 50%;
table-layout: fixed;
}
#mytable div {
width: 100%;
height: 100%;
}
#mytable img {
width: 100%;
height: 100%;
}
HTML:
<div id="mycontainer">
<table id="mytable" cellpadding="0" cellspacing="0">
<tr>
<td><div><img src="http://dummyimage.com/28x28/000/fff.png&text=Dummy" /></div></td>
...
</tr>
...
</table>
</div>
I have solved my problem via JavaScript. I couldn't find a way to make all the browsers play nice without forcing them.
I basically loop over each image checking what their parent tables size was supposed to be, then divide that by the number of rows to find the image height and by columns for width.