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:
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}
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:
This works on most major browsers and ereaders:
And is converted properly for Kindle Fire:
(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:
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:
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:
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.)
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 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):
But what happens when you view the ebook in iBooks on iPad?
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:
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!