I'm using two flex tables. One for header and one for data.
The one for data is wrapped with a scroll panel.
The size of my columns is presented with percentage and this is where my problem begins:
I set the width of both tables to 100%.
The thing is that the scrollbar isn't always visible. It's visible only when required.
So when the scrollbar is shown - there's a gap between the width of the header and the width of the data area inside the scrollpanel. (since the scrollbar itself has width of 16px)
This way, the titles of the columns, doesn't match precisely the data columns.
Any suggestions?
Thanks in advance!
Based on your comment from my other answer you are left with having to code. I have solved this sort of problem in the past by using a shim column. I wouldn't call it elegant but it did the trick. Basically, you have an extra column in your header at the end that acts as a shim for the scrollbar. When the scrollbar is being displayed then the shim column is displayed with the exact width of the scrollbar. When there is no scrollbar you hide the shim.
Setup your layout with the additional column. Style it however you want. I usually make it so it blends in with the adjoining column so the user doesn't see a little square when it is being displayed.
Add all your data rows to the content table as you normally would. Make sure the content table and all its tr/td are added to the DOM.
Once the data is added then test whether the scrollbar is visible. You can do this by checking if the scroll height is greater then the offset height.
ScrollPanel scrollPanel;
Element scrollElem = scrollPanel.getElement();
if (scrollElem.getScrollHeight() > scrollElem.getOffsetHeight()) {
// scrollbar is visible
}
If the scrollbar is displayed then show your shim column, otherwise hide it.
if (scrollElem.getScrollHeight() > scrollElem.getOffsetHeight()) {
// scrollbar is visible - show shim column
shimColumnTD.getStyle().setDisplay(Display.BLOCK);
}
else {
// scrollbar not visible - hide shim column
shimColumnTD.getStyle().setDisplay(Display.NONE);
}
Determine the width of the shim column so that it matches the width of the scrollbar. If you go look inside the below method you can see how it does this.
// calculate the width of the scrollbar for the given browser
int shimWidth = AbstractNativeScrollbar.getNativeScrollbarWidth();
Obviously, this is just all pseudo but it should lead you in the right direction. Good luck...
There are a lot of possible things you can do to keep columns in sync, but most of them requires active layout and/or preview resize events.
I guess that, for your use case, is much simpler and (performance wise) far faster to either:
shrink both tables a bit, to always accomodate the space for the scrollbar (or even remove the scrollbars at all, keeping the scrolling behavior functionality). Both solutions are generally achieved by using a pair of nested div, with the second one wider enough to hide/accomodate the scrollbar;
wrap your second table into a panel that does not shrink the content when it overflows. In GWT you can do that natively using a CustomScrollPanel (instead a ScrollPanel). Just pay attention that is a RequiresResize panel that needs either an interrupted chain of ProvidesResize containers, or an explict size.
Side note: If you ever need to calculate the size of the native scrollbars in a cross browser solution, just use AbstractNativeScrollbar.getNativeScrollbarHeight() (and/or the width one).
A common trick for this sort of thing that avoids complex code and layout is to simply fix the widths of all your columns except the last one. The last column will auto adjust and you won't have to worry about the scrollbar at all.
Here is a jsfiddle sample along with some sample html/css to show you what I mean. The caveat is that all of the columns have to have width (they cannot be percentages) except the last one.
jsfiddle example
CSS:
.container {
width: 500px;
border: 1px solid red;
}
.content-wrapper {
overflow: auto;
height: 75px;
}
table {
width: 100%;
border-collapse: collapse;
}
col {
width: 100px;
}
col:last-child {
width: auto;
}
.container td {
border: 1px solid green;
}
HTML:
<div class="container">
<div class="header-wrapper">
<table class="header">
<colgroup>
<col/>
<col/>
<col/>
<col/>
<col/>
</colgroup>
<tr>
<td>Column A</td>
<td>Column B</td>
<td>Column C</td>
<td>Column D</td>
<td>Column E</td>
</tr>
</table>
</div>
<div class="content-wrapper">
<table class="content">
<colgroup>
<col/>
<col/>
<col/>
<col/>
<col/>
</colgroup>
<tr>
<td>Row 1/A</td>
<td>Row 1/B</td>
<td>Row 1/C</td>
<td>Row 1/D</td>
<td>Row 1/E</td>
</tr>
<tr>
<td>Row 2/A</td>
<td>Row 2/B</td>
<td>Row 2/C</td>
<td>Row 2/D</td>
<td>Row 2/E</td>
</tr>
<tr>
<td>Row 3/A</td>
<td>Row 3/B</td>
<td>Row 3/C</td>
<td>Row 3/D</td>
<td>Row 3/E</td>
</tr>
<tr>
<td>Row 4/A</td>
<td>Row 4/B</td>
<td>Row 4/C</td>
<td>Row 4/D</td>
<td>Row 4/E</td>
</tr>
<tr>
<td>Row 5/A</td>
<td>Row 5/B</td>
<td>Row 5/C</td>
<td>Row 5/D</td>
<td>Row 5/E</td>
</tr>
</table>
</div
</div>
Related
I have some design requirements for an email template where I have two "challenges":
two columns need to flip to one column
some visible border lines need to be switched from vertical to horizontal
The following shows how it should look (2 columns on the left for desktop, 1 column on the right for mobile):
The whole email is based on responsive tables and the two-column part is implemented as follows right now:
<table cellpadding="5" cellspacing="0"
style="background-color:#F6F6F6; font-size: 14px; color:#58595b; width:100%; border-collapse:collapse;">
<tr><td align="center" valign="top" height="10" colspan=2 style="line-height: 10px; font-size: 10px;"> </td></tr>
<tr>
<td valign="top" style="border-right: 1.5px solid; border-color: #d0d0d0; padding-right:40px; text-align:right; width:42%; vertical-align:top;">
Start point
</td>
<td valign="top" style="padding-left:40px; vertical-align:top;">
<strong>Fri, January 12, 2023 12:00</strong>
<br />
Harbour, Seatown
</td>
</tr>
<tr><td align="center" valign="top" height="10" colspan=2 style="line-height: 10px; font-size: 10px;"> </td></tr>
<tr>
<td valign="top" style="border-right: 1.5px solid; border-color: #d0d0d0; padding-right:40px; text-align:right; width:42%; vertical-align:top;">
End point
</td>
<td valign="top" style="padding-left:40px; vertical-align:top;">
<strong>So, January 18, 2023 10:00</strong>
<br />
Central Station, Capital
</td>
</tr>
<tr><td align="center" valign="top" height="10" colspan=2 style="line-height: 10px; font-size: 10px;"> </td></tr>
</table>
I tried the approach with having a left and a right table (explained here) but the problem is that I do not use fixed widths.
How could I achieve the required design with a responsive mail template?
You will need to use the technique as outlined in the link, but if you want to use percentages instead of fixed widths, then use width="50%".
This is because the technique works on the basic fundamentals of HTML, that if a block doesn't fit in the space available, it will automatically shift underneath.
So to enable the stacking without a fixed pixel width, you will need to add a #media query to force the stacking (otherwise it would not stack).
e.g.
#media (max-width: 620px)
.table-left,.table-right {
width: 100% !important;
}
(The article you link to is a bit outdated: don't use [class=...], just write it out normally. Gmail may strip the entire <style> section if it doesn't like something in it, and this is one of those things it doesn't like.)
I prefer an override (max-width, and !important) because you want everything possible inline, and only to use embedded styles where strictly necessary.
But that's also why it's best to use a fixed pixel width, because some email clients do not respect your embedded styles (styles in the <head>). GANGA emails (one form of Gmail account) fall into this category. Those email clients would not stack even though they may need to, if you fully rely on the #media query for the stacking.
To override the border, put a style on the <td>, and reference it in the #media query, e.g.
#media (max-width: 620px)
.border {
border-right:none!important;
}
.border-top {
border-bottom:1.5px solid #d0d0d0 !important;
}
As one doesn't have the same border structure (they don't both need border-bottom), one of the <td>s will need a different class. Here, I'm expecting the first one, i.e. <td class="border border-top">.
I'm trying to create a pricing recap at the end of a document I'm working on. I would like it to have a dotted line between the item on the left and the price on its right, very much like this :
However, this Index is generated with the createIndex function and I don't have the source HTML for this. And I've been trying since yesterday with differente HTML syntaxes to make it work but it is impossible. My best attempt so far is this one, but I can't automatically set the width of the dotted line :
<table style="width:100%;border-collapse: collapse;">
<tr>
<td style="width:40%;white-space:nowrap;">Item 1</td>
<td style="border-bottom:dotted 1px black;width:45%;"></td>
<td style="text-align:right;width:15%;white-space:nowrap;">Price 1€ HT</td>
</tr>
</table>
I really am stuck here, any advice would be welcome.
In this case you can use a little 'hack'. Unset the width of both texts (resolves to width: auto;) and set the width of the dotted line container to width: 99%;. For this to work you also need to set white-space: nowrap on the text elements, but you already did that.
<table style="width:100%;border-collapse: collapse;">
<tr>
<td style="white-space:nowrap;">Item 1</td>
<td style="border-bottom:dotted 1px black;width:99%"></td>
<td style="text-align:right;white-space:nowrap;">Price 1€ HT</td>
</tr>
</table>
As soon as I started coding responsive emails, I noticed that contiguous images (all with the same original height) in a HTML table row didn't always remain the same height when being responsively scaled. That's a big problem for me because the email layouts that I am working on are image heavy and have to be tightly aligned. Uneven height images break the layout. I eventually came up with the solution presented here: http://am-samples.gear.host/iPhone5S-iO7-issue.html
Navigate to that URL and resize the browser to see the responsive scaling in action.
Here are the main snippets in case you can't navigate to the URL above:
Table that has the contiguous images
<table class="100p" width="100%" cellspacing="0" cellpadding="0" border="0" align="center" bgcolor="#7fff00" style="background-color: #7fff00;">
<tr>
<td class="100p" align="center" width="100%" valign="top">
<div>
<table class="100p" width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td class="100p" width="100%" align="left" valign="top">
<span width="26.09375%" style="width: 26.09375%; display: inline-block;">
<img id="ourStory" class="responsiveImage" src="http://am-samples.gear.host/images/bottom-our-story.png" border="0" style="display: block;" />
</span><span width="19.6875%" style="width: 19.6875%; display: inline-block;">
<img id="recipes" class="responsiveImage" src="http://am-samples.gear.host/images/bottom-recipes.png" border="0" style="display: block;" />
</span><span width="25.15625%" style="width: 25.15625%; display: inline-block;">
<img id="seafood" class="responsiveImage" src="http://am-samples.gear.host/images/bottom-seafood.png" border="0" style="display: block;" />
</span><span width="29.0625%" style="width: 29.0625%; display: inline-block;">
<img id="giftCards" class="responsiveImage" src="http://am-samples.gear.host/images/bottom-giftcards.png" border="0" style="display: block;" />
</span>
</td>
</tr>
</table>
</div>
</td>
</tr>
</table>
CSS classes referenced
.responsiveImage {
max-width: 100% !important;
width: 100% !important;
height: auto !important;
border: none;
}
*[class="100p"] {
width: 100% !important;
height: auto !important;
}
I've stripped the code down to the essentials just to clearly present the issue. If you take a look at the source code, you'll see that the top and bottom black strips are just tables with a black background color. The red strip is actually made up of contiguous images. The original height of all the images is the same. Because of that I expected the height of all the images to scale equally. The table that contains the images has a background color of florescent green. That way, in Litmus, it is easy to see if the height of any of the images is different.
I've tested this solution in Litmus and it works fine on the email clients that I am interested in except two: iPhone 5S (iOS7 and iOS8). Here is a screenshot of the result in iPhone 5S and iOS7 (iOS 8 produces a similar result) : http://am-samples.gear.host/images/iPhone5S-iOS7-issue.jpg
So the problem is that when scaling, sometimes the image heights are not all equal. Any ideas on how to fix this on the iPhone 5S?
Different widths with the same height makes the images a different scale, which means that as they shrink through the 100% w x auto h, they will differ in height.
To retain consistent height/width through mobile I would make sure that the scale is identical. E.g. make all images 100px x 50px. (you can use percents here if you wish too)
The only other option I can really offer from what I see is a defined height to force each to that amount, but in HTML email, this is not likely to be followed by the email clients processors.
I am using XMLWorker and itext to convert html to pdf .
my html have a table and I need to set it's cellspacing =0 cellpadding=0 .
does anyone know how to do it ?
in html I saw I can replace it by setting the style :
border-collapse: collapse;
border-spacing: 0px ;
border : 0;
padding : 0;
thanks
Tami
I've tried what you're doing using the CSS you propose and it works for me:
You can find my test here: ParseHtmlTable5
This is my HTML (including the CSS): table3_css.html
<html>
<head>
<style>
table, td {
border: 1px solid green;
border-spacing: 0px;
padding: 0px;
}
</style>
</head>
<body>
<table class='test'>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Savings</th>
</tr>
<tr>
<td>Peter</td>
<td>Griffin</td>
<td>$100</td>
</tr>
<tr>
<td>Lois</td>
<td>Griffin</td>
<td>$150</td>
</tr>
<tr>
<td>Joe</td>
<td>Swanson</td>
<td>$300</td>
</tr>
<tr>
<td>Cleveland</td>
<td>Brown</td>
<td>$250</td>
</tr>
</table>
</body>
</html>
I suggest that you compare your HTML with mine to find out what you're doing wrong.
You should also use the latest version of XML Worker and iText(Sharp) as we've improved HTML parsing significantly in the latest releases.
Note that I've defined a solid, green border of 1px to prove that there is no padding and no spacing between the cells. If you change the CSS like this:
<style>
table, td {
border: 0px;
border-spacing: 0px;
padding: 0px;
}
</style>
You'll get the (ugly) version of a table without borders, without spacing between the cells and without padding inside the cells.
I am creating an email template to use in Pardot. I have coded the email up. It works fine in OSX Mail, Outlook 07 +, Opera Mail, however GMail is being a real pain. It is adding some weird height or something to the tr or td in my table.
Any suggestions?
<table border="0" cellpadding="0" cellspacing="0" width="228">
<tbody>
<tr valign="bottom">
<td valign="bottom"><span pardot-region=""><img src="widget_top.jpg" alt="Placeholder"></span></td>
</tr>
<tr bgcolor="#ffd13f">
<td style="padding: 10px;">
<h2><span pardot-region="">Subheading span across one or two lines for best practice:</span></h2>
<span pardot-region=""><p><b>Date:</b> Thursday 29 November</p>
<p><b>Time:</b> 1.30pm (GMT)</p>
<p><b>Where:</b> Register online ></p>
<p><b>Topic:</b> Dynamic performance management</p>
<p><b>Presenters:</b> Octavius Black, CEO and Sebastian Bailey, President</p></span>
</td>
</tr>
<tr valign="top">
<td valign="top"><span pardot-region=""><img src="widget_bottom.jpg" alt="Placeholder"></span></td>
</tr>
</tbody>
</table>
(this table is inside a set of tested tables).
Screen shot can be found here: http://i45.tinypic.com/15wzda9.png
Cheers :)
On the images you have to put (inline)
style="display:block;"
:)
display:block; is definitely needed. You probably should zero out everything in all img tags, and set width and heights also.
<img style="margin: 0; border: 0; padding: 0; display: block;" src="" width="600" height="150"
alt="">
Also, you don't need the spans inside the table cells. If you want to keep them, make sure they have margin and padding zero'd out there too.