View Full Version : SVG & Layout fun - need some help


ldolse
01-28-2011, 05:19 AM
I've been working on scanning and converting some of my favorite paper books that aren't available as ebooks, and some formatting one would think should be simple is really quite challenging.

Anyway challenge of the day is chapter headings with large images. The book has a squarish image at the beginning of every chapter - the image pretty much goes to the page borders and takes up about ~60% of the page. Below that are a Chapter header and 1-2 paragraphs.

I'm trying to future-proof my epubs and use decent sized images that can scale across multiple devices. The obvious answer seemed to be SVG. The problem I'm having is inserting an SVG image which will always be nailed to the top of the page border, and try to include the Chapter header and at least 2 lines of text no matter the aspect ratio of the page. It seems i can have only one or the other - an SVG which is scalable and remains nailed to the top of the page, but pushes text away in landscape-ish views, or an SVG that slides away from the top of the page when the width is narrowed.

Ideal Requirements:

Width of the image should be 100% of the page width in portrait mode, ~60% of the height
As the aspect ratio changes that should change to allow for the header and a few lines of text.
In portrait views the image should always be at the top of the page with equal margins on the three sides - that's another issue is that ADE doesn't seem to center it perfectly....


I've attached an epub book that displays three different examples, all manipulating the height of the SVG view box. There is a div with a red border around it so you can see how resizing/viewbox parameters stretches the div (seems like ADE prefers SVG wrapped in Divs as well).

Ideally I'd like something close to example 1, but without the image floating down the page and increasing whitespace as the width narrows.

Here's the SVG/html code I'm using in case you don't need to download the example epub:<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Width 100 and Height 70</title>
<link href="../Styles/Stylesheet.css" rel="stylesheet" type="text/css" />

<style type="text/css">
@page { margin-bottom: 5.000000pt; margin-top: 5.000000pt; }
</style>
</head>

<body class="calibre">
<div class="chapterpic">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xlink="http://www.w3.org/1999/xlink" height="60%" version="1.1" viewBox="0 0 876 857" width="100%">
<metadata id="metadata7">image/svg+xml</metadata>

<g id="layer1">
<image height="876" id="image3144" width="857" xlink:href="../Images/testimage.png"></image>
</g>
</svg>
</div>

<h2 class="calibre23" id="heading_id_2">Ex. 1:Width 100%, Height 70%</h2>

<p class="calibre24"><span class="font2">This setting provides the best balance between both portrait and landscape views, and seems to display well in ADE and QT based renderers. &nbsp;Unfortunately as the width gets narrower the image will not stay nailed to the top of the page, and white space also increases at the bottom of the image as well.</span></p>

<p class="calibre24"><span class="font2">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur vulputate, eros eget blandit iaculis, nulla sem pulvinar diam, eu vehicula est nibh ut tellus. Fusce in ligula metus. Proin hendrerit velit sit amet diam vestibulum id sodales urna aliquet.</span></p>
</body>
</html>

pdurrant
01-28-2011, 06:40 AM
If you add

preserveAspectRatio="xMidYMin meet"

to the attributes of your svg element, that will keep the image at the top of the SVG box.

The obvious way to do what you want would be to use the preserveAspectRatio attribute, set the svg width to 100%, and style it with a CSS2 style having max-height: 70%.

Unfortunately, nothing (browsers, ADE, etc) seems to honour the max-height CSS attribute.

By setting height to 70%, things almost work, except when the image size is less than 70% because of the thin page. You then get white space below the image.

I don't think it's possible yet to do what you want. It shows how far ebook specifications and implementations have to come before they're properly fit for designing good looking books.

ldolse
01-28-2011, 07:03 AM
Thanks - that did improve things quite a bit. Need to read up on that attribute further. At least the image is nailed to the top, even if the whitespace can't be eliminated - anyway I don't think there are mobile phone readers that can render SVG just yet, so really needing that narrow a width to look right isn't too critical.

Ebook formatting does seem to still have a long way to go - makes me sad when I see so much of the discussion on the next revision of epub focused on interactivity vs. fixing these basic layout issues.

Jellby
01-28-2011, 09:34 AM
Unfortunately, nothing (browsers, ADE, etc) seems to honour the max-height CSS attribute.

That's because there's no concept of "page height" in the CSS model used by ePUB, which is based in web pages, that have a width but no definite height (you just scroll up or down to see the contents). From the CSS spec (bold is mine):

<percentage>
Specifies a percentage for determining the used value. The percentage is calculated with respect to the height of the generated box's containing block. If the height of the containing block is not specified explicitly (i.e., it depends on content height), and this element is not absolutely positioned, the percentage value is treated as '0' (for 'min-height') or 'none' (for 'max-height').

pdurrant
01-28-2011, 10:12 AM
That's because there's no concept of "page height" in the CSS model used by ePUB, which is based in web pages, that have a width but no definite height (you just scroll up or down to see the contents).

There is window height, which is what's used is you specify height: 70%. There's no reason why max-height shouldn't work the same way.

