Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

html: margins have no effect #2924

Closed
HackbrettXXX opened this issue Sep 23, 2020 · 34 comments · Fixed by #2977
Closed

html: margins have no effect #2924

HackbrettXXX opened this issue Sep 23, 2020 · 34 comments · Fixed by #2977

Comments

@HackbrettXXX
Copy link
Collaborator

HackbrettXXX commented Sep 23, 2020

The documentation and code suggest that the user can set page margins in the html method, but they have no effect. The margin options seem to get lost somewhere.

@HackbrettXXX
Copy link
Collaborator Author

Some afterthoughts: The behavior between margins and the x/y and width (#2925) options is not immediately clear. I suggest the following:

  • on the first page (the current page when html is called), the start actualX (actualY) is the maximum of the x (y) value and the left (top) margin
  • on subsequent pages, the starting y coordinate should be the top margin. The x coordinate should still be the max of x and left margin
  • Similar to x/y, the width option should be constrained by the right margin: if actualX + width would extend beyond the right margin, set the width to pageWidth - actualX - right. So the formula would be: actualWidth = min(width, pageWidth - actualX - right)
  • The bottom margin is simply the margin at the bottom of each page

@TopDev114
Copy link

.html is much better than addHtml, fromHtml, etc.
I installed jspdf@2.1.1 for .html use.
Please let me know why the margin is not working in .html.
I want to use this method urgently.

@TopDev114
Copy link

TopDev114 commented Sep 29, 2020

I installed jspdf@2.1.1 for .html use.
Please let me know why the margin is not working in .html.
I want to use this method urgently.

@jaq-czaplin
Copy link

Same problem. Margins in html method has no effect :(
Also width and height of html2canvas options does not seam to make any difference eather...
I'm using version 2.1.1.

@staghouse
Copy link

Make sure you are avoiding collapasing margins. For example margin-bottom on one element, and margin-top on an element below it will collapse inward to the element NOT to the margins

@ncioj10
Copy link

ncioj10 commented Oct 5, 2020

@HackbrettXXX Yes I think that may be very useful, I currently have a letter generation use case and am dearly missing this feature.

@kevinborg
Copy link

Ok so has there been anyone who managed to solve this ? yes @HackbrettXXX my issue was a duplicate. I am setting margin with an array of random numbers but this has no effect on the printed pdf. I am using using the latest version of jsPdf and setting of margins does not work. v2.1.1 seems like it is very limited to customizability using the html() plugin compared to the previous versions of jsPdf using fromHtml() & addHtml() Do I have to install previous version below 2.0.0 such as 1.5.3 to achive the desired outcome ?

@kevinborg
Copy link

Please can someone guide me on this ? I desperately need tis margin feature !!

@HackbrettXXX
Copy link
Collaborator Author

@kevinborg If you need the margins right now, you need to downgrade back to 1.5.3 and use from/addHTML.

If it can wait, you may wait for this issue to be resolved. You may also prepare a pull request yourself if it is urgent.

@kevinborg
Copy link

@HackbrettXXX I have downgraded to 1.5.3 but this causes a problem were the downloading a pdf does not work and i am unable to debug this because no console error is thrown. I have installed html2canvas separately and using addHTML method as shown below

    const source = window.document.getElementById('invoice');
    const pdf = new jsPDF('p', 'pt', 'a4');
    const options = {
      pagesplit: true
    }
    pdf.addHTML(source, 15, 25, options, () => {
        pdf.save('file.pdf');
    }); 

am I doing something wrong or missing something here ? Also do i need to install a specific version of html2canvas ?

@bjornhansen
Copy link

I'd also like to use margins with the .html() method. It's fantastic, but when I have an element too tall to display on one page, the split happens exactly at the page edge -- not good for printing.

Are there plans to fix this or update the documentation?

@HackbrettXXX
Copy link
Collaborator Author

We will fix this as soon as someone from the community provides a pull request. I personally don't have time for this currently.

@emildatcu
Copy link

Did anyone fixed or found a workaround for this problem?

I also really need this 'feature' to work properly. I think that 'upgrades' like this one, when a default behavior is getting broke, it should be a priority in getting it working. It shouldn't be an issue in the first place.

It's freaking frustrating when a library says it's doing something, and after you install it and use it, you realize that it's not actually doing what it's supposed to do...

@jeffsieu
Copy link
Contributor

@HackbrettXXX I would love to have a go at this, but I'm currently having trouble running the html function from the debugging page (from npm start).

It keeps giving this error:
image

@HackbrettXXX
Copy link
Collaborator Author

@jeffsieu thanks. I'm assigning you.

In your debugging page, you need to load html2canvas (and dompurify if you pass a string to html). You can do so by adding a script tag, e.g.

<script src="node_modules/html2canvas/dist/html2canvas.js"></script>

@jeffsieu
Copy link
Contributor

@HackbrettXXX Is the content supposed to be scaled to fit the margins? And to be clear, is it context2d.js that manipulates the position/scale of the output?

@HackbrettXXX
Copy link
Collaborator Author

@emildatcu I understand that this is frustrating, but please understand that this is a (free!) open source library that's currently maintained by a single person (me). And I simply don't have the time to fix everything immediately. Even keeping up with all new issues and pull requests is hard. That's why it's open source and everyone can contribute to this project :)

@HackbrettXXX
Copy link
Collaborator Author

@jeffsieu The content should not be scaled to fit the margins. Instead, consider it as if the drawing canvas is the entire page minus the margins. If something would extend beyond the left/right margin, we should clip that. If something extends below the bottom margin, start a new page (with the top margin). See also my #2924 (comment).

The position is AFAIK partly controlled by context2d.js and partly html.js. I'm not too familiar with both files.

@jeffsieu
Copy link
Contributor

@HackbrettXXX After a bit of digging around in the code, I still find it quite challenging to fully understand what's going on in the library.

To my understanding, the html function takes in an html element, then puts it in a pre-defined container, passes that container to html2canvas, then takes the resultant canvas and assigns it as a property of context2d, after which it gets turned into a pdf.

I'm still unsure at which point in the code does the canvas get split into pages, which is probably where the margin needs to be added. Can you provide any guidance?

@HackbrettXXX
Copy link
Collaborator Author

The html module passes this.canvas to html2canvas, so all canvas API calls from html2canvas are consumed by the canvas.js module.

The splitting into pages is controlled by the autoPaging property in the context2d module. As far as I can see, the splitting happens in 3 functions: drawImage, pathPreProcess, and putText.

@jeffsieu
Copy link
Contributor

Ok, I managed to get the top and left margins working, but I'm unsure how to modify the pdf renderer to cut off at the right and bottom margins. As Context2D is making calls to putText which does this.pdf.text(...), I think something will have to be changed in jspdf.js?

@Jigisha-sublime
Copy link

@kevinborg If you need the margins right now, you need to downgrade back to 1.5.3 and use from/addHTML.

If it can wait, you may wait for this issue to be resolved. You may also prepare a pull request yourself if it is urgent.

Hello,
I am using .html API in my project and can't downgrade to the older versions because I need to use some good styling features which are not supported in older versions, can you please suggest any workaround for the bottom margin? I can manage everything else by customizing my content but we really need support for the bottom margin.
Can anyone please suggest any workarounds for this requirement?

P.S. I can not use html2Canvas as well as I need the pdf text to be selectable.

@datcuemil
Copy link

@Jigisha-sublime, I used this as a workaround at least until this issue is fixed and works, and the text is selectable:
`const downloadPDF = () => {
const content = contentRef.current;
if (!content) {
return;
}
const doc = new jsPDF({
orientation: 'portrait',
unit: 'pt',
format: 'a4',
});

const opt = {
  margin: [5, 0, 8, 0],
  filename: `${report.name} - ${moment().format(
    'DD.MMM.YYYY',
  )}.pdf`,
  enableLinks: false,
  pagebreak: {
    avoid: ['tr'],
    mode: ['css', 'legacy'],
  },
  image: { type: 'jpeg', quality: 1 },
  html2canvas: {
    allowTaint: true,
    dpi: 300,
    letterRendering: true,
    logging: false,
    scale: 2,
    scrollX: 0,
    scrollY: 0,
  },
  jsPDF: { doc },
};

html2pdf()
  .from(content)
  .set(opt)
  .toPdf()
  .get('pdf')
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  .then((pdf: any) => {
    const totalPages = pdf.internal.getNumberOfPages();

    for (let i = 1; i < totalPages + 1; i++) {
      pdf.setPage(i);
      pdf.setFontSize(8);
      pdf.text(
        `${i}/${totalPages}`,
        pdf.internal.pageSize.getWidth() - 10,
        pdf.internal.pageSize.getHeight() - 5,
      );
    }
  })
  .save();

}`

hope it helps you as well :)

