Skip to content

Instantly share code, notes, and snippets.

@JayPanoz
Last active September 7, 2018 15:45
Show Gist options
  • Save JayPanoz/812c25dc01e0745c6f5d56ecb964f721 to your computer and use it in GitHub Desktop.
Save JayPanoz/812c25dc01e0745c6f5d56ecb964f721 to your computer and use it in GitHub Desktop.
Experimental CSS to get portrait-aspect-ratio image + caption on same page, on reflow
/* Current nugget */
/* This in your fallback CSS (for ePub 2) */
.portrait-caption {
height: 99%; /* must check if necessary */
margin: 1.5em 0;
page-break-before: auto;
}
.portrait-caption > img {
width: auto;
max-width: 100%;
height: 80%;
}
/* The following in another CSS (EPUB 3) */
/* EPUB 3 FALL-FALL-FALLBACK */
.portrait-caption {
background-color: yellow; /* I'm using bg-color to check which styles are applied in RS */
}
.portrait-caption > img {
height: 80vh;
max-height: 800px; /* Must check CSS specs — how max-height is supposed to behave when vh/calc on height */
object-fit: contain; /* to keep aspect-ratio of image. Thanks iBooks’ default CSS for that */
}
/* Feature query using @supports = progressive enhancement */
@supports (page-break-before: always) and (height: calc(99vh - 5em)) {
.portrait-caption {
min-height: 100vh; /* fallback for the following line if anything goes wrong */
min-height: calc(100vh - 0px); /* = 100vh but we make sure it is recomputed when doc is updated */
width: 100%; /* is probably useless */
background-color: LightGreen;
page-break-before: always; /* So… ADE doesn't support that though it says it does */
-webkit-column-break-inside: avoid; /* making ADE behaves */
display: block;
margin: 0; /* image in flow, it is not in its own xhtml file. That's the magic. */
}
.portrait-caption > img {
box-sizing: border-box; /* because padding */
max-width: 100%;
min-height: 60vh; /* So that it doesn't become ridiculously tiny when huge font-size is set */
height: -webkit-calc(98vh - 5em);
height: calc(98vh - 5em); /* 98vh - caption’s height || Fallback is 80vh */
object-fit: contain; /* to keep aspect-ratio of image. Thanks iBooks’ default CSS for that */
padding: 1vh 0; /* if for some reason it breaks inside, we make sure we got a padding at top of image, bottom for caption */
margin: 0 auto; /* centering */
}
}
/* For Readium scroll as the viewport is unreliable.
1. min-height depends on your documents’ sizes. Using `em`
makes sure it is recomputed when font-size is changed.
Maybe we could find something else?
2. FYI, if you just got an image in a xhtml file,
Readium’s default viewport in scroll is 300 x 150px
so your 100vh-height image will be 150px. */
@media screen and (min-height: 150em) {
.portrait-caption {
display: block;
margin: 1.5em 0;
min-height: 0; /* reset */
height: auto; /* reset */
background-color: red;
}
.portrait-caption > img {
min-height: 300px; /* reset */
height: auto; /* reset as we rely on max-width */
max-height: 100%;
max-width: 100%; /* Pic will scale based on its width */
padding: 0;
}
}
@JayPanoz
Copy link
Author

JayPanoz commented May 20, 2016

Brace yourself, here comes “THE EPIC UPDATE”

tl;dr: I did it. Who’s your daddy now?

The ePub 2 Fallback

Should be in one CSS.

.portrait-caption {
  height: 99%;                /* must check if necessary */
  margin: 1.5em 0; 
  page-break-before: auto;
}
.portrait-caption > img {
  height: 80%;
}

The Golden Nugget

Should be in another CSS.

Here you go, use and abuse it, test it everywhere and report issues. Test, iterate, improve, enhance, media-querite and have fun.

/* EPUB 3 FALL-FALL-FALLBACK */

.portrait-caption {
  background-color: yellow;  /* I'm using bg-color to check which styles are applied in RS */
}
.portrait-caption > img {
  height: 80vh;
  max-height: 800px;  /* Must check CSS specs because it is useless at the moment*/
  object-fit: contain;    /* to keep aspect-ratio of image. Thanks iBooks’ default CSS for that */
}

/* Support query = progressive enhancement */