Jellby
01-28-2011, 01:54 PM
There is window height, which is what's used is you specify height: 70%.

Where does it say that? The except I quoted says the percentage refers to the containing block, and the containing block is not the window, but probably the <body> element, which "depends on content height". I wish it would work like you say, but I haven't found any reference saying so.

pdurrant
01-28-2011, 02:28 PM
Where does it say that? The except I quoted says the percentage refers to the containing block, and the containing block is not the window, but probably the <body> element, which "depends on content height". I wish it would work like you say, but I haven't found any reference saying so.

I don't have a reference to where it says that. But that's the way ADE handles it, if the html and body elements are set to have height 100%.

This is, again, one of the problems with ePub specs. There are basics of layout info needed for high quality typesetting that are just not well defined or are not well implemented.

ldolse
02-02-2011, 09:47 AM
OK, new SVG problem, different book.

This time I'm trying to handle scene break markers, and the scene break marker is a simple dingbat - ☆ - unfortunately because ADE based devices are terrible with regard to their default fonts I can't just stick that in my code.

Rather than embedding a whole font, I thought that SVG could come to my rescue again, and it did - sort of...

I converted the dingbat to a path in Inkscape, pasted the SVG code into Sigil, worked my way past Sigil's current issues with SVG, and after some trial and error got it working in both ADE and QT. Basically needed to wrap the SVG in a div, and also add a style to the SVG class that limited the SVG to 1.5em in height. So far so good.

Then looking at the xhtml I was thinking about how inefficient it was to paste the same SVG code into the file over and over again for every scene break marker, and low end devices might not like it much... So I decided to add it as a file to Sigil in the images directory. It was also much more obvious to me how to set up alt-text for browsers which don't support SVG using an image tag - I'm sure that's possible directly in the SVG, but wasn't sure how to go about it.

Anyway I set the image up similarly to the original SVG - wrapped in a div tag, height set to 1.5em. Now the SVG gets squashed... Auto on the width didn't help. Manually setting a width did work, but Webkit and ADE seem to disagree wildly about what '1em' is horizontally. To get the right aspect ration it needed to be around 1.5x6em in Webkit, but 1.5x3em in ADE. That's no good. I tried adding preserveAspectratio, but that only succeeded in squashing the svg in different directions.

Is there an easy fix, or is this entirely the wrong approach and an SVG font would be better?

I've attached another example epub.

This is my SVG code:
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" preserveAspectRatio="xMidYMid meet" viewBox="0 0 139.75 131.09">
<metadata>image/svg+xml</metadata>
<g transform="translate(-260.12456,-332.18677)">
<g transform="matrix(3.9575472,0,0,3.9575472,-421.93397,-780.94632)" fill="#000">
<path d="M183.91,307.67,190,303.46l5.9375,4.2188-2.0312-7.0312,5.9375-4.0625h-7.5l-2.3438-6.7188-2.3438,6.7188h-7.5l5.9375,4.0625-2.1875,7.0312m6.08-1.1l-10.781,7.8125,4.0625-12.656-10.938-7.6562h13.594l4.0625-12.812,4.0625,12.812h13.594l-10.938,7.6562,4.0625,12.656-10.76-7.81"/>
</g>
</g>
</svg>


This is my html code: <div class="scenebreak"><img alt="*" class="scn_img" src="../Images/Star.svg" /></div>

And this is the relevant css(without the width, so squashed):
.scn_img {
height:1.8em;
}
.scenebreak {
display: block;
margin-bottom: 1em;
clear:all;
margin-left: 0;
margin-right: 0;
margin-top: 1em;
page-break-before: avoid;
text-align: center;
}

pdurrant
02-02-2011, 11:12 AM
I suggest putting the height="1.8em" into the .scenebreak CSS, removing it entirely from the .scn_img CSS, and adding a height:100% attribute to the img tag.

If you want to add space above and below the graphic, add some margin-top and margin-bottom to the .scenebreak CSS.

(The img tag height attribute only takes pixels or percent. Although the CSS height can take ems, I don't think it's specified what happens if you specify only height or width. But with the img height attribute, it's pretty much universal that the aspect ratio is maintained.)

ldolse
02-02-2011, 11:38 AM
I'd tried something like that when it was a div with an inline SVG, and that didn't work, but it may well work with the <img> tag. I'll give it a shot just to see.

Actually I just found another solution which seems to work perfectly, i.e. use <object> instead of <img>: <div class="scenebreak">
<object class="scn_img" alt="*" data="../Images/Star.svg" type="image/svg+xml">
</object>
</div>

I would like to get a better understanding of all these different ways one can insert an SVG - font, object, img, inline - any others? I'm not talking about technically how-to so much as best practices to use one technique vs. another.

ldolse
02-02-2011, 11:54 AM
Changing the height to 100% with the <img> tag worked perfectly as well, thanks. Both <img> and <object> seem to work better in other ways too - Safari renders them, while it ignores the inline version - not sure if this would in any way affect how ibooks would render this kind of content.