Forum How do I...?

Page breaking after ::before even when using

cayhorstmann
I have the following code to put an icon to the left of a div.Note:

div.Note {
  margin-top: 0.5em;
  margin-bottom: 0.5em;
  padding-left: 4em;
  padding-top: 0.2em;
  padding-bottom: 0.2em;
  orphans: 3;
  widows: 3;
}

div.Note::before {
  content: "📝";
  font-family: "Noto Emoji";
  float: left;
  margin-left: -1.5em;
  font-size: 2.5em;
  break-after: avoid;
}


Unfortunately, a page break can appear between the div.Note::before and the div.Note. How can I avoid that?

This issue is similar to https://www.princexml.com/forum/topic/2239/page-break-between-content-and-content-before?p=1#9841, which recommends to use float. But that's just what I am doing.

I am using Prince 15.1.
cayhorstmann
I also tried position: absolute, like the OP did many years ago. Same effect: Page break between ::before and the element. This is a show stopper for me.
cayhorstmann
I tried instead to use a background image for the note icon, with background-repeat: no-repeat.

That fixes the problem of having a page break between the icon and the note text.

But it raises a new problem. When a long note is broken across pages, the second page again gets a background image. I do not want that. Is there a way of making no-repeat really mean no-repeat?
howcome
Are you able to post a small code example which has a page break in the wrong place?
cayhorstmann
Sure. Here you go.
  1. test.html8.5 kB
  2. test.pdf38.6 kB
howcome
Thanks. By top-aligning the icon with its note, the success rate is higher. Attached.

But we still don't have a tight connection between these two items. Hmm.
  1. test.html8.5 kB

Edited by howcome

cayhorstmann
Thanks, I tried margin-top, and as you point out, it is better. But not perfect. In two volumes of 700+ pages with hundreds of notes each, a higher success rate isn't good enough.
howcome
By setting the icon on the paragraph, rather than the container, it seems less prone to breaking.
  1. test.html8.5 kB
cayhorstmann
I noticed that too. Unfortunately, I need the "Note" text before the first paragraph, and I don't know how to add an icon and text at the same time as ::before. And I can't add the icon as the background image to the first paragraph--it might not be long enough to contain it.
howcome
Given your orphans/widows settings, paragraphs will often move to the next page from where its container is started. So, attaching icons to the container will result in empty icons.

I suggest solving the "Note" text some way; rather than generating a block-level container element, you could generate a inline-level span element at the beginning of a paragraph. The "Note" text could be attached to this element.

Many years ago I proposed chaining pseudo-elements, where you could do:

p::before {  /* add "Note" */ }
p::before::before { /* add icon */ } 


But this never made it into CSS.
cayhorstmann
Thanks, I took out the widows/orphans. Volume I of the book now has no breaks after the icons, just a few notes with unfortunate orphans. Definitely better.

Do you think it is a bug to break after a float in ::before? If so, I'll file a bug report.
howcome
Good you found a solution. Pagination will often be a compromise.

Given the other constraints that have been set, I don't think breaking after the float is a bug.

Personally, I'd probably use sidenotes rather than floats to place the icons.

https://css4.pub/2023/sidenotes/
cayhorstmann
How would the sidenotes work? I don't want to change the HTML.
howcome
Sidenotes are much more flexible than using floats with negative margins, and there's no need to change the HTML. Here's your example using sidenotes:

https://css4.pub/2024/sidenotes/#icons

Edited by howcome

cayhorstmann
That's very interesting, thanks!

Unfortunately, when I tried it, there were instances of page breaks that place the icon on the bottom of one page and the note on the top of the subsequent page.
howcome
Could you post the code?
cayhorstmann
Here you go.
  1. test.html8.5 kB
  2. test.pdf38.6 kB
howcome
Here's a version without containers, it seems quite resilient against page breaks.
  1. test.html11.8 kB
  2. test.pdf44.1 kB

Edited by howcome

cayhorstmann
Ok, but that doesn't do me a lot of good. Notes in the book can contain multiple p, pre, ul, ol.

I think there ought to be a way to avoid breaking a page between a sidenote and the element to which it is attached.
howcome
If you must use containers and want to avoid breaking, try setting "break-inside: avoid;" on the container, rather than on the note.
  1. test.html8.5 kB
cayhorstmann
That's not a viable solution. The container (here div.Note) can be long enough that it must be broken across pages.

Such a break should just not separate the decoration (be it a float, a sidenote, or a background image) from the container body.

Have another look at the sample that I posted as "Here you go" four posts previously. Why is the Note icon present at the bottom of page 2 without any part of the note's content? Perhaps the computation naively thinks that the icon fills the vertical space, so a break must be taken? But why? There is no widow/orphan statement that would have prevented a line or two of the content to be included on page 2. Clearly some of the content fits, and I believe it should appear before the break.