Forum How do I...?

make elements the same height as paged media with javascript? (aka 'covers')

mrwarper
As many here will know, 'Covers' are a classic in CSS fora -- and I have a method that I'd like to improve upon. I think this should be possible to do with Prince, but I'm afraid I'm not familiar enough with it yet.

The idea is to have elements (typically images) of an appropriate class ('cover', 'fullpage', you get the idea) in single pages (trivial CSS: " * + .cover { page-break-before: always; } .cover { page-break-after: always; } ") and then have each element take up as much space as possible on its page -- hence the usual term 'cover'.

If the image is wider than the page, styling it with 'width:100%; height: auto;' will suffice, and at high enough resolutions this will work and look good regardless of media size, just leaving some blank space above and/or below the image. Unfortunately, things are not as easy with 'narrow' images.

As per the CSS specifications (I can't remember where I read that exactly to provide a link, but I'm pretty sure this is how it works -- please feel free to correct me), direct descendants of the <body> element must be given an explicit height, and any percentage values will be interpreted as relative to the parent's WIDTH since, unlike the paged media, the <body> has no defined height by default. So 'cover {height: 100%; }', simple as I think this should be, won't get you anywhere.

Since I always 'print' to one of a few page sizes, as many media queries at the top of the CSS save my day with variations of "@media (min-height: 19cm) and (max-height: 19cm) { .cover { height: 19cm } }" where necessary.

But this 100% effective solution solution doesn't merely lack elegance, it is also clumsy -- should I decide to print on different media sizes, I'd be forced to add a new media height to the CSS every single time. While we wait for CSS specs to evolve into something that allows an easier solution or workaround for this problem, I think Prince javascript-in-CSS might solve it here and now.

I am thinking something similar to the CSS+js pseudocode 'cover { height: media.height(); }' would work for ALL media sizes without modifying a single line anywhere. Then it would be combined with the easy method above for wide covers and we could have a solution both simple and universal to the cover question. We would just need something along the lines of

.cover {
@media (max-aspect-ratio: width()/height() ) { width: 100%; height: auto; }
@media (min-aspect-ratio: width()/height() ) { height: media.height(); width: auto; }
}

in our print CSS if only the image (element) initial dimensions and media height could be queried and later used in javascript.

I haven't had a lot of time to discover a way to do it yet, or even find out whether it's possible at all, so I thought I would ask here.

Your thoughts?
hallvord
Hi,
a while ago, I was experimenting with some similar questions regarding "cover" pages - I ended up with some slightly convoluted CSS for sure, but didn't need JS. Perhaps you will be able to re-use some of this approach?

https://github.com/yeslogic/miscellaneous-testcases/commit/8e7f7631bb451855f4f6ed04b78a43e542138c1d

In general: keep in mind that position:fixed will place things according to the viewport (in this case: the page!) and percentages and stuff will now also use page dimensions.

Announcement: repos for tests/utils

Edited by hallvord

mrwarper
Hi,

thank you, but I don't need javascript -- it would just be handy to make my documents print 'responsively' -- i.e. currently I need one CSS set of rules following the pattern "@media (min-height: 19cm) and (max-height: 19cm) { .cover { height: 19cm } }" per each media size I need to print on. With the simple javascript API I would like to have available, all media sizes would be covered in one go with the code I wrote above, thus avoiding the need to edit any files.

On a different note, anything positioned with 'fixed' in printed media will appear at the same location on every single page. The other day I used that for a CV, but it's quite rare to need it.

Regarding your code, I actually use a variant of it in other places. The only important difference is you use a background image, which is fine for those semantically unimportant, whereas I feel a cover image should be part of the HTML. However there's still no way to make 'height: 100%' work for either type of image unless you set an explicit height for the HTML element they are attached to/contained in.

Below you can see an example of simple markup and CSS demonstrating both of them in action at the same time: the book cover is considered an integral part of the document and thus is an HTML element, the metadata decoration is just that -- so it exists in the CSS only, and nowhere else.
img_height.png
  1. img_height HTML.htm0.9 kB
    An old SF novel -- Simple HTML
  2. img_height common.css0.2 kB
  3. img_height print.css0.2 kB
  4. img_height.png115.1 kB