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!
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.
Here's what it looks like on a legacy Kindle (what I'm calling "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:
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:
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:
And it looks equally bad on Kindle for iPad:
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:
That's fine, but look at the same code on a 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:
And here's what the very same file looks like on a legacy Kindle:
Success!
And just in case you were worrying, here's what the EPUB file looks like in iBooks on the iPad:
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!