@Jigisha-sublime
Copy link

@datcuemil, thanks for your response.
I tried the same function, it's working for margins but the text is still not selectable.
I am using
jspdf ( V 2.1.1.) and
html2pdf.js ( V 0.9.2 ).
any suggestions?

@Jigisha-sublime
Copy link

Also, is there any way we can repeat the HTML header on each page with this method?
Not just doc.text() but adding actual HTML content as a header
i.e. <p> Header part </p> or some logo images.

@vasuneet
Copy link

vasuneet commented Feb 8, 2021

I am also not seeing any effect of margin attributes. I am using html to render div contents and its splitting the text in between. margin has no impact at all

@vandum
Copy link

vandum commented Mar 9, 2021

I just update version 2.3.1 . It ok. But #2924 sill problem. I hope you will fix soon.

@JamesDAdams
Copy link

@vandum that not working i have that :
image

@msankar1991
Copy link

Is any fix done in latest version about margins ?

@Xstyler85
Copy link

I have the same problem

@yogeshparmar22
Copy link

I have to the same problem

@IkamG
Copy link

IkamG commented Feb 14, 2023

still an issue

@yatkolenko
Copy link

yatkolenko commented Dec 21, 2023

any updates? also have problem with margins between pages in PDF

image

@hayyangovinda
Copy link

@yatkolenko
Hello ,I think it is ok now, the method .html accepts margin as option ,pass it ,,then it should be fine :
image
table

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.