On Tuesday 9 January, some people met at the MIT Press offices in Cambridge to seed the Paged Media Open Source initiative: a suite of JavaScripts to paginate HTML/CSS in the browser for the purposes of exporting print-ready, or display-friendly, PDF from the browser. This project, launched by Adam Hyde (Coko Foundation, Shuttleworth Fellow), is based on community-led development and I was invited to work on it with Fred Chasen during the next few months. For this first meeting, I made a presentation about different Paged Media approaches and tools that already exist. This is Part 2 of my post in two parts and is a version of that presentation.
In the previous post, I wrote about different paged media approaches. Now, in Part 2, we focus on another method based on the CSS Paged Media Module and the CSS Generated Content for Paged Media Module.
For the purposes of writing this article, I have tested two standalone publishing tools which have implemented the CSS paged media specifications: PDFreactor and Prince. Prince is the most used, PDFreactor is the most promising (because it combines Paged Media and CSS Region).
I have produced a simple demo book based on the open-source J. Rand Capron’ book Auroræ : their characters and spectra (source : Project Gutenberg). You can find the demo file at Paged Media Gitlab. I have also started a table comparing the implementations of the two tools. This is an ongoing work to which the Paged Media community is invited to contribute - it will eventually document the implementations by other tools, step by step. The results of browser testing will also be documented.
C. Complex layouts
I am most interested in looking at ways to express rich layout. The goal isn’t to learn to create a book with CSS Paged Media, as there are lots of examples about doing that already available on the internet. My example of the Auroræ book is one of those. The challenge is to explore the limit of the specifications, how to work with them, and, eventually, to see what needs to be proposed in the future for more complex and multi-level layouts.
For a start, we know that we can’t think a book and a site in the same way. We have seen that paged media, in general, differs from continuous media in that the content of the document is split into one or more discrete static display surfaces. The CSS paged media module proposes specifications to build areas filled with content where the elements come one after another. It’s based on the Document Model Object, a tree-like representation of a document.
Presenting this model of structure as it is with just a few stylisations of the content is not enough to build a book. Elements logically following each other in the DOM may need to be seen side by side on a page because of the following principles of design:
- Elements arranged close to each other are perceived as more related than those placed further apart;
- It may be better to move some content to make layouts more balanced or readable: the way content is displayed creates contrast guiding the users’ eyes in the intended direction;
- It’s important to manage the white space created by unintentional page breaks due to elements being “pushed” to the next page because they cannot be cut.
Traditionally, in print publications with rich layouts, figures are moved to the top or bottom of columns or pages, images can spread across two columns of layout, highlighted quotes are added to catch the eye, the notes are positioned in different ways (not just as footnotes), and so on. In short, elements need to be moved on the page independently of DOM order to meet the presentation requirements. This can be handled at varying scales for books, spreads or pages.
Over the next weeks/months, I will write specific articles on the topics listed below - details and links will gradually be added.
Scale of the book
-
Flow interrupted (by one page or by another flow)
(example : booklet of images/plates or inserts in the middle of a book) -
Parallel flow
(example : on the same page, a flow in English and a flow in French)
Scale of the spread
- Content in margins
- Images across the spread
- Proprieties inside/outside
Scale of the page
-
Block exclusion with absolute position
(example: a highlighted quote or image across two columns) - Images on the top of the page or in the corners of the columns
- Floats in the middle of the text
Positioning of notes
- Margin notes
- Sidenotes
- Notes in multicolumn
This list is the beginning of my work program to explore the features necessary to support more sophisticated layout and identify when CSS specifications alone are adequate. For example, with floats, the content that can be moved out of the current text flows into a different place and new keywords to help refine the control of the float property have recently been proposed. In the same way, I will look with interest at the improved approaches for controlling layout in used in flexbox and grid.
If the CSS specifications are not enough, I will look at experimental implementations or syntax. Indeed, standalone tools already expand several properties with proprietary values or proposed new features. Some interesting features have also been proposed by Bert Bos, who has written a task list of requirements for paginated display with associated proposals to solve several layout problems encountered in print; and Jen Simmons has proposed a new specification for CSS regions in the context of grid.
D. Specific styled & content stuff needed to make a book
Last but not least, there is a whole range of styled and content stuff - specific or not - needed to build a book: generated content, color management, baseline and typographic matters.
Generated contents
Generated contents are elements added to books to help readers navigate between pages: a table of contents, running headers and footers, page numbers, cross-references, an index, and so on. These elements make little sense on the web and don’t exist in HTML content.
CSS Generated Content for Paged Media Module describes the way to render content that does not come from the document tree. It contains :
- named string: copy text for reuse in margin boxes
- running elements: move elements (complete with style and structure) from the document to margin boxes
- target-counter(s): retrieve the value of the innermost counter obtained from the target end of a link
- target-text: retrieve the text value of the element referred to by the URL
Generally, these features are completed with the concept of counter to automatically number elements. They are created and manipulated with the counter-increment
, counter-set
and counter-reset
properties, and used with the counter()
and counters()
functions as defined in the CSS Lists and Counters Module.
This set of features is enough for building:
- Folios → specific counter page
- Table of contents → target-text + target counter
- Numbering of chapters, figures, etc. → counters
- Index → target-text + target-counters
- Cross-references → target text + target counter
- Running headers → named strings or running elements in margin boxes
- Highlighted quotes → named strings
Color management
The purpose of color management is to keep the appearance of colors consistent as they are converted between different technologies. To understand the differences in processes from one technology to another, the concept of color spaces and color profiles are needed.
Screen uses light refracted through combinations of red-green-blue (RGB) additive color to display colors: red, green and blue light are added together to create all the other possible colors.
Printers use combinations of Cyan, Magenta, Yellow, and Black (CMYK) inks added together to create all the other colors.
A color profile defines how the tool should display or print colors inside its own color space. For example, a hobbyist camera will be more likely to display a smaller piece of the RGB space where a high-end professional screen will be able to display a bigger zone of the same space. The only way to be sure that the colors stay as much the same as possible on multiple devices is to embed the definition of the color profile inside the document.
The CMYK on screen is always simulated (even in a tool like InDesign) as perfect equivalence is not possible. However, if we want to be sure of the printed colors, we need RGB to CMYK equivalence when generating a PDF to send to a professional printer, which can be only done using color profiles.
The conversion can be declared on specific elements or for the entire document.
On specific elements
Prince and PDF reactor extend color keywords from CSS Color Module: CMYK colors can be specified using the non-standard function cmyk()
on elements.
For the document
The color profile can be integrated and the colors transformed when generating the PDF output file. For example, in Prince, the output intent color profile is selected using the --pdf-output-intent
command-line option, or using the prince-pdf-output-intent
property inside a @prince-pdf
at-rule
In browsers and their default print boxes, care must be taken because the conversion is not necessarily done when requesting printing or generating the PDF. There is also a problem rendering CMYK images for display in browsers. So it will be necessary to think about what level of the process the color conversion will be done.
Baseline matters
In print, it’s common (and even essential), to align lines of text (with or without different sizes of font) to invisible grids in the document. This greatly improves readability of duplex printing and for documents with multi-column layouts. Lines remain at the same position on every page, thus keeping a vertical rhythm which is very beneficial to the reading experience.
On browsers, snapping the text to a document grid is very difficult for now. The implementation of line-height and font-size into browsers is very different from the way it is handled in software such as InDesign.
The font-size: 12px
and line-height: 12px properties behave differently between fonts. Elements have the same font-size, but fonts produce elements of different heights and so different line-height. This difference comes from the fact that the font size is based on its ascending and descending metrics that vary from font to font. The line-height is calculated using the ascenders and descenders of a character and there is no way in CSS to bind the text to a baseline, as you can do in InDesign.
The problem is that we have no way to identify or control the height of a line with CSS. However, creating a baseline in the browser requires more mathematics and a good amount of trial and error, especially if you want to use different fonts in your document. For sure, it can be solved with JavaScript and I will write a more detailed post about doing that soon.
It’s possible with PDF reactor, with proprietary features added in CSS and without changing the line-height of elements, to automatically create line grids and snap text to these grids.
It works like this :
- a line grid is declared for the document or for the root element on each page with the property :
-ro-line-grid: create`;
- the gap between the lines is declared with the
line-height
on the same element; - the property
-ro-line-snap: baseline;
is added to all elements which we want snapping to grid.
Typographic matters
If we want designers to use HTML and CSS for print publications, we need the same fine control of typography that InDesign provides. Indeed, after discussion with many graphic designers, what slows adoption of HTML and CSS be designers is:
- the difficulty of snapping the text to a document grid (as I described above);
- not being able to manage the flag and the justification and having to finish them by hand;
- more generally, macrotypography and open types features.
Fortunately, the macrotypography and open types features are more or less now working in browsers. The evolution of implementations are good and there is, in addition, a quite broad range of specification on this subject:
- kerning
- ligatures
- subscript and superscript
- small caps
- numerical formatting
- glyphs alternate
The biggest challenge is the management of line breaks with justification and flags.
Hyphenation is managed by the property hyphens
and depends on the language declared in the document or in its elements. In HTML, the language is defined by the lang
attribute and browsers will only apply the rules if this attribute is present and the corresponding dictionary (for hyphen and end of line management) is available.
The hyphenation and line break are automatic. However, we also need to be able to add and delete them manually for management of homogeneous white space throughout a paragraph and for setting ugly flags. This work takes multiple iterations and may be fastidious if we need to generate the PDF each time to check the changes. With a browser, the solution would be to think about an API for correcting/updating page breaks with modification on the fly.
Conclusion: the Paged Media initiative
The two parts of this post are a quick state-of-the-art survey about creating layouts with HTML / CSS. These are basic considerations that we will need to take into account in the development of a suite of JavaScripts to paginate HTML/CSS in the browser.
There are a number of questions we need to ask:
- what is already implemented in browsers ?
- what can we implement ourselves from the CSS paged media specifications?
- what we want to add to the specifications?
- how can we leave room to the user to add more features?
A range of other issues remain to be explored: internationalization, support of mathematical languages, etc. Hopefully, solutions for specific issues will come as users figure out ways to add javascript framework / polyfill to extend what browsers can do.
Our goal is to build tools for paged media rendering rather than a particular product which is more adaptable for various workflows and products. We want to use the advantages of browsers: CSS feature implementations, development tools to explore rendering, modularity and interoperability with other tools… The idea is to generate the PDF once and then edit on the fly in the browser. It may be ambitious but we have hope with a community-first approach to developing. It’s a great adventure we have begun!
Comments