Forum How do I...?

How to float an image/div on the page on which it should be anchored by default?

melusina
Given the HTML fragment in content.html‎, with default styling
css.png
for div.figure > img

causes the image to break to the next page, since the available space is not sufficient:
no_float.png


Thus, I used
div.figure {
    float: top;
}

in order to float it to the top of the page. I expected, that the image, instead of being broken down to the second page, would float to the top of the first page. The result, however, is that it floats to the top of the second page (see second screenshot below). This is not helpful because it often de-associates the text that is about the image from the image, neither is it the intuitive behaviour of using float I think. Taking something out of the flow, for me would mean that the available space on the page on which the image is anchored is not relevant anylonger for the decision to break the floated element to the next page. Instead we would see the other elements that are not floated moving further down.

Have I done anything wrong with the CSS or is there any way to achieve the behaviour that I would like to achieve?

float_top.png

  1. content.html4.7 kB
  2. css.png10.3 kB
  3. float_top.png121.8 kB
  4. no_float.png89.6 kB
howcome
Your code looks correct.

Prince will -- unless told otherwise by the defer-* properties -- try keep the page float on the same page as it's anchored. But there are situations where that's not possible, e.g. when the anchoring point naturally appears towards the bottom of the page.

Could you post a complete html file, with the css and image, so that I can analyze your case in more detail?

Here's a guide to using page and column floats, including the defer-* properties:

https://css4.pub/2022/float/

Edited by howcome

melusina
Unfortunately, I can not use defer-* and other more comprehensive float properties, because we still use princexml 12.5.

I understand, that there are some edge cases, but this situation actually happens in all cases in which we apply floats to figure divs in our publications, so the reason must be something different.

Thank you so much for looking into it. I zipped the project: pdf.zip‎

you'll find the output in the root folder 'pdf/' and all the files that we use to generate the pdf in 'pdf/_tmp/'. The pdf is put together out of several html files and css files. Sorry for the complicated structure. The sequence of which css files are processed is:

<link href="melusina.css" rel="stylesheet" type="text/css" />
<link href="publication.css" rel="stylesheet" type="text/css" />
<link href="melusina_pdf.css" rel="stylesheet" type="text/css" />
<link href="series_pdf.css" rel="stylesheet" type="text/css" />
<link href="publication_pdf.css" rel="stylesheet" type="text/css" />

The publication is one of our test publications and not a real world example. But as I mentioned, the problem appears always when we apply floats to the figures.
  1. pdf.zip399.7 kB

Edited by melusina

howcome
Thanks for sharing code. It seems that Prince follows this pseudo-algorithm for placing page floats:
if ((natural_anchoring_point + height_of_figure) > page_area_height) then 
   move figure to next page
else
   keep figure on same page

In your example, all three anchoring points naturally appears too low on the page to fit the figure; if the figures had been floated to the top of their natural page, the anchoring points would have been pushed to the next page. If so, the figure would have appeared one page before its anchoring point, which is probably not what you want.

In the attached PDF file, I've removed some text (to move the second/third anchoring points upwards) and marked all three anchoring points with a red x.

The first anchoring point (on page 9) appears low on the page, so the figure is moved to page 10. (I'm using PDF page numbers, not the printed page numbers)

The next anchoring point is on page 13 where the figure fits and is floated to the top of the same page. Likewise on page 15.

So, Prince will use the same page, if possible.
  1. publication.css0.2 kB
  2. ref_02_melusina_anthology.html46.1 kB
  3. ref_02_melusina_anthology.pdf78.1 kB

Edited by howcome

melusina
Dear @howcome, thanks so much for testing and explaining this for me. In principle that logic was what I feared it would be. I am saying this because the behaviour that we aspire for is the one that you mention we probably do not want (maybe there are some good reasons why we shouldn't want it, I am not aware about?).

We do not have problems with images appearing in the middle of the text instead of at the bottom or top in general. The situations in which we wanted to make use of the float are precisely thos situations in which there is not enough space for the image to appear at the bottom of the page.

The reason for this is that we often have publications with multiple images after another with not much text in between. Thus, the float behaviour in its current form leads to more dissociation between text and image (img a does not fit on page 1 and is at top of of page 2, img b that is just 3-4 lines after img a in the natural textflow can not be floated to already occoupied position on page 2 and floated to the top of page 3 and so on. At the same time all the text from after the 2 images moves from after the images to before the images (due to the float). A second reason is that in our experience writers tend to first write about the image and then show the image. Thus, indeed positioning the image " one page before its anchoring point" as you said often appears as the "more natural" position in the narrative flow.

I suspect that the defer-* property you mentioned at the beginning can achieve such things. Do you know of a way to do this in prince 12.5? ( we will migrate in the future to the newest prince version, but it is not clear yet when this will happen). The aspired logic would go like this:

if ((natural_anchoring_point + height_of_figure) > page_area_height) then 
   apply float:top
   do not move figure to next page
else
   keep everything as it is
howcome
Thanks for a good explanation of what you would like to happen. However, Prince will not place a page float on an earlier page than its anchor, so there is no way to achieve your design using CSS with Prince. This is also true for Prince 15

(Presumably, one could add negative values to 'defer-page', but that could easily cause havoc. Or, one could possibly add a magic keyword to 'float-policy', but I don't see that happening either.)

There are, however, several ways to achieve your design.

First, you can move the figure/image element to a point earlier in the source.

Or, you can put all images at the beginning of the document (or chapter/section) and defer the page. With this method you will have exact control over which page the figure ends up on. You will need Prince 14/15 for this, there's a guide here:

https://css4.pub/2022/float/#deferring-to-a-page




Edited by howcome

melusina
ok, thanks for outlining possible options!