Re: [gcpm] custom pages and page lists

Håkon Wium Lie <howcome@opera.com> wrote on 2008/08/19 12:13:41
> This message is a writup of the possible solutions to a problem we
> have disussed for a while. In its simplest form, the issue is: how do
> we set different headers/footers on the first page and subsequent
> pages in a chapter? For example, given this markup:
> 
>   <div class="chapter">
>     <h1>The beginning</h1>
>     ....
>   </div>
> 
>   <div class="chapter">
>     <h1>The end</h1>
>     ....
>   </div>
> 
> How does one make the first page of each chapter have no headers,
> while the remaining pages have the chapter title as header? This is
> called use case 1 (UC1)
> 
> Another common use case is how to achieve the same formatting without
> having 'div' elements to rely on:
> 
>   <h1>The beginning</h1>
>     ....
>   <h1>The end</h1>
>     ....
> 
> This is called use case 2 (UC2)
> 
> Finally, we need to make sure that the 'page' property can continue to
> support one of the use cases in CSS2, namely to put an element on a
> separate page with a page break before and after:
> 
>   @page rotated {size: landscape}
>   table { page: rotated }
> 
> This is called use case 3 (UC3)
> 

CSS2 and CSS3 Paged Media have the following example where the two
tables with page: rotated are rendered on the same page if they fit.
Is this use case not very important?

    In this example, the two tables are rendered on landscape pages
    (indeed, on the same page, if they fit). The page type "narrow"
    is used for the <p> after the second table, as the page
    properties for the table element are no longer in effect:

    @page narrow { size: 9cm 18cm }
    @page rotated { size: landscape }
    div { page: narrow }
    table { page: rotated }

    with this document:

    <div>
    <table>...</table>
    <table>...</table>
    <p>This text is rendered on a 'narrow' page</p>
    </div>

I'd like to call this use case 3.1 (UC3.1) in the follwing comments.


> In this message, I will sketch several solutions and evaluate them
> wrt. the three use cases above.
> 
> ------------------------------------------------
> OPTION A
> 
> The latest Editor's copy of the GCPM draft contains a simple solution
> using named strings:
> 
>   http://www.w3.org/Style/Group/css3-src/css3-gcpm/Overview.html#named
> 
> 
> UC1:
> 
>   @page { @top-center { content: string(title, first-except) }}
>   h1 { string-set: title content(); page-break: before }
> 
> That is, the keyword "first-except" specifies that the header should
> not appear on the first page.
> 
> UC2:
> 
>   @page { @top-center { content: string(title, first-except) }}
>   h1 { string-set: title content(); page-break: before }
> 
> The code is the same as UC1, the 'div' element is simply not used.
> 
> UC3:
> 
> There is no change in the 'page' property so the same code can be
> used:
> 
>   @page rotated {size: landscape}
>   table { page: rotated }
> 
> Option A, however is quite simple and does not allow the first
> page to have (say) different margins from the subsequent pages. 
> 

UC3.1:
No change.

> 
> ------------------------------------------------
> OPTION B
> 
> Page Groups is also described in the (alas, unreleased) GCPM draft:
> 
>   http://dev.w3.org/csswg/css3-gcpm/Overview.html#page-groups
> 
> UC1:
> 
>   @page chapter { 
>     @top-center { content: string(title) }
>   }
>   @page chapter:first { 
>     @top-center { content: none }
>   }
>   div.chapter { page: chapter; page-group: start }
>   h1 { string-set: title content() }
> 
> This solution is based on using the 'page' property as well as a new
> 'page-group' property. The 'page' property remains inherited. A page
> break is generated before every 'start' page.
> 
> UC2:
> 
> Not possible -- this code would, e.g., result in h1 elements
> being alone on a page:
> 
>   @page chapter { 
>     @top-center { content: string(title) }
>   }
>   @page chapter:first { 
>     @top-center { content: none }
>   }
>   div.chapter {  }
>   h1 { page: chapter; page-group: start; string-set: title content() }
> 
> 
> UC3:
> 
> No change, this code would still work:
> 
>   @page rotated { size: landscape }
>   table { page: rotated }
> 

UC3.1:
No change.

> 
> ------------------------------------------------
> OPTION C
> 
> Named page lists:
> 
>   http://dev.w3.org/csswg/css3-gcpm/Overview.html#named2
> 
> Further, option C makes some assumptions:
> 
>  - the 'page' property no longer inherits
> 
>  - every element with a non-auto value on 'page' start on a new page,
>    so there would e.g. be a page break between these two div elements:
> 
>      div.chapter { page: chapter }
>      <div class="chapter">...</div>
>      <div class="chapter">...</div>
> 
>   - if 'page' has more than one value, it will not generate any page
>     breaks between/after the pages in the list.
> 
> 
> UC1:
> 
>   @page chapter { 
>     @top-center { content: string(title) }
>   }
>   @page chapter-start { 
>     @top-center { content: none }
>   }
>   div.chapter { page: chapter-start chapter }
>   h1 { string-set: title content() }
> 
> UC2:
> 
>   @page chapter { 
>     @top-center { content: string(title) }
>   }
>   @page chapter-start { 
>     @top-center { content: none }
>   }
>   h1 { page: chapter-start chapter; string-set: title content() }
> 
> 
> UC3:
> 
> No change, this code would still work:
> 
>   @page rotated { size: landscape }
>   table { page: rotated }
> 

