Sunday, January 15, 2012

Media Queries for formatting Poetry on Kindle and EPUB

What a tangled web we weave! Amazon wants to maintain support for its legacy ereaders, we all want to support different size ereaders, but nobody supports the code the same way. What to do? One solution is to use media queries, something I've been meaning to explain for months.

A media query lets you create multiple sets of CSS (just what you want to do, right?) and then apply the most appropriate set automatically according to the ereader the ebook is opened in. So, in a single ebook file, there would be various choices of CSS, perhaps one best suited for old legacy Kindles, another for KF8, another for really small screens like iPhones, and yet another for the full-color 9.7” iPad. The ebook would adapt to its environment, giving each user the best possible experience.

That's the theory anyway.

Of course, there are a couple of caveats. Media queries only affect CSS, not HTML, which limits to some degree what can be changed for those ereaders that don't understand a lot of CSS (yes, I'm talking about clunky old mobi). And not all devices of the same screen size support CSS the same way. Ebook designers, like web designers before them, will continue to make multiple versions of the same ebook until the code is standardized. (And don't expect ebook reader manufacturers to adhere to standards without a lot of prodding.)

But media queries do help. Let's see how they work.

Suppose you want to format poetry in your ebook. Poetry is tricky because each line's length must somehow be respected, even in a screen where the line does not fit. The typical solution is to divide each line of poetry into multiple lines, with the 2nd and subsequent lines indented below the first. No matter how narrow the ereader screen, the reader will still be able to identify each line of poetry as a unit.

Let's look at Whitman's O Captain! My Captain! on the Kindle App in a landscape-oriented iPad. (All of these screenshots are from Kindle Previewer, just so I don't have to copy them to a bunch of different devices.) Notice that no matter how short, each line of poetry is displayed on its own line. Poetry doesn't reflow. It's hard to tell from this screenshot, but note that Kindle automatically indents lines of text 40px for Kindle and Kindle for iPad and iPhone, but not for Kindle Fire!

Poetry, little formatting

If we turn the iPad sideways, or make the text bigger, or both, the lines suddenly don't fit. Not only that, the automatic first line indent that Amazon adds makes poetry look particularly bad. It starts being hard to tell what is the second half of a long line, and what is an individual shorter line.

Poetry, vertical

Here's what it looks like on a legacy Kindle (what I'm calling "old mobi"):
Poetry, Kindle (old mobi)

Not pretty.

And here's what it looks like on Kindle Fire. Remember that Kindle Fire doesn't have an automatic first-line indent:

Poetry, Kindle Fire

The combination of automatic full justification with no first-line indent and no adjustment for the poetry lines looks particularly bad on the Kindle Fire. It's just a sea of text.

What's the solution? The convention for formatting poetry is to indent the part of the line that doesn't fit. What layout folks call a hanging indent.

You can do this pretty easily with CSS. Add a left margin of say, 2em, which will push the whole line over and then add a negative text-indent of -2em so that the first line starts at the flush left as usual. In this way, each line of poetry will start at the left margin, but any part of the line that overflows will be displayed indented on the second and subsequent lines. Here's the CSS code:

p {line-height: 1;padding:0;margin:0}
p.firstline {margin-top:2em; margin-left:2em; text-indent: -2em;}
p.line {margin-left:2em; text-indent: -2em;}

And here's what it looks like on the Kindle Fire:

Poetry- KindleFire formatting

I'd certainly want to adjust the general formatting a bit, but now the lines of poetry are at least inteligible.

But if you open it up with a legacy Kindle, it looks pretty bad:

Poetry - bad Kindle formatting

And it looks equally bad on Kindle for iPad:

Poetry, Kindle for iPad, bad formatting

What's going on?? It turns out that old mobi handles values for text-indent in a very strange way. If you don't set a text-indent value, old mobi automatically indents 40px. If you set a positive text-indent, it will use that instead. (You can use px or em, but if you use em, only whole numbers will work.) But if you set a negative text-indent, it actually creates a hanging indent, with the first line flush left and the second and subsequent indented as much as the absolute value of text-indent. Go figure. That's weird and unexpected, but if you set the left margin at the same time, it all gets mucked up and the details are way too boring to explain. Trust me, you don't want to go there.

To create a hanging indent on old mobi, you use just a negative text-indent, but no left margin. It shouldn't work, but it does.

h1 {text-align: left}
p {line-height: 1} 
p.firstline {margin-top:20px;text-indent:-40px}
p.line {text-indent:-40px}

And here's what it looks like on a legacy Kindle:

Old Kindle poetry

That's fine, but look at the same code on a Kindle Fire:

Poetry bad formatting Kindle Fire

Because of those negative-indents and the lack of an automatic left margin, or whatever hack old mobi used, now our text is cut off. Unacceptable.

So, Kindle Fire and decent EPUB ereaders that support CSS like iBooks want a left margin and a negative text-indent, but old mobi can't handle that combination, being able to use only the negative text-indent.

The answer is to serve different CSS to different ereaders, by way of a media query. I'm going to show you how to do it in an internal stylesheet but the same principles would hold in an external stylesheet.

First, create a regular stylesheet with no media attribute that will contain the styles that should be applied to all versions of the ebook.


<style type="text/css">
    h1 {text-align: left}
    p {line-height: 1;padding:0;margin:0}
</style>


Next, create a second stylesheet with media="not amzn-mobi" in the opening style tag. The stylesheet should include all of the styles that should apply to all ereaders except legacy Kindle. Amazon says you should use media="kf8" but that's just because they imagine a world where all ereaders are either Kindle Fire or legacy Kindle. Let's just say that most people's worlds are bigger than that.

<style type="text/css" media="not amzn-mobi">
    p.firstline {margin-top:2em; margin-left:2em; text-indent: -2em;}
    p.line {margin-left:2em; text-indent: -2em;}
</style>


Finally, create a stylesheet just for legacy Kindle, adding media="amzn-mobi" to the opening style tag.

<style type="text/css" media="amzn-mobi">
    p.firstline {margin-top:20px;text-indent:-40px}
    p.line {text-indent:-40px}
</style>


Here's what it looks like on Kindle Fire:

Kindle Fire Poetry - good

And here's what the very same file looks like on a legacy Kindle:

Old Kindle Poetry -good

Success!

And just in case you were worrying, here's what the EPUB file looks like in iBooks on the iPad:

Poetry in iBooks

Indeed, it looks fine, because iBooks' support of CSS is pretty good. 

A technical note. There was some concern that you couldn't serve different indents to Kindle Fire and to legacy Kindle because the legacy Kindle code uses the width attribute (in a bizarre way) in the HTML, and not the CSS. But the technique described above works because KindleGen converts the CSS in a good EPUB into the weird, hackish old mobi code—complete with width tag—that legacy Kindles love, but creates "KF8" code for the new Kindle Fire, which, as I mentioned Thursday, is virtually the same as the original EPUB. And EPUB readers will get the original, good, EPUB file. So everyone's happy.

Except designers who have to do twice the work. Think standards don't matter? Think again.

One final note. I've been saying that the KF8 files that KindleGen generates from the original EPUB are practically identical to that original EPUB. That's true only for the CSS that KF8 supports. I haven't tested it extensively, but I suspect KindleGen will just ignore the CSS it doesn't support. And I have yet to determine (nor have seen elsewhere) just how well Kindle Fire supports CSS in the first place. I need a couple more days!


30 comments:

  1. Thank you for this information, Liz. Very helpful.

    ReplyDelete
  2. Liz, I think you're being overly generous in what you call "acceptable." Personally, I wouldn't apply that term to poetry with any justified lines or end-of-line hyphenation. In fact, I wouldn't even try to put serious poetry on any ereader that didn't give the designer control over those elements -- unless it was by way of something like SVG images.

    There's only so much I'm willing to sacrifice on the altar of ebooks!

    ReplyDelete
  3. Thanks Liz,
    Great information, as always.

    ReplyDelete
  4. Hi Aaron:

    My iPhone is 2" wide and I can't change that. So, I prefer the text to wrap then be displayed too small to read. We can't have everything.

    Some, I'm sure, would continue to read at least certain poetry in print. But not all.

    ReplyDelete
  5. So where is IDPF in all this? You'd think that the lessons of HTML would serve to make things easier this time around. On the web it used to be a nightmare coding around IE6 weirdness but then the web standards project came along and things are much better now. Not perfect but better.

    ReplyDelete
  6. Wow, this is awesome. I'm about to publish a poetry ebook and got the hanging indents working beautifully in EPUB but not for Kindle. I could make it look great for the new Kindles and lousy for the others or forgo the hanging indents altogether. Just yesterday I was wishing there was a way to serve reader-specific css files. Then I came upon your site today and your solution works quiet well. Thank you, a thousand times, thank you for this post.

    ReplyDelete
  7. When I used

    <div style="padding-left: 2em; text-indent: -2em;"> </div>

    as the poetry line wrapper, it seemed to work well on both NOOK Touch and Kindle Touch. But I will try your media query approach.

    Thanks.

    ReplyDelete
  8. I've had bad luck with media queries. Last one I tried choked ADE--it didn't parse the CSS file at all.

    ReplyDelete
  9. There are a lot of threads on a lot of forums asking questions which are answered by this post. Nice one.

    ReplyDelete
  10. Hi Liz,

    This is definitely helpful. What about situations where we want to feed one rule to iBooks and a different one to the Kindle Fire?

    Its seems that:
    "not amzn-mobi"

    is also read by the ipad unfortunately. It would be better if we had a syntax that was Kindle specific also.

    If you have a solution I'd love to hear it.

    ReplyDelete
    Replies
    1. Here's a cool reference for different media queries (beyond the not amzn-mobi if needed). It's totally for web developers so it's all about that kind of stuff.

      http://css-tricks.com/snippets/css/media-queries-for-standard-devices/

      Delete
  11. This is really great info, thanks.

    Another wrinkle here is that if you set a left margin for verse (as I do when it is quoted in a prose work), Kindle ignores text-indent. There doesn't seem to be any way to create a hanging indent for paragraphs that already have a margin.

    ReplyDelete
    Replies
    1. @Peter. This article might help: http://www.pigsgourdsandwikis.com/2012/02/multiple-indents.html

      Delete
  12. Rather than multiple stylesheets wouldn't something like @media only screen and (min-device-width: 768px), amzn-mobi, amzn-kf8 {definitions} be easier to maintain (example supposes particular styles for iPad and Kindles).

    ReplyDelete
  13. awesome! i'll definitely be bookmarking this page for help. thanks for the post. =)

    ReplyDelete
  14. My problem is I haven't a clue what this all means! Can you recommend a service that could format a poetry book (with pictures) that would suit most digital readers? I've searched extensively, but nobody seems to handle poetry. (Well, actually it's a story in verse, so there are no chapters or headings, but several pictures.)

    ReplyDelete
  15. I am not able to follow the technical code you propose, but I am very happy to see the results. Congratulations! As a reader of professional texts, I am very frustrated since much technical information on reports (pdf usually) on the web is not adapted to be read in eReaders. Information on tables, figures and plots is incomplete or unreadable when transferred to an EPUB format. I understand your work should help in that field.

    ReplyDelete
  16. Thanks, Liz. Very helpful.

    I'm curious if you or anyone has had any experience using anything other than amzn-mobi or amzn-kf8 in the media query and the result on other ereaders. I've had success using those two, with everything rendering perfectly across devices (kindles, ipad, kobo, sony, nook) but as soon as I use anything other than those two, even using 'not amzn-mobi', causes ADE to ignore all CSS. This baffles me, since it *should* only ignore anything in the media query... right?

    ReplyDelete
  17. I wonder if you could assist. I used your code and ran a test upload on Amazon Kindle. I was amazed, it worked perfectly. I then continued with the volume of poetry, saved as Web Page Filtered as normal, copied and pasted the sections and... Amazon refuse to accept the file. The Previewer throws up a warning error for the first "text/css" (taken from the first of the 3 codings in red on this blog.
    I have done nothing different from the test upload to the complete file, other than a larger file. I would be most grateful because if it worked for the test upload, it should have worked for everything.
    Interestingly, Amazon will not even re-upload the orginal test file.
    Stephen

    ReplyDelete
    Replies
    1. Hi Stephen:
      My gut feeling says there's something totally unrelated going on, probably a minor typo that's gumming up the works. This has often happened to me: I spend forever trying to figure out something about the new thing I'm trying , only to find that it was an old thing—improperly spelled, for example—that was the issue. Let me know!
      Liz

      Delete
  18. Thank you for commenting so quickly Liz. I have made a second copy and this one worked without error on the Kindle previewer on my pc. Again, the Kindle website spat it out lol I then ran the whole HTML code through an online checker and it came up with nothing as an error other than it wanted a HTML language coding at the top which isn't needed for this purpose. So Word converted the file perfectly and your code on this blog was inserted correctly and also worked perfectly.
    I am about to do a completely new file and try again both without your code here and with it. But so very strange that my test upload worked perfectly and I have examined the HTML from the Kindle site and there is no difference.
    As you say, it could well be a new error unrelated to anything but contained now in the new Body. I will let you know and thank you again.
    Stephen

    ReplyDelete
  19. Hi Liz, added to above post for you...
    I have so far today spent 7 hours trying to work out what was wrong, why the file would not upload successfully, and also contacted you and took up your time.
    I have just tried to upload a new web filtered file saved from Word, it gave the following Attention! message...
    "We encountered a problem while processing your file. This error may be due to an unsupported or incorrectly formatted file. Please try uploading your book in a different format."
    I added your HTML into the head of the file and tried again... and again it was rejected with the same error message.
    I then went to a web filtered file which I have already submitted to Amazon and is on the Kindle site and, you guessed it, exactly the same error message. It wouldn't even take a file that it has already accepted.
    I now feel there is an error on the Kindle uploads section and so will send an email to Amazon asking them to check it out.
    I will let you know the reply when they ever get around to checking.
    Stephen

    ReplyDelete
    Replies
    1. Stephen, so sorry you're having trouble. My guess now goes to using Word, as its output is pretty awful and bloated. Try using a straight text editor (BBEdit, for example).

      Delete
  20. Hello again, Liz,
    Just to let you know that I had an email response from Amazon which states their system has a "glitch" preventing some publishers from uploading files. I have a feeling they have no idea who this has affected until they are contacted directly. They advised that it should now be fixed for me and to advise if there is a further problem.
    I uploaded my file containing your code from this blog and it was accepted straight away :)
    Thank you, so much, I appreciated your comments and this Blog page has been a tremendous help to me.
    Stephen

    ReplyDelete
  21. This is fantastic! Do you have an example of how the styles are applied (e.i. what the code looks like in the screen grabs) that could be easily shared?

    ReplyDelete
    Replies
    1. Um, I don't understand what you mean. All the code I used for the screen shots is given.

      Delete
  22. Hi, Liz. I'm looking forward to trying this out. But I want to reconcile it first with something you said about queries on your later post on multiple indents--specifically regarding Nook or legacy Nook (link and quote below): http://www.pigsgourdsandwikis.com/2012/02/multiple-indents.html
    "Since NOOK completely ignores the "not amzn-mobi" media query and any CSS that follows it, the trick is to put the NOOK (and other ereader code) in a stylesheet without a media query, and before the aforementioned old Kindle stylesheet."

    Would that not apply to this double query as well, to where we might put the "not amzn-mobi" styles in the first (and general) stylesheet with no query, leaving us with just the last media query/stylesheet afterwards, containing those styles applicable to "amzn-mobi"?

    Also, do you know if files mentioning amzn in their stylesheets are accepted by ibookstore? I've heard they reject epub books mentioning amazon, but that might only apply to the readable text in the book?

    ReplyDelete
  23. Hi Liz! Thank you very much for this post; it was one of the EPUB ones I found almost a year ago that made a lot of things possible for me. Even though my company doesn't use media queries in our poetry E-books, your insights on indents and units of measurement got me thinking in very useful ways.

    ReplyDelete

More of my books