Forum How do I...?

Change margin box content based on starting page number

johnstephens
I currently use the following directives to alternate the positioning of my page numbers on left and right pages.

@page :left {
  @bottom-left {
    content: counter(page);
  }
}
@page :right {
  @bottom-right {
    content: counter(page);
  }
}


After generating sample PDFs of each article, the managing editor creates a custom CSS file to offset the page numbering appropriately. For example:

body { counter-reset: page 422; }


The article-specific CSS is linked in the XHTL as follows:

<link rel="stylesheet" type="text/css" media="print" href="path/to/main.css" />
<link rel="stylesheet" type="text/css" media="print" href="path/to/article-specific.css" />


What we want is to have the page numbers always show on the right for odd-numbered pages, and always on the left for even-numbered pages—but because the page counter could be reset to any number, we're getting the page numbers positioned on "right" and "left" pages relative to first page of each article, instead of relative to the even or odd page number.

Is there a way to fix this with logic in the main CSS file and/or in my XHTML template? I don't want to add logic to the article-specific CSS, because that would be a burden to my editors.

Thank you!
mikeday
I think at the moment this will require an additional CSS rule, eg.
:root { page-break-before: left }

or:
:root { page-break-before: right }

And you choose one or the other as appropriate. Perhaps you could do this with JavaScript, if the starting page number was specified as an attribute somewhere?
johnstephens
Thank you, Mike!

Somehow I missed your reply and then got waylaid by another project. But now that I'm testing this suggestion, I've run into some complications.

My document format requires header and footer content that alternates from page to page. Crucially, I have a distinctive margin header for the first page (@page :first { @top-left {) that overrides the @top-left content on :left and :right pages.

When I add ":root { page-break-before: left }" to my stylesheet, my first-page header appears on a blank page prepended to the document, instead of on the first content page.

I'm aware that I can create named pages using this pattern:

#firstpage_here {

  page: firstpage;
}

@page firstpage {
…
}


I tried associating my first-page styles with a named page called "firstpage", but then I always get a page-break after the page-defining element. I even tested adding "page-break-after: avoid" to both the "#firstpage_here" and the "@page firstpage" selectors, but that had no effect.

I'm not sure what steps I can take to troubleshoot this.

Provided I could get the first-page document on the first content page of my document (Step 1), I would also want to suppress the leading blank page somehow. Is there a command-line flag that might help here?

I have enclosed a a simple, self-contained test document using a stripped-down stylesheet if that helps.

Thank you again!
  1. paginationSample.html60.8 kB
hallvord
Hi,
seem this would be easy if Prince supported
@page :nth(odd) { ... }
@page :nth(even) { ... }

selectors. I have tested and it doesn't work at the moment. I find no other selectors that apply to @page but are based on the *actual* value of a reset page number, unfortunately.

(This is assuming odd and even selectors could be based on the reset page counter, not the physical one. Stuff like :nth(3) is probably spec'ed to depend on the physical page number though - perhaps it should be consistent? IMHO :nth(3) should match the page described as 3rd by a reset counter..but I'm not sure if CSS experts would agree..)

Announcement: repos for tests/utils

Edited by hallvord

hallvord
Another interesting approach might be supporting
@page :not(blank):first {

- a selector for targeting the first non-blank page in a document.. This is currently not supported either, but I think adding it would be quite conformant with the current CSS spec.

Announcement: repos for tests/utils

Edited by hallvord

hallvord
Seems the CSS WG has already considered this question - I found this text in the CSS3 draft about page selectors:

In documents with a left-to-right page progression the first page of the document is a right page, and vice versa. To explicitly force a document to begin printing on a left or right page, authors can specify a break-before value that that propagates a page break to the root. [CSS3-BREAK] The UA must suppress the first (empty) page(s) in this case (and the :first pseudo-class matches the first printed page).


So if Prince catches up with CSS3 (although it is just a draft..) this might just work :)

Announcement: repos for tests/utils

mikeday
Prince supports @page:left and @page:right, and yes you can control whether the first page of a document is a left page or a right page by placing "page-break-before: left" or right on the root element. :)
hallvord
But Mike - if I interpret this correctly Prince doesn't implement the behaviour described in this sentence:
The UA must suppress the first (empty) page(s) in this case (and the :first pseudo-class matches the first printed page).

I'm not entirely sure I understand this though :) But it sounds like :first is not meant to match a generated blank page. If Prince changed that it would seem to solve John's problem.

Announcement: repos for tests/utils

mikeday
Prince should not leave an entirely empty page at the start of the document, and I can't reproduce the problem with Prince 11.
johnstephens
Thank you, Mike! I was using Prince 10, and upgrading to Prince 11 resolved the problem.