Csswg-drafts: [css3-page] CSS counter for position fixed elements on paged media

Created on 16 Oct 2017  路  16Comments  路  Source: w3c/csswg-drafts

(From Blink issue 774830)

A retired MDN example showed page numbers using

@media print {
  #print-foot {
    display: block;
    position: fixed;
  }

  #print-foot:after {
  content: counter(page);
  counter-increment: page;
  }
}

The behavior differs across browsers:

Firefox:

  • Page: 1
  • Page: 2

Chrome, Edge:

  • Page: 1
  • Page: 1

Safari:

  • Page: 1 (appears only on the 2nd page)

Which behavior is correct? Should the counter-increment occur each time the element is rendered?

css-page-4

Most helpful comment

Counter increment for fixed elements when printing is useful in creating page numbers of page's footer. So

Page: 1
Page: 2

is expected.

All 16 comments

A retired MDN example showed page numbers using

For the record: the example is still present on the current revision. The rev'd URL was used on Chromium issue to make sure the reference doesn't break in the future.

(Thanks for filing BTW)

The Firefox behavior is so buggy. If you create a static element after #print-foot which uses counter(page) and is displayed in the first page, then the second page shows Page: without any number.

I think counter values should lie in the element tree, so #print-foot::after should have a single value for the counter page, which would be 1.

Also see #1026, a proposal to read counters in arbitrary properties. I don't think this can be possible if counter values belong to fragments.

Interesting, so the behavior of Firefox is actually undesired?

How do I move this forward? Should I just submit a pull request to the spec draft?

Any updates?

Counter increment for fixed elements when printing is useful in creating page numbers of page's footer. So

Page: 1
Page: 2

is expected.

Any updates/plans for fixing this issue?

Per the current spec https://drafts.csswg.org/css-lists/#creating-counters counter values should percolate thru the element tree, same as other styles; it just has a funky "inherit from preceding element in the document" instead of the normal inheritance from its parent element.

That said, I know that Blink, at least, actually inherits thru the box tree and attempts to emulate inheriting thru the element tree (which results in some bugs, and also some bad perf stuff).

To get a page counter, the intention is that you do a counter-reset/increment in @page, then counter() will pick up the correct value based on what page it ends up on. (And presumably will change values in fixpos appearing on multiple pages? This isn't well-defined.)

I can comment on the Firefox behavior, and I can confirm that it's just an accident of how fixed-pos replication during printing is implemented. I'd consider it a bug.

@tabatkins ,

@page
{
    counter-increment: page;
}

Does not work, even in firefox. Was that what you were talking about?

(I'm deleting useless "ping" comments. Please do not ping without new information; we'll get to the issue when we get to it, otherwise.)

@page {
  counter-increment: page;
  @bottom-center {
    content: counter(page);
  }
}

This works in all paged-media focused engines. If it's not working then that's an issue with the implementation, not the spec.

It's already been pointed out that counter values must be derived from the element tree, I just wanted to add that this approach underlies the target-counter() function - target-counter("print-foot", page) must evaluate to a single value. So trying to create page number footers with a position: fixed element should not be considered a valid approach.

I made an edit on MDN to explain the snippet. @page margin boxes are not implemented in any major browser engine yet, neither did target-counter().counter-increment: inside a @page does not increment the counter printed on position-fixed elements.

Getting back to OP's post, I just solved this little quirk while working on another project. Chrome refused to increment the counter until I called the counter reset. Once I did that, whole thing started working.

body {
    counter-reset: page;
}
footer {
    counter-increment: page;
}
#footer-content {
    content: counter(page);
}

@BattlemageBob, for me, firefox shows the total page counting at first page and nothing else at others. At chrome, always 1 at every page.

body
{
    counter-reset: page;
}

footer
{
    counter-increment: page;
    position: fixed;
}

footer::before
{
    content: counter(page);
}

@darakeon try changing where you're defining the counter increment to

@page {
counter-increment: page;
}

You will get wildly different results based on where you declare that. Hope that helps.

@page {
    counter-increment: page;
}

body {
    counter-reset: page;
}

.pagination {
    position: fixed;
    top: 0;
}

.pagination::before {
    content: counter(page);
}

Firefox: prints zero at first page, nothing on the others
Chrome: prints zero at all pages

Was this page helpful?
0 / 5 - 0 ratings