9

I'm creating PDFs in ColdFusion using cfdocument. I need to make a table with the header row slanted so it all fits on the page. Here's an example of what I'm trying to accomplish.Example I created in GIMP None of the HTML or CSS examples I have found so far have worked. Now I'm wondering if this is a quirk specific to ColdFusion and/or PDFs creation. I know this code came directly from an answer to a similar question here, but it does not create a table with slanted columns in my PDF. It creates this. My result, which is not slanted

//CSS
* {
  box-sixing: border-box;
}

.outerDiv {
  background: grey;
  height: 200px;
  width: 100px;
  border: 1px solid black;
  border-bottom: 0;
  border-left: 0;
  transform: skew(-30deg) translateX(58%);
}

th:first-child .outerDiv {
  border-left: 1px solid black;
  position: relative;
}

.innerDiv {
  position: absolute;
  width: 250px;
  height: 85px;
  bottom: -34%;
  left: 10px;
  transform: skew(30deg) rotate(-60deg);
  transform-origin: 0 0;
  text-align: left;
}

body,
html {
  height: 100%;
}

body {
  display: flex;
  justify-content: center;
}

table {
  border-collapse: collapse;
}

td {
  border: 1px solid black;
}

.well {
    min-height: 20px;
    padding: 5px;
    margin-bottom: 10px;
    background-color: #f5f5f5;
    border: 1px solid black;
    border-radius: 3px;

}

.well_tight {
    padding: 3px;
    margin-bottom: 5px;
    background-color: #f5f5f5;
    border: 1px solid black;
    border-radius: 3px;

}

//ColdFusion/HTML

<cfdocument format="pdf" name="#formname#" pagetype="letter" marginleft=".25" marginright=".25" margintop=".25" marginbottom=".5">

<cfoutput><style type="text/css">@import "/mach15/web/assets/css/formPDF.css";</style></cfoutput>


<div class="well">
     <table cellpadding="0" cellspacing="0">
          <tr>
                <th>
                  <div class="outerDiv">
                    <div class="innerDiv">This is first column header</div>
                  </div>
                </th>
                <th>
                  <div class="outerDiv">
                    <div class="innerDiv">This is second column header</div>
                  </div>
                </th>
                <th>
                  <div class="outerDiv">
                    <div class="innerDiv">This is third column header</div>
                  </div>
                </th>
          </tr>
          <tr>
                <td> 1 </td>
                <td> 2 </td>
                <td> 3 </td>
          </tr>
          <tr>
                <td> 4 </td>
                <td> 5 </td>
                <td> 6 </td>
          </tr>
          <tr>
                <td> 7 </td>
                <td> 8 </td>
                <td> 9 </td>
          </tr>
          <tr>
                <td> 10 </td>
                <td> 11 </td>
                <td> 12 </td>
          </tr>
    </table>
</div>
  • 1
    Well it works as html, so it definitely a cfdocument limitation. It only [supports CSS2](https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-tags/tags-d-e/cfdocument.html) (mostly) and `transform` is CSS3. Closest I have found so far is [this old thread](https://forums.adobe.com/thread/80941) which mentions a few hacks (though neither is very good IMO). – Leigh Apr 12 '17 at 23:39
  • 1
    I recommend using WKHTMLTOPDF (a free command line program) with ColdFusion 8, 9, 10, 11 & 2016 to generate PDF documents. I've had good success with slanted/rotated text, shadows, webfonts (fontawesome), SVGs, CSS gradients, Alpha PNG support, relative/absolute position, etc. – James Moberg Apr 13 '17 at 04:21
  • 1
    Yes, I doubt slanted text is possible with cfdocument. @JamesMoberg - If you have an example of creating slanted text with WKHTMLTOPDF, feel free to post it as an answer, as it would probably be helpful to others in the future. – Leigh Apr 13 '17 at 15:41
  • I'll see what I can do. The HTML provided in the sample doesn't work "as is", so I'm thinking that some chrome-specific CSS transform rules may need to be added or potentially use some JS to convert to canvas on-the-fly. – James Moberg Apr 14 '17 at 15:41

2 Answers2

2

I work on styling PDF documents using cfdoucment quite a bit and have had a lot of trouble with CSS. so many features aren't supported that would make styling the PDFs so much easier: CSS3 properties, CSS Pseudo elements and not even the !important tag can be used unfortunately.

There are however enough tricks and work arounds that you can use to (somewhat) achieve your desired results, they usually require customizing your markup a bit, Here's how I would go about solving your problem:

First: Getting a table with bordered cells/rows is not a fun task with CSS for CF PDF. One of the CSS Properties that's not supported is border-collapse: collapse; so if you use tables there will be spaces between cells, etc.. you'll end up with something like this for a standard table:

enter image description here

So I would probably generate a separate markup using <div> just for your PDF content and add a pdf-only class or something to it to display only on PDFs and hide elsewhere.


In your questions there are 2 problems that cannot be fixed due to CSS's limitation. 1) slanted lines 2) vertical slanted text.

1) Slanted lines:

