Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PDF Table with slanted header

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>
like image 230
Jacqueline Connors Avatar asked Apr 12 '17 23:04

Jacqueline Connors


1 Answers

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.

like image 71
Sammy Avatar answered Nov 15 '22 22:11

Sammy