Skip to content

Instantly share code, notes, and snippets.

@MurakamiShinyu
Last active October 6, 2025 14:28
Show Gist options
  • Save MurakamiShinyu/20647c319981ec0613c6adab44d0ed6f to your computer and use it in GitHub Desktop.
Save MurakamiShinyu/20647c319981ec0613c6adab44d0ed6f to your computer and use it in GitHub Desktop.

CSS typesetting engine: Vivliostyle.js

The idea of Vivliostyle.js, since 2014

  • Develop an open-source CSS typesetting engine that runs on web browsers that anyone can freely use.
  • Use web browser's rendering engine and PDF output feature.
  • Support the latest web standards via web browsers.
  • Add support for CSS specifications for paged media:
    • CSS Paged Media
    • CSS Generated Content for Paged Media
    • CSS Fragmentation
    • CSS Page Floats
    • etc.

Advantages and disadvantages of using web browsers for rendering and PDF generation

Advantages of using web browsers:

  • CSS capabilities improve as browser rendering engines evolve
  • Can leverage the browser ecosystem
  • Possibility of real-time preview in browsers

Disadvantages of using web browsers:

  • Affected by browser bugs and changes
  • PDF generation feature has limitations depending on browsers

CSS Paged Media related specifications discussions

Page spread inside/outside support for CSS margin, float, etc. properties

Proposed specs:

Example:

figure {
  float: outside;   
  margin-inside: 1ch;
}
  • inside maps to left on right-page and right on left-page
  • outside maps to right on right-page and left on left-page

Implemented in Vivliostyle.js

vivliostyle/vivliostyle.js#1519

Added *-inside/outside properties:

  • margin-inside, margin-outside
  • padding-inside, padding-outside
  • border-inside, border-outside
  • border-inside-color, border-outside-color
  • border-inside-style, border-outside-style
  • border-inside-width, border-outside-width
  • inset-inside, inset-outside

Extended properties with inside and outside values:

  • float, clear
  • text-align, text-align-last

Other implementations

Question

Naming issue: spread-inside and spread-outside might be better than inside and outside. e.g. margin-spread-inside, margin-spread-outside

Advantages of spread-inside and spread-outside:

Advantages of inside and outside:

Two-dimensional page floats

Proposed specs:

Implemented in Vivliostyle.js

vivliostyle/vivliostyle.js#1444

float: none | [ block-start || block-end || inline-start || inline-end ||
       left || right || top || bottom ]

Examples:

float: top;        // float to top edge
float: top left;   // float to top left corner
…

Other implementations

Question

Stacking direction when multiple floats are placed in the same position.

for float: block-start (= float: top in horizontal-tb writing mode):

  • Stacking direction must be from block-start to block-end (top to bottom in horizontal writing mode)

for float: block-end (= float: bottom in horizontal-tb writing mode):

  • Aligned to block-end, but should be stacked from block-start to block-end.
    • Question: This may be inconsistent with traditional CSS floats, where boxes with float: inline-end (float: right in LTR text) are stacked from inline-end to inline-start. But is there a use case for stacking from block-end to block-start?

for float: block-start inline-start (= float: top left in horizontal and LTR writing mode):

  • Aligned to block-start and inline-start
  • Stacked from block-start to block-end
    • Question: Should be stacked from inline-start to inline-end first, then from block-start to block-end?

for float: block-start inline-end (= float: top right in horizontal and LTR writing mode):

  • Aligned to block-start and inline-end
  • Stacked from block-start to block-end
    • Question: Should be stacked from inline-start to inline-end or from inline-end to inline-start first, then from block-start to block-end?

Related Vivliostyle.js issue: Should 2D page floats be stacked in inline direction first?

Clearing page floats: clear: page and clear: column

Proposed spec:

Elements may request to clear page floats with the 'clear' property:

column: The page float requests to be the first page float at its favored position in the column; rather than being stacked after other page floats, it should be moved to the next possible position.

page: The page float requests to be the first page float on the page. If there is already another page float on the page, the page float is moved to the next page.

The placement process is iterative; if the requested position cannot be honored, the page float the next possible position is tried, etc.

When clear: page or clear: column is specified on a non-page-float element, it should also take effect and the element should be moved to the next page or column if preceding page floats exist in the current page or column.

Implemented in Vivliostyle.js

vivliostyle/vivliostyle.js#1551

Other implementations

CSS Notes (Footnotes, Side Notes, etc.)

Proposed spec:

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