chromium/components/printing/resources/print_header_footer_template_page.html

<!doctype html>
<html>
<head>
<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
<style>
  body {
    display: flex;
    flex-direction: column;
    margin: 0;
  }

  #header,
  #footer {
    display: flex;
    flex: none;
  }

  #header {
    align-items: flex-start;
    padding-top: 15pt;
  }

  #footer {
    align-items: flex-end;
    padding-bottom: 15pt;
  }

  #content {
    flex: auto;
  }

  .left {
    flex: none;
    padding-left: 24pt; /* csschecker-disable-line left-right */
    padding-right: 6pt; /* csschecker-disable-line left-right */
  }

  .center {
    flex: auto;
    padding-left: 24pt; /* csschecker-disable-line left-right */
    padding-right: 24pt; /* csschecker-disable-line left-right */
    text-align: center;
  }

  .right {
    flex: none;
    /* historically does not account for RTL */
    padding-left: 6pt; /* csschecker-disable-line left-right */
    padding-right: 24pt; /* csschecker-disable-line left-right */
  }

  .grow {
    flex: auto;
  }

  .text {
    font-size: 8pt;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
</style>
<script>

function getComputedStyleAsFloat(style, value) {
  return parseFloat(style.getPropertyValue(value).slice(0, -2));
}

function elementIntersects(element, topPos, bottomPos, leftPos, rightPos) {
  const rect = element.getBoundingClientRect();
  const style = window.getComputedStyle(element);

  // Only consider the size of |element|, so remove the padding from |rect|.
  // The padding is used for positioning.
  rect.top += getComputedStyleAsFloat(style, 'padding-top');
  rect.bottom -= getComputedStyleAsFloat(style, 'padding-bottom');
  rect.left += getComputedStyleAsFloat(style, 'padding-left');
  rect.right -= getComputedStyleAsFloat(style, 'padding-right');
  return leftPos < rect.right && rightPos > rect.left && topPos < rect.bottom &&
         bottomPos > rect.top;
}

function setupHeaderFooterTemplate(options) {
  const body = document.querySelector('body');
  const header = document.querySelector('#header');
  const footer = document.querySelector('#footer');

  body.style.width = `${options.width}px`;
  body.style.height = `${options.height}px`;
  header.style.height = `${options.topMargin}px`;
  footer.style.height = `${options.bottomMargin}px`;

  const topMargin = options.topMargin;
  const bottomMargin = options.height - options.bottomMargin;
  const leftMargin = options.leftMargin;
  const rightMargin = options.width - options.rightMargin;

  header.innerHTML = options['headerTemplate'] || `
    <div class='date text left'></div>
    <div class='title text center'></div>`;
  footer.innerHTML = options['footerTemplate'] || `
    <div class='url text left grow'></div>
    <div class='text right'>
      <span class='pageNumber'></span>/<span class='totalPages'></span>
    </div>`;

  const date = new Date(options.date);
  const formatter =
      new Intl.DateTimeFormat(
          navigator.languages[0].split('@')[0],
          { dateStyle: 'short', timeStyle: 'short' });
  options.date = formatter.format(date);
  for (const cssClass of ['date', 'title', 'url', 'pageNumber', 'totalPages']) {
    for (const element of document.querySelectorAll(`.${cssClass}`)) {
      element.textContent = options[cssClass];
    }
  }
  for (const element of document.querySelectorAll(`.text`)) {
    if (options.isRtl &&
        !element.classList.contains('url') &&
        !element.classList.contains('title')) {
      element.dir = 'rtl';
    }
    if (elementIntersects(element, topMargin, bottomMargin, leftMargin,
                          rightMargin)) {
      element.style.visibility = 'hidden';
    }
  }
}

</script>
</head>
<body>
  <div id="header"></div>
  <div id="content"></div>
  <div id="footer"></div>
</body>
</html>