Friday, March 23, 2012

Centering in ebooks across ereaders

A long time ago, I realized that the most basic parts of childrearing—eating, sleeping, and peeing and pooping—were by far the hardest to figure out. So it is with ebooks. It seems almost ridiculous to have to write a big, long complicated post about centering—something so essential and so fundamental—but I keep bumping up against it, so write I will. I hope I'll save you some sleepless nights.

Centering in ebooks involves CSS, the box model, inheritance, and ereader inconsistencies. The main problem with centering lies in not understanding how these aspects relate to each other.

The text-align property

I'll start with the simple. There is a CSS property called text-align whose possible values are left, right, justify, and center. But there is one very important caveat: text-align only affects inline-level objects within the block-level objects to which text-align has been applied. Let's look at that closely, since it is the source of many misunderstandings and thus errors.

Here is a simple p element that contains text.

<body>
<p class="center">Here is some text that should be centered</p>
</body>


And here is the CSS:

.center {text-align:center}

And here is what it looks like:

Preview: centeringex.html

You may think that it is the p element that has been centered, but you'd be wrong. It's actually the inline contents of the p element, an anonymous inline block, if you can stand the CSS parlance, or simply the text itself (if you can't), that is being centered. The p element itself is not centered.

How can you tell? We'll set the width of the p element to 60%, and then set the background color to yellow, so you can actually see it.

.center {text-align:center; width: 60%; background: yellow}

Preview: centeringex.html

You can now clearly see that the p element is still aligned left (which is the default in most browsers and ereaders) even while the inline text that it contains is aligned center within the p element.

Centering block-level elements

So how do you center a block-level element? The canonical way is to set the right and left margins to auto. According to the CSS spec, when both left and right margins are auto, they should be equal, and thus the item will be centered. And don't forget that unless your block element has a width that is smaller than the window size, you won't be able to tell if it's centered or not.

So, to center our p element, we'd have this:

.center {text-align:center; width: 60%; background: yellow; margin-right: auto; margin-left:auto}

And we would get this:

Preview: centeringex.html

This works on most major browsers and ereaders:

Centering-iBooks iPad

And is converted properly for Kindle Fire:

Kindle Fire Previewer - CenteringAcrossEreaders

(Regular Kindle doesn't support width and thus can't center a block-level element at all.)

CSS bug in ADE, NOOK, etc.

Unfortunately, ADE, and the ereaders based on it (like NOOK, NOOK Color, and presumably Sony Reader though I didn't test this last one), don't properly interpret the auto value for left and right margins, and the result is that the blocks are not centered:

NOOK Color centering

Independence of alignment of contents and of the block that contains them

Before we get to the solution, I just want to underline how the text-align properties and centering of the block level elements using automatic right and left margins are independent of each other.

That is, the alignment of the inline-level elements within a block-level element need not match the alignment of the block-level element. That is, we can center the p element within the window and then left-align the contents of the p element:

.mismatch {text-align: left; width: 40%; background: red;margin-right: auto; margin-left:auto }

And that should look like this:

Aligned left within centered block

Notice how the image and the text are aligned to the left within a box that is centered on the page.

Again, ADE, NOOK, and presumably Sony Reader, don't properly interpret the right and left margins set to auto:

NOOK centering mismatch

The Solution

The solution hinges on the fact that text-align only affects inline elements. (This is why simply enclosing an inner div in an outer div whose text-align property is set to center will not work.) We'll enclose the p elements in a wrapper div, whose text-align property we'll set to center, and then we'll set the display property for the p elements themselves to inline-block. The inline-block value is sort of a hybrid between inline and block, that for our purposes keeps the p elements starting their own paragraphs (like regular block-level elements) but allows them to be affected by text-align (like inline-level elements).

Here's the CSS with the new bits in bold:

.wrap {text-align:center}
.center {text-align:center; width: 60%; background: yellow; display:inline-block}
.mismatch {text-align: left; width: 40%; background: red;display:inline-block }


And here's our new HTML:

<div class="wrap">
<p class="center">Here is some text that should be centered</p>
<p class="mismatch"><img src="momo.jpg" alt="momo" width="200" height="150" /><br />This image and text will be aligned to the left within the centered block that contains them.</p>
</div>


Let's look first at iBooks on iPhone: (I've put it in landscape orientation just so it's easier to see, it looks the same in portrait.)

iPhone Centering

Everything is as it should be. Our boxes are centered, but the contents within them are centered and left-aligned respectively.

How about NOOK Color?

NOOK Color-centering inline-block

NOOK Color also likes this solution, even when Publisher Defaults are turned off (although then you have other margin issues).

And Kindle Previewer converts the file just fine for KF8 and the Kindle Fire ("old" Kindle can't center divs but maintains the text-alignment for the inline level elements):

Kindle Fire Previewer - CenteringAcrossEreaders6

But what happens when you view the ebook in iBooks on iPad?

iBooks iPad Centering

The boxes are centered as desired. But the text and image that should be left aligned in the lower box are now justified! Look at those ugly spaces between the words. What happened?

Now we've bumped up against iPad's default overrides. Remember that by default, Full Justification is set to ON, hidden away in the iBooks area of the Settings panel. I don't think most people who use iBooks will ever know this setting exists so ebook designers have to plan for it. You used to be able to add a span tag around the text that you wish to have aligned to the left, but that hack no longer works.

Thankfully, there is still a workaround. If you add the com.apple.ibooks.display-options.xml file to the META-INF folder, with the <option name="specified-fonts">true</option>, the justification that you choose in your CSS will be maintained, regardless of the Full Justification setting chosen. The user can still override your choices by choosing a different font in the Fonts menu, but at least the book will start out the way you want it:

iBooks iPad

To resume:

The text-align property only applies to inline elements within the block-level element to which the property is applied. It is inherited by block level elements that may be enclosed in the outer block-level element and in turn applied to the inline elements that the inner block level elements contain. If you need more info on block level vs inline, see the CSS spec or my my HTML/CSS book.

The canonical way to center a block-level element is by setting both margin-right and margin-left to auto. The fact that this is not supported by ADE or NOOK (and presumably not by Sony Reader or other ereaders based on ADE) is a serious bug.

You can center block-level elements by wrapping them in another block level element (a div), setting the text-align to the outer div to center, and then setting the display property of the inner div (or p or whatever) to inline-block.

iBooks on iPad has a default setting of Full Justification for text, which you can override by adding the com file to the META-INF folder. This has ramifications with respect to font choice, of course, as well.

iBooks on iPhone has the Full Justification setting, but by default it is set to OFF (presumably because of the narrow screen).

This should be much simpler.

And yes, it's true that I have no AT&T coverage in my office!


22 comments:

  1. As always, Liz, you have helped many of us trying to keep up with the eBook design and eReader devices/apps world. But did you have to make my head hurt on a Friday? Couldn't you saved it for, say, Monday?

    I assume this solution also works on the Kindle Fire and e-Ink Kindle?

    ReplyDelete
    Replies
    1. Thanks, Walt. And yes, the display:inline-block solution works for Kindle Fire and is equally ignored by e-ink Kindle. I updated the post accordingly.

      Delete
  2. For ADE, and for all readers, also iBooks: if "margin:auto" doesn't work, center can be made by setting margin-left equal to (100%-width)/2.

    ReplyDelete
    Replies
    1. Yup, quite right, as long as you know the width of the inner div. It just won't work if it's a percentage.

      Delete
  3. Thank for that. Have you ever test a weird but simple thing; Add a blank span for the texte right et center. "span"Center text"/span"
    I use that for many ebooks and it works! : )
    Even on ADE, Sony, Kobo, iBook, but i never test it on Nook et Kindle. Did you hear too about Readium ? It will be, i think, a good thing for us all!

    ReplyDelete
  4. This even made sense at a sleepless two thirty in the morning. Thank you.

    ReplyDelete
  5. No ho entenc per què . . . even after reading this excellent blog entry and after having purchased two of your books, the one thing I want to know is missing: how do I put text on a colored background (as you did above) and how do I put words on top of an image and have both come out correctly on an iPad? "Text on top of Image" would be a very welcome blog entry--especially to this author and illustrator of children's books! Aloha, James Rumford

    ReplyDelete
  6. As usual, brilliantly explained. A most useful post, but yes, a bit hard on the brain on a Sunday morning.

    Text on top of an image? I didn't know that was possible. I too would find that most useful.

    ReplyDelete
  7. i would suggest using a background image - does it work with ebooks?

    ReplyDelete
  8. No wonder e-book formatting is so infuriatingly complex to get right and no wonder most people get it wrong. At least with print book formatting, WYSIWYG.

    I'm a print book designer and typesetter and I have enough HTML and CSS knowledge to format a dead simple novel. But, after reading this, I may never try to center an e-book line again. Flush left will do quite nicely, I'm thinking.

    Thanks, Liz ... as always, for sharing your incredible knowledge on this subject. I know I can always call on your for help.

    ReplyDelete
  9. I've been using (well, fighting with) css for about eight years, and this is the first explanation of css centering that has made sense. Now I finally understand.

    You're a genius!

    ReplyDelete
  10. Wow thanks, now let's hear about centering an image vertically on different eReaders.

    ReplyDelete
  11. Text on top of an image? I tried playing with that and couldn't do better than this: (spaces inserted into tags would need to be removed)

    < div style = "text-align:center;"> container div with, e.g. text-align:center; as desired
    < img style="display: inline;" src=" whatever" />
    < p style="display: inline; position: absolute; margin-left: -12em;"> some text
    < /p>
    "position: absolute;" allows that element to ignore other elements and therefore be stacked on top of them. However, the only way I could actually force that was with the ad hoc method of giving it a specific negative margin. The text would normally show up to the right of the image, and a negative left margin pulls it leftward and on top of the image.

    Img can be either inline or inline-block, but < p> must be "inline" or it refuses to overlap the img, at least for me.

    Much less than ideal, and I have no idea in which readers it would work. I'm also looking forward to Liz's lucid how-to!

    ReplyDelete
  12. It's not technically a bug in ADE - the ePub specification includes this line:
    "Reading Systems may set the value of any margin property whose specified value is auto to 0."

    ReplyDelete
  13. …But is there a way of getting block level elements to span more than one page in ADE? I'll be impressed if you can show me block text that spans more than one page!

    ReplyDelete
  14. Hy Liz,

    I hope you can give me some advice for my problem with a current epub file:

    - it was created with InDesign CS 5 on MAC OS 10.6.8;
    - it was optimized with Sigil (0.4.2), and the preview in all my readers on MAC is perfect (Sigil, Calibre, Adobe Digital Editions, Firefox epub reader).

    Although the alignment is left for all elements it looks different on different ipads:
    - on a colleagues ipad all looks perfect
    - on the customer’s ipad some Headlines are shown as justify
    - on a friend’s ipad all text elements are shown as justify (on his iphone it looks nearly perfect …)

    Thank you for feedback!
    Michael

    ReplyDelete
  15. Thanks, it really helped me out.
    I actually ended up with two wrapper div's, one with the center, one with the inline-block. My differently aligned paragraphs are inside these two. When the paragraphs were inline-block's themselves, they showed up side by side.

    ReplyDelete
  16. Thanks Liz! Your solution worked for me except that when centered text wrapped to a second line, both lines then appeared to be aligned left.

    The only fix I could find for this was to move the margin properties from the p style to the wrapper div style with display: block. That left only inline properties in the p style with display: inline (not inline-block, just inline).

    ReplyDelete
  17. This has fixed 95% of my problems! Images already behaved well in iBooks, but not in Nook, ADE, et al. Thanks to you, I have properly centered all images, save one: a little bee graphic used at the beginning of each section. I had applied all the same css to both, with one addition: the bee's width of 42px must be defined, else it takes on my img{width:90%} and is far too large as a result. Could this cause the bee to remain uncentered in Nook? I would hope not, but no noncompliance surprises me anymore..

    ReplyDelete
  18. A wonderful post for sure Liz. I hope you don't mind if I ask a question.

    Concerning my own problems with InDesign -- currently with InDesign cs4 and cs5,5 I am able to import and place my novel into InDesign via Place and I can export it happily and without problems to epub. The novel has no Word internet hyperlinks in it. But when I import another book from Word(with 170 i/net hyperinks in it) then InDesign crashes every time when I try and export to epub. And yet I can happily export this same book to Kindle via the InDesign plug-in with no problems.

    I've also tried importing this Word document as docx and doc but InDesign still crashes every time I try to export to epub.

    Is there a workaround other than spending hours re-formatting the links in InDesign or is this a known bug in ID ?

    My thanks to you in advance.

    ReplyDelete
    Replies
    1. I bet the problem is not all of the links but just one in particular. Look for links that contain an ampersand: they make ID crash when exporting to EPUB. (One option is to replace with bit.ly link. )

      Delete
  19. Liz, you are a life saver! I'm not sure if you still frequent this blog anymore, but maybe someone else will have an answer:

    Is there a good way to combine this HTML/CSS with something to force the text underneath the image (in my case, a caption) to stay on the same page as the image?

    Thanks!

    ReplyDelete

More of my books