I was able to create the slanted blocks by attaching a background image (see below) to the header cells and shifting them along with some other css code that's hopefully easy to follow:

enter image description here

.th {
    padding:10px 0;
    height: 200px;
    position: relative;
    left:50px;
    border-top: 1px solid #000;
    background:url(../img/line.gif) no-repeat right center;
}

Here's the full markup with the CSS:

<div class="table-wrapper pdf-only">
  <div class="row th-row">
    <div class="th th1">&nbsp;</div>
    <div class="th th2">&nbsp;</div>
    <div class="th th3">&nbsp;</div>
    <div class="th th4">&nbsp;</div>
  </div>
  <div class="row td-row first-td-row">
    <div class="td td1">Row 1</div>
    <div class="td td2"><span class="td-border"></span>r1c1</div>
    <div class="td td3"><span class="td-border"></span>r1c2</div>
    <div class="td td4"><span class="td-border"></span>r1c3<span class="td-last-border"></span></div>
  </div>
  <div class="row td-row">
    <div class="td td1">Row 2</div>
    <div class="td td2">r2c1</div>
    <div class="td td3">r2c2</div>
    <div class="td td4">r2c3</div>
  </div>
</div>

CSS:

.table-wrapper {
    width:75%; // so that the last column won't get cut off
    position: relative;
}

.row {
    width: 100%;
}

.td-row {
    border-bottom:1px solid #000;
    width: 100%;
    position: relative;
}

.td {
    padding:15px 0;
    text-indent: 10px;
    position: relative;
}

.th {
    padding:10px 0;
    height: 200px;
    position: relative;
    left:50px; // this should the same as the width of line.gif
    border-top: 1px solid #000;
    background:url(../img/line.gif) no-repeat right center;
}


/* Adjust the td, th widths below . You can even add different % to 
different cols as long as the total adds up to 100% per row. */

.td, .th {
    width: 25%; 
    float: left;
}

.th1 {
    border-top: 0;
}

span.td-border {
    height:1000px;
    width: 1px;
    position: absolute;
    border-left: 1px solid #000;
    left: 0;
    top:0;
}
span.td-last-border {
    height:1000px;
    width: 1px;
    position: absolute;
    border-left: 1px solid #000;
    right: -10px;
    top:0;
}

.first-td-row {
    border-bottom: 1px solid #000
}

Here's what you'll get: (this is an actual generated PDF using <cfdocument>)

enter image description here

so that takes care of the slanted headers


2) Vertical Text

I can think of 2 solutions, none of which are ideal, but then again we're styling CF PDFs so we'll have to get creative.

To get exactly what you have posted in your question (rotated text) I believe the only way to achieve this is using images instead of texts. Yeah I know it's cheating specially if your tables are going to be dynamic with the header texts constantly changing this won't work. But if this list won't change too much you might as well use images, example:

enter image description here

You would then add another element inside your header cell and set that image as its background and center position it:

<div class="th th1">
  <div class="text"></div>
</div>

.th .text {
  width:100%;
  height:100%;
  position:absolute;
}

.th1 .text {
  background-image:url(../img/col1-text.gif) no-repeat center center;
}

If using images as texts won't work, you can perhaps loop through the text and and a line break after each letter followed by a space and increment it each time in a descending fashion:

&nbsp;&nbsp;&nbsp;1<br/>
&nbsp;&nbsp;l<br/>
&nbsp;o<br/>
C<br/>

That obviously doesn't rotate the text, but it will make it easier to fit the content in the header.

Hope that helps.

Sammy
  • 3,059
  • 4
  • 23
  • 32
0

Are you using CF11 or above? If so, please use <cfhtmltopdf> with much better css support instead of the legacy <cfdocument>.

https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-tags/tags-g-h/cfhtmltopdf.html

Henry
  • 32,689
  • 19
  • 120
  • 221