@supports (page-break-before: always) and (height: calc(99vh - 5em)) {
  .portrait-caption {
    min-height: calc(100vh - 0px);  /* = 100vh but we make sure it is recomputed when doc is updated */
    width: 100%;  /* is probably useless */
    background-color: LightGreen;
    page-break-before: always;  /* So… ADE doesn't support that though it says it does */
    -webkit-column-break-inside: avoid;  /* making ADE behaves */
    display: block;
    margin: 0;  /* image in flow, it is not in its own xhtml file. That's the magic. */
  }
  .portrait-caption > img {
    box-sizing: border-box;  /* because padding */
    max-width: 100%;
    min-height: 60vh;  /* So that it doesn't become ridiculously tiny when huge font-size is set */
    height: -webkit-calc(98vh - 5em); 
    height: calc(98vh - 5em);  /* 98vh - caption’s height  */
    object-fit: contain;  /* to keep aspect-ratio of image. Thanks iBooks’ default CSS for that */
    padding: 1vh 0;  /* if for some reason it breaks inside, we make sure we got a padding at top of image, bottom for caption */
    margin: 0 auto;  /* centering */
  }
}

/* For Readium scroll as the viewport is unreliable */

@media screen and (min-height: 150em) {
  .portrait-caption {
    display: block;
    margin: 1.5em 0;
    min-height: 0;   /* reset */
    height: auto;  /* reset */
    background-color: red;
  }
  .portrait-caption > img {
    min-height: 300px;   /* reset */
    height: auto;  /* reset as we rely on max-width */
    max-height: 100%;
    max-width: 100%;  /* Pic will scale based on its width*/
    padding: 0;
  } 
}

Checked on:

  • iBooks (iOS + OS X, all modes)
  • Readium (Chrome extension — all modes)
  • Google Play Books (will default to fallback)
  • Modern RMSDK (ADE 4.5 OS X + iOS)
  • Legacy RMSDK
  • Kobo iOS (it seems they override img styles so maybe try a class or an id?)

The process

It's epic, much more epic that “Emojyles” actually → https://twitter.com/JiminyPan/status/730756695106916352

  1. I somehow started with display: table as there is a nasty trick for legacy RMSDK: using display: row and display: cell instead of display: table-row and display: table-cell—yes, it is that bad. Problem is you must then use min-height for img, which limits what you can do.
  2. I tried flexbox but well, it doesn’t even work very well in iBooks (last line of caption doesn’t behave well at reflow) so it’s a dead end at the moment.
  3. I discovered display: table was actually the problem in “modern RMSDK” so I dropped it—and yeah I wondered why I’ve been using it in the first place.
  4. I was somewhat reminded of object-fit: contain; so I wanted to test it.
  5. Being absolutely pissed by ADE 4.5 (see here) I tried adding page-break-before in the support query.
  6. Dat arsehole (ADE 4.5) told me it supports page-break-before while it clearly doesn’t (see there).
  7. Then I remembered the -webkit-column-break-whatever properties, which aren’t standard at all but oh yeah, it looks like ADE 4.5 is using that. See https://developer.mozilla.org/en-US/docs/Web/CSS/break-inside for more info (note at the end, especially) so I don't know, maybe ADE 4.5 is a fucking liar and claims it supports page-break-before while it supports -webkit-column-break-before. But anyway… I flipped so much tables that I don't have another one left to flip.
  8. And then using -webkit-column-break-inside: avoid, it fucking worked in ADE 4.5. See there.
  9. I concluded that my stupidity at persevering helped me achieve this. It is sad but awesome at the same time.

It’s up to you now. TEST DAT BITCHY NUGGET and make reflowable books great again!

@JayPanoz
Copy link
Author

JayPanoz commented May 23, 2016

Further details + notes

height, max-height and min-height

As a reminder:

min-height > max-height > height

So you can set a max-height if there is no min-height (fallbacks) but you’ll have to !important it for some reason (I guess because vh?).

I can’t get the “reflow image please” part to behave with max-height, even when setting a min-height smaller than the max-height (in px). So maybe height: calc() is the culprit. I really don't know, found absolutely nothing about that.

Edit: Or maybe it is once again those fucking RS overrides since it it working as intended in web browsers.

So the workaround is to make sure your pictures are freaking huge enough so that you don’t need max-height.

iBooks

iBooks won’t take your max-height into account, at all. I guess there is a bug when vh are used. Though the inspector shows iBooks’ default max-height: 95% is overridden by your own max-height, applied styles show max-height: 95% is being used… which means:

min-height > iBooks’ max-height > max-height > height

Edit: Or maybe it is twice again those fucking RS overrides + an iBooks bug on top of it, dropping the max-height when height in vh or calc() since it it working as intended in web browsers.

So the workaround is to make sure your pictures are freaking huge enough so that you don’t need `max-height.

Constrain caption’s font-size

There’s one trick if you want to constrain the caption’s font-size on iOS: -webkit-text-size-adjust: [x * 100]% . Used it in the past and It works at least in iBooks but I didn't check for this nugget so please correct me if I'm wrong.

@tooolbox
Copy link

tooolbox commented Oct 9, 2016

I applaud you, sir, even if all of this hoop-jumping makes me want to cry.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment