CSS Paged Media implementation in Vivliostyle.js

2021-04-10
Shinyu Murakami
Vivliostyle Foundation

Contents

  1. CSS typesetting engine: Vivliostyle.js Core
    1. The idea of Vivliostyle.js, since 2014
    2. Which CSS specifications are required for CSS typesetting?
    3. Redeveloping CSS Paged Media support
  2. Let's get familiar with CSS Paged Media!
    1. Named strings—for running headers
    2. Named pages—page type selector
    3. Nth page selector: nth()
  3. Summary of supported CSS specs for paged media
    1. CSS Paged Media Level 3
    2. CSS Generated Content for Paged Media (GCPM)
    3. CSS Fragmentation Level 3
    4. CSS Page Floats
    5. For more info, visit Vivliostyle Documents→Supported CSS Features

CSS typesetting engine: Vivliostyle.js Core

The idea of Vivliostyle.js, since 2014

Which CSS specs are required for CSS typesetting?

Vivliostyle.js uses web browsers,
so it can basically use any CSS specs for the web.
We just need to add support for CSS specs for paged media🌟

And so Vivliostyle.js development began. 👉History of Vivliostyle

Redeveloping CSS Paged Media support

Many CSS paged media features have been implemented in Vivliostyle.js for quite some time. (Thanks to the early devs 🙏)

However, a few important features remained unimplemented.

And finally, since the end of 2020, we have made some progress.

🌟CSS features for page media now available in the latest version:

Let's get familiar with CSS Paged Media!

Named strings—for running headers

Example usage of named string:

@page :right {  /* chapter title in the right page top-right header */
  @top-right {  /* except in the first page of the chapter */
    content: string(chap-title, first-except); 
  }            
}
h1.chapter {          /* chapter heading */
  string-set: chap-title content();
}
h1.chapter[title] {   /* can also use an attribute value */
  string-set: chap-title attr(title);
}

Named pages—page type selector

Define page style by naming each type of page. Example:

@page cover { /* Named page rule (name: "cover") */
  margin: 0;  /* "cover" page should have no margins */

  /* "cover" page should have no page headers */
  @top-left { content: none; }
  @top-right { content: none; }
}

.cover {
  page: cover;  /* specify the named page with the page property */
}

Nth page selector: nth()

Define the style of the Nth page of a document.

Syntax: @page :nth(An+B)
(Like a page version of the :nth-child(An+B) selector)

Example:

@page :nth(1) {
  margin: 0;
  background-image: url(cover.png);
}

Difference between :first and :nth(1) in multiple HTML documents concatenated

When combining multiple HTML documents into a single book (PDF, WebPub):

  • @page :first matches only the first page of the first document.
    • This is how Vivliostyle already behaved. Note that the current CSS Paged Media spec does not define the behavior when combining multiple HTML documents into a book, so this behavior is not a standard.
  • @page :nth(1) matches the first page of each document.

That is, if you have separate files for each chapter, @page :nth(1) matches the first page of each chapter, and @page :first matches only to the first page of the whole book.

Combination of named page and :nth() example

@page :first { /* matches only the first page of the whole book */
  counter-reset: chapter;
}
@page chapter:nth(1) { /* the first page of each chapter file */
  counter-increment: chapter;
}
h1::before {
  content: "Chapter " counter(chapter) ". ";
}
.chapter {
  page: chapter;
}

The HTML file for each chapter looks like:

<body>
  <section class="chapter">
    <h1>The chapter title</h1>
    ...
  </section>
</body>

This allows you to initialize the chapter counter at the beginning of the whole book and increment it at the beginning of each chapter.

Note: If you have multiple chapters in a single HTML file, @page chapter:nth(1) will match only the first page of the HTML file, not each chapter.

Summary of supported CSS specs for paged media

CSS Paged Media Level 3

https://www.w3.org/TR/css-page-3/

CSS Generated Content for Paged Media (GCPM)

https://www.w3.org/TR/css-gcpm-3/

CSS Fragmentation Level 3

https://www.w3.org/TR/css-break-3/

CSS Page Floats

https://www.w3.org/TR/css-page-floats-3/

For more info, visit Vivliostyle Documents→Supported CSS Features