UC3.1:
Not possible.

    table { page: rotated }
    <table>...</table>
    <table>...</table>

These two tables are rendered on separate pages.
To prevent page break between two tables, two same page names can be
specified,

    table { page: rotated rotated }

but it also prevent page break after the tables.

> 
> ------------------------------------------------
> OPTION D
> 
> If the inheritance of 'page' is changed, another option opens up. 
> 
> UC1:
> 
>   @page chapter { 
>     @top-center { content: string(title) }
>   }
>   @page chapter:first { 
>     @top-center { content: none }
>   }
>   div.chapter { page: chapter }
>   h1 { string-set: title content() }
> 
> That is, the ':first' pseudo-class can be applied to any named page --
> not just the first page of the document.
> 
> 
> UC2:
> 
> No, this doesn't work as 'h1' would be on a page by itself:
> 
>   @page chapter { 
>     @top-center { content: string(title) }
>   }
>   @page chapter:first { 
>     @top-center { content: none }
>   }
>   h1 { page: chapter; string-set: title content() }
> 
> 
> UC3:
> 
> No change, this code would still work:
> 
>   @page rotated { size: landscape }
>   table { page: rotated }
> 

UC3.1:
Not possible.

    table { page: rotated }
    <table>...</table>
    <table>...</table>

These two tables are rendered on separate pages.

> 
> ------------------------------------------------
> OPTION E
> 
> Bert has sketched another solution:
> 
>   http://lists.w3.org/Archives/Public/www-style/2008Jul/0425.html
> 
> UC1:
> 
>   @page chapter-start { 
>     next-page: chapter;
>     @top-center { content: string(title) }
>   }
>   @page chapter { 
>     next-page: chapter;
>     @top-center { content: none }
>   }
>   div.chapter { page-break-before: chapter-start }
>   h1 { string-set: title content() }
> 
> UC2:
> 
>   @page chapter-start { 
>     next-page: chapter;
>     @top-center { content: string(title) }
>   }
>   @page chapter { 
>     next-page: chapter;
>     @top-center { content: none }
>   }
>   h1 { page-break-before: chapter-start; string-set: title content() }
> 
> 
> UC3:
> 
> Unclear, as there is no 'page' property.
> 
> This proposal avoids using any new properties one the element, but
> relies on a new 'next-page' property in the page context. (Also,
> there's a new 'page-side' property to replace :left and :right).
> 

UC3.1:
Not possible.

> ------------------------------------------------
> 
> Here are my personal favorites:
> 
> I like the syntax of Option D the best (as it requires no new syntax),
> however UC2 doesn't work.
> 
> Option A is a simple solution that works with all use cases, but it
> has limited functionality.
> 
> Option C, including the stated assumptions, addresses all use cases in
> a familiar syntax.
> 
> In sum, I'd probably argue to keep Option A along with Option C.
> 
> -h&kon
>               Håkon Wium Lie                          CTO °þe®ª
> howcome@opera.com                  http://people.opera.com/howcome


I would like Option D with named page list.

UC1: same as Option D.
     Option C's code works too.

UC2:
  @page { 
    @top-center { content: string(title) }
  }
  @page chapter-start { 
    @top-center { content: none }
  }
  h1 { page: chapter-start auto; string-set: title content() }

This example is similar to the GCPM WD's example.
http://www.w3.org/TR/2007/WD-css3-gcpm-20070504/#named3
This spec says:
    The last value in the list becomes the leaving value which is
    compared with the first item the 'page' property of the next
    element. If those two values are different, a page break is
    generated.

The following assumptions are needed.
 - the 'page' property no longer inherits

 - every element with a non-auto value on 'page' start on a new page,
   so there would e.g. be a page break between these two div elements:

     div.capter { page: chapter }
     <div class="chapter">...</div>
     <div class="chapter">...</div>

  - if 'page' has more than one value, it will not generate any page
    breaks between the pages in the list.

These are same as OPTION C's assumptions except "between" 
(not "between/after") in the last.


UC3: same as Option D.

UC3.1:
    table { page: rotated }
    <table>...</table>
    <table>...</table>

These two tables are rendered on separate pages.
To prevent page break between two tables, two same page names can be
specified,

    table { page: rotated rotated }

It doesn't prevent page break after the table and works well.


Best regards,

-- 
Shinyu Murakami
http://www.antennahouse.com
http://www.antenna.co.jp/AHF/

Received on Tuesday, 19 August 2008 10:54:52 UTC