JSFiddle - React, Tailwind, and code Playground
HTML
<div>My first sentence consists of words<span class="footnote">My first footnote.</span>. My first paragraph consists of two sentences<span class="footnote">My second footnote.</span>.
<p>We behave as footnotes should - we auto-extract the text and insert a page break as nescessary between text blocks. <span class="red">Right-click the "result" frame and choose "Print Frame" to see the footnotes appear aligned to the bottom of each page.</span></p></div>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ut eros ac lectus egestas malesuada a quis nulla. Praesent laoreet adipiscing elementum. Aliquam ultrices, dui placerat sollicitudin posuere, justo elit dapibus turpis, sit amet venenatis dolor metus at purus. Aenean aliquam magna eu ultricies ultricies. Maecenas sit amet interdum odio. In volutpat condimentum convallis. Suspendisse tempor nulla a pellentesque auctor.
</p><p>
Sed vestibulum<span class="footnote">My 3rd footnote.</span> facilisis tellus, vel convallis nisl lacinia id. Vestibulum lobortis diam vitae rutrum tincidunt. Suspendisse eros lacus, ultricies sit amet interdum at, scelerisque placerat ipsum. Nam euismod ligula auctor massa fermentum tristique. Integer volutpat iaculis auctor. Mauris quam nisi, consequat a nunc sagittis, porttitor aliquam massa. Duis eu mauris sem. Nullam porttitor enim a quam placerat vulputate et a augue. Donec varius velit eget justo semper vulputate. Morbi imperdiet elit in lacinia rhoncus.
</p><p>
In et risus vitae augue placerat pellentesque at vitae metus. Sed faucibus sapien eget viverra feugiat. In sit amet sagittis arcu. Sed vestibulum condimentum orci. Nunc ultricies laoreet mi, at blandit augue sagittis at. Etiam pretium, libero nec consequat posuere, risus leo laoreet dui, sit amet dapibus mauris neque vel eros. Cras tincidunt lorem vitae convallis pellentesque.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ut eros ac lectus egestas malesuada a quis nulla. Praesent laoreet...
CSS
/* courtesy of @apaul34208: http://stackoverflow.com/questions/23498447/printed-html-per-page-footnotes/23622470#23622470 */
*{
-moz-box-sizing: border-box;
box-sizing: border-box;
}
body, html {
font-size: 1em;
padding:0;
margin:0;
height:100%;
}
.pageWrapper {
position:relative;
border: 1px solid #000;
min-height:100%;
-webkit-region-break-inside: avoid; /* added these bits to work out print issue */
page-break-after: always;
page-break-inside: avoid;
}
.footnote {
float: footnote;
color: red;
}
.footer {
border-top:1px solid red;
position: absolute;
bottom:0;
}
.footerEntry {
height:15px;
font-size:8pt;
}
.red {
color: red;
}
JavaScript
var pageHeight = 970; // our print page height - for A4
var pageWidth = 670; // our print page width - for A4
var footnoteHeight = 15;
// First pass - identify footnotes, mark locations and replace all the footnote text
var footnoteCount = 0;
var pageFooterOffsets = [];
var pageFooterText = [];
var all = $('body').children();
all.wrapAll("<div id=\"tempDocWrapper\" style=\"width:"+pageWidth+"px; float:none;\" />");
function identifyFootnotes(extractText) {
footnoteCount = 0;
pageFooterOffsets = [];
$('.footnote').each(function (ind, el) {
var f = $(el);
var offset = f.offset();
pageFooterOffsets[footnoteCount] = offset.top;
if (extractText) {
pageFooterText[footnoteCount] = "<li value=\""+(footnoteCount+1)+"\" class=\"footerEntry\">" + f.html() + "</li>";
f.replaceWith("<sup class=\"footnote\">" + (footnoteCount+1) + "</sup>");
}
footnoteCount++;
});
}
identifyFootnotes(true);
// Second pass - Insert the footnotes at page boundaries
var currentFootnote = 0;
var lastFootnoteInPage = 0;
var currentPageElems = [ ];
var availHeight = pageHeight; // Initially, the available space for content is the whole page - this shrinks as we add footnotes.
if (footnoteCount > 0) {
all.each(function (ind, el) {
var div = $(el);
currentPageElems.push(div); // Capture all children on current page for later wrapping.
if (!div.is('div') && !div.is('p'))
return;
var domElem = div[0];
var offset = div.offset();
if (currentFootnote == footnoteCount)
return; // All finished
if (domElem.style.position != "" && domElem.style.position != "relative") {
return; // We ignore a fixed / absolute positioned div for determining page breaks
}
var currentPage = Math.ceil((offset.top+1) / pageHeight);
var pageStartPos = (currentPage - 1) * pageHeight;
while (lastFootnoteInPage <...