Appendix B, Image Formats Explained draws out the distinction between raster and vector graphics, and Chapter Three, Structure, covers the use of Scalable Vector Graphics (a vector format) in your content, as a welcome alternative to using image formats such as PNGs and JPGs.
This appendix considers a few of the outlying issues that apply to moderate-to-advanced use of SVG.
Typically, when SVG editors save an image file, they include information that describes the state of the editor as it stands at that time, such as grid settings, and the position of guides, in addition to the actual image information itself. This editor-state information is redundant in a final e-book deliverable, and thus increases its size needlessly (thus costing you more under Amazon's 70% revenue model). Moreover, where an EPUB file contains such image files, validating it using the IDPF's online validator also yields a mass of notifications about unrecognised attributes and the like (which represent the editor information). These validity problems preclude sale of the EPUB through retailers other than Amazon.
Tools such as Inkscape allow you to save images as plain SVG, and while this omits the editor information, it does not resolve the validation problem completely, as you still get an error message like this:
Error while parsing file 'element "rdf:RDF" not allowed anywhere; expected the element end-tag or text'.
This occurs because, currently, Inkscape leaves the following element in the SVG code:
<metadata id = "metadata3339"> <rdf:RDF> <cc:Work rdf:about = ""> <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource = "http://purl.org/dc/dcmitype/StillImage" /> <dc:title></dc:title> </cc:Work> </rdf:RDF> </metadata>
…which you will have to remove manually using your text editor if you seek a perfectly valid EPUB but choose to go no further than saving as plain SVG (another good reason foracquiring a decent editor).
However, it is often possible to re-express the vector drawing instructions in a given image in a simplified or ‘optimised’ way. This preserves the image information, such that it appears the same when rendered, but removes other redundancies (in addition to the unneeded editor information), thus saving even more space than when you save as plain SVG. The total reduction in file size is dramatic, and so, to save in optimised form in Inkscape, you should choose ‘Save As’ from the File menu, and then select ‘Optimised SVG’. The process is a little different in editors such as Illustrator, so you may have to hunt around on the web for relevant directions if you are not using Inkscape.
Note that you can still edit the image subsequently, but any guides and grid settings etc. will have disappeared, causing the editor to use defaults. It is a very good idea therefore to save the image under a different filename by, say, appending ‘_Optimised’ to the end. For example, if the name of your file is Chapter_2a.svg, you should save it as Chapter_2a_Optimised.svg. This will preserve the un-optimised version, which is useful if you need to return to editing the image at some point (which occurs more often than you may think).
Moreover, to switch the book over to using the optimised versions you need only load all its HTML files into your text editor, and then do a global search-and-replace operation that changes ‘.svg’ to ‘_Optimised.svg’. If you need to switch back at any time to using the un-optimised version because, say, you need to continue developing the book, you need only perform another global search-and-replace, where you change ‘_Optimised.svg’ to ‘.svg’.
Finally in this section: while saving in optimised form removes the metadata element shown above (containing the ‘rdf:RDF’ part that the IDPF validator dislikes), it also introduces a line-height attribute into the SVG code. The IDPF validator complains about this too, and so, as with the plain SVG option, you must remove every instance of that attribute using your text editor in order to get a clean report from the validator (if doing this causes problems with the graphic in question, you will have to think of a different way to get the same effect in your vector editor). Having to do this is is tedious when using SVG images in a book, but saving as plain or optimised SVG and then editing manually is a necessary part of StepA in Stage Seven of the production process (assuming that you want to create the smallest deliverable possible).
Clearly, where SVG images include textual content, you may wish to use a particular font for that text, and if you choose a typeface from those installed on your production machine a web browser on the same machine will render the image faithfully. However, without intervention on your part, and unless they already have that typeface installed, e-readers will be unable to render such graphics using the same font, and so will use a default instead, which is unlikely to be what you desire.
There are three solutions to this:
A.
Convert to Paths. You can convert the text in a given graphic to the equivalent paths (see Step Eightin the Capturing Font Glyphs section below). This means that your vector editor will convert the glyphs in question to equivalent collections of linked nodes. This renders academic the question of whether a given user agent possesses the typeface, because the text no longer exists as a native textual entity.
B.
Embed Font in Graphic. You can import the relevant font information into the SVG file itself – either an entire font file, or selected parts that direct the rendering of the glyphs that your graphics possess (assuming that your vector editor supports partial embedding). In this case, the typeface goes wherever the file goes.
C.
Embed Font in Book. You can embed the relevant font file within the book file rather than individual graphics files, and have the renderer draw the glyph information from that; wherever the book file goes, so does the typeface.
There are various advantages and disadvantages to these approaches. Option A is favourable if your graphics have relatively little text, because adding just a handful of extra vector elements to a given graphic will not increase its size unduly. However, if you have a great deal of text in your graphics, where a wide range of glyphs are employed, it would be better to consider the other options as they may result in graphics files that are smaller and thus cost you less under Amazon's 70% revenue model.
Moreover, once converted to paths, you cannot re-edit the text as text. This means that you can make alterations only by emplacing the correct text, as native textual content, before converting it to paths again.
Option B runs the same risk as Option A, in that you could end up with a set of graphics files that are bloated with replicated typeface information. Moreover, such SVG files will not render in the Firefox web browser currently, which means you could not transport a given graphic over to a web site without changing the file to use option A or C. Furthermore, while Adobe's Illustrator supports font-file embedding, Inkscape does not (again, currently), so this option is unavailable to Inkscape users.
Option C is therefore the best beyond situations where the text in your graphics is relatively sparse, as it decouples the graphics from the typeface information. This allows a single instance of a given font file to be shared economically throughout the book.
This solution becomes even more agreeable if your e-book uses the typeface in question elsewhere in its textual content, as the @font-face declaration in your CSS code will be sufficient for the renderer to locate the glyph information. However, while this works for web browsers, and appears to work for EPUB readers, it does not work for all Kindles. That is, some Kindle user agents render the graphic without the custom typeface.
This means that you have to create an explicit link to the font file within each graphics file that uses the typeface, and you will have to do this by editing the SVG file manually rather than through your vector editor. Thankfully, this is a relatively straightforward task, as an SVG file is simply a text file, just like a piece of HTML. Indeed, it looks very similar to HTML too, as it uses the same angle-bracket syntax.
These points in hand, the steps you should take to link to a font file are as follows:
1.
Open File in Text Editor. Locate the appropriate SVG file, and open it within your editor. If you get a message of some form about overly long lines, it will mean that you have embedded a raster image in the file, in which case your vector editor will have converted the information it contains into very long lines of text (non-human readable) that it placed within the graphics file.
It is inadvisable to proceed if you see such a message, because changing the text in such a file, and then saving it may cause corruption of the embedded graphic. If you do get such a message, open the file in your vector editor and delete the graphic (you will re-insert it later), and then save the file. Then re-open it in your text editor.
2.
Locate the <defs> element. Once you have the file in the editor, scroll down until you see an element that looks like this:
<defs/>
…or which looks like this:
<defs> <!-- Other elements here --> </defs>
In the first case, the <defs> element is childless, and so is self-closing, whereas the second example shows a <defs> element that possesses child elements relating to other structures in the file (do not worry if you see an id attribute in the <defs> tag, you can ignore that because it makes no difference to the task at hand).
3.
Insert a <style> element. Having located the <defs> element, you should insert a <style> element into it, and that element should contain a @font-face declaration. For example, the typeface used in the diagrams in this guide is called Quattrocento Sans, and so the <defs> element in the corresponding SVG files looks like this:
<defs> <style type = 'text/css'> @font-face { font-family : 'Quattrocento Sans'; src : url('../Fonts/QuattrocentoSans-Regular.ttf'); } </style> </defs>
In other words, if the <defs> element is childless initially, then you remove the trailing slash from the tag, and add an end tag such that the <defs> element now looks like the example above. (Again, if the <defs> element contains attributes, just leave them in place.) If, however, the <defs> element has existing children, you simply add the <style> element as an additional child, and leave everything else as it is.
Note here that the value for the font-family rule in the example above comprises two words, and so you must enclose it in quotes, as you must with the value of the src rule, whether or not the filename contains spaces. Failure to include the quotes in either case will cause the renderer to ignore the @font-face declaration.
4.
Use Single Quotes Only. This is a critical point: you must use single not double quotes to delimit the values of the font-family and src rules, because a hidden trap awaits the uninitiated here. If you edit the SVG file subsequently in Inkscape, that tool will preserve the @font-face declaration, but will cause it to convert the double quotes to the HTMLcharacter-entity equivalents.
That is, the following, which uses double quotes:
@font-face { font-family : "Quattrocento Sans"; src : url("../Fonts/QuattrocentoSans-Regular.ttf"); }
…will turn into the following:
@font-face { font-family : "Quattrocento Sans"; src : url("../Fonts/QuattrocentoSans-Regular.ttf"); }
…which will fail.
Single quotes are fine, Inkscape will not touch them, but double quotes will not survive the edit, and this will cause e-readers to ignore the typeface you have set for a given piece of text in the image, such that it uses a default instead. Note that you will receive a warning about this from Kindle Previewer when you build the Mobi/KF8 file, although you will receive no such warning when you validate the EPUB.
Despite all this, however, we are still not out of the woods, as choosing to save in optimised form (as covered in this chapter's first section above) causes Inkscape to replace any single quotes that you have used in your @font-face declarations with ‘'’ characterentities (that is, apostrophes, which are also single quotes in plain ASCII).
That is, the following:
@font-face { font-family : 'Quattrocento Sans'; src : url('../Fonts/QuattrocentoSans-Regular.ttf'); }
…will turn into the following:
@font-face { font-family : 'Quattrocento Sans'; src : url('../Fonts/QuattrocentoSans-Regular.ttf'); }
…which will also fail. There is only solution here, which is to open your optimised SVG files in your text editor just before you import them into your EPUB, and to change every ' back to proper single quotes.
Yes, such things are unnecessary and truly annoying, and they constitute a great waste of time when you are unaware of the trap in question, and have embarked on the usual jungle trek that ensues when you try to diagnose such problems. Sadly, they also go with the territory.
A final point on this topic: theprocessing that Amazon performs on a book file when it is uploaded for sale, can affect the use of custom typefaces in SVG images. That is it can causes another bug on (at the least) a Kindle Touch to manifest, such that some characters are rendered in the font you have stipulated, while others (within the same word or phrase) are rendered in one of the user agent's defaults. This is one point where the technique of emailing the book to your Kindle is of great value, as it gives you a chance to see the SVG material as customers will see it. If you fall foul of this particular bug, the only solution is to find an alternative typeface that looks very similar to the one that renders incorrectly.
There may be times when you need to render just one, or a bare handful at the most, of exotic or unusual characters within a mass of more-conventional glyphs in an ordinary piece of textual content. In this case, the greater the exoticism the lesser the chance that the default fonts that are available on user agents will support the characters in question.
As Option B states in the SVG and Custom Fonts section above, you could embed a custom font-file to ensure that the characters in question render correctly. However, as the next appendix, Unicode and All That, points out,there are few typefaces that cater for essentially all the characters in the writing systems for which Unicode caters (so called ‘pan-Unicode’ fonts). It follows that using just a few or even one glyph from the font file will cause much of the information that file contains to consume space redundantly. This will bloat the size of the book file unnecessarily, thus costing you more under Amazon's 70% revenue model (as theDrop Capitals section in Appendix C, Advanced Styling & Layout also points out). The the size of the deliverable and the redundancy within it will therefore be particularly large if you use a true pan-Unicode font, as it will contain information describing a massive number of glyphs.
A far better alternative lies in converting the character(s) in question into individual SVG graphics that you insert into the character sequence comprising the content in question. Indeed, this is the approach taken in Chapter Three, Structure, which gives theMongolian end-of-chapter symbol. That is, when reading the relevant section in that chapter, you are looking at a small SVG graphic, not a ‘native’ character glyph.
Recalling from Chapter Five, Layout, that <img> elements haveinline flow, you need do no more than give the graphic in question the correct size using a CSS rule, and you should follow these steps to create the graphic:
1.
Fire-up your vector editor.
2.
Create a text element in a new diagram.
3.
Place a character in the font in question into the text element, and set it to an initial size of, say, 10 points (you may need to use, on Windows systems, the Character Map application to capture the character you desire, or the equivalent on other systems).
4.
Adjust the size of the canvas such that the character fills the canvas snugly, and save the file.
5.
Insert an <img> into the text in your content, giving its src attribute the name of the SVG file.
6.
Create a CSS definition that applies to the character image (either by class or ID), and give it a font-size rule with a value of 1em (note, not 100%, otherwise the renderer will scale the graphic according to the size of its containing element).
7.
Create a version of your book using Sigil, Calibre or whatever EPUB editor you are using, and then create a Mobi/KF8 (assuming you are targeting the Kindle brand), and review the section that carries the exotic character. Determine the change required to make the character the correct size in relation to the rest of the content, and go back to your vector editor. Adjust the size of the character accordingly, and the size of the canvas again to maintain a snug fit, and save. Repeat this step until the character in the vector file is the correct size.
8.
Change the character to a path in the vector editor (in Inkscape, this is under ‘Path/Object to Path’), and save the file.
You may have to experiment a bit to get the right size, and you may need to alter the canvas size and the position of the character within the canvas so that everything renders seamlessly. However, once you reach Step Eight above, the SVG file will represent the character's outline not as a codepoint, but as a set of line primitives, and this will obviate embedding within your deliverable the font file from which you drew the glyph.
It is possible to make an SVG image ‘in-line’ with the HTML code in which it appears. Normally, you emplace an image in an HTML file by means of the <img> element, which has the advantage that, should the same image appear more than once in your book, there is still only one copy of that image within the deliverable. It follows that the more times the image in question appears in the book, the greater the return you get on the cost that it incurs in terms of the ultimate size of the deliverable, and hence on the pecuniary cost under Amazon's 70% revenue model. That is, repeated use of the same image throughout a book amortises its cost.
However, SVG is a human-readable tag language with a hierarchical structure, just like HTML, and so the code that comprises a given SVG image can form a native part of the HTML code that makes up the chapter in question. In the context of e-book production, there are two reasons you might wish to do this:
1.
CSS Styling. It allows you to style an image using CSS, in just the same way that you would style a piece of HTML. The details of this are beyond the scope of this text, but this section of this appendix is present in order to help you start out in the right direction. If you do wish to style in-line SVG, the search-terms suggestion is:
2.
Clickable Image Elements. You can make elements of the SVG image act as links on which the reader can click/touch in order to go directly to another point in the book's content. The section below considers this in detail.
Note here that, in the wider context of web site development, a third reason for using inline SVG is that you can then animate all or parts of the image using a bit of JavaScript programming, although, obviously, this does not apply to e-books. A fourth reason is that inline SVG means the browser does not have to perform a separate fetch for the image file, in addition to fetching the HTML, and this can speed-up page loading significantly.
The following demonstration of inline SVG uses the ‘link-forward’ arrow graphic that you see in this guide on the end of words that link to material that resides in following chapters. To make such an image in-line with the HTML for a given chapter, follow these steps:
1.
Open Image File in Vector Editor. Open your SVG image in your vector editor and save it in optimised form, ascovered in the first section above.
2.
Open Image File in Text Editor. On opening the SVG file in your text editor, you will see something that looks like the following (which is the optimised code that implements the arrow graphic), although note that it will not be laid out in the same way:
<svg xmlns:rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns = "http://www.w3.org/2000/svg" height = "40" width = "75" version = "1.1" xmlns:cc = "http://creativecommons.org/ns#" xmlns:dc = "http://purl.org/dc/elements/1.1/"> <g transform = "translate(220.58 -1160.5)"> <g fill-rule = "evenodd" stroke = "#000"> <path d = "m-213 1192.9 14-13.5" stroke-linecap = "round" stroke-width = "15"/> <path d = "m-199 1179.4h16.5" stroke-linecap = "round" stroke-width = "15"/> <path d = "m-182.08 1167.4 33 12-33 12z" stroke-linejoin = "round" stroke-width = "5"/> </g> </g> </svg>
If you see code that looks like this:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
…or this:
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" ... "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
…you should remove it, as it is not necessary to achieve the effect we seek. You should also remove all the code that reads as follows:
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/">
…as this is also unnecessary and it makes the surrounding HTML invalid.
3.
Copy and Paste Code. Select all the code from top to bottom and copy it. Then open in your text editor the chapter file in which the image should appear, and paste the copied code at the correct location within that chapter's code.
4.
Insert viewBox Attribute. If you examine the code above, you will see two attributes that look something like this (where the numbers will depend upon the dimensions of the image):
height = "40" width = "75"
This describes the aspect ratio of the image in abstract ‘units’ (i.e. it does not specify pixels, or ems, and suchlike). Given this, and continuing here with the numbers in the example above, you should insert an extra attribute that looks like this:
viewBox = "0 0 40 75"
That is, the last two values should match the values of the width and height attributes (note that the capitalised ‘B’ in the viewBox attribute departs from the all-lower-case convention for HTML tags and attributes, but this is the way the SVG standard defines these things). You can then remove the width and height attributes, as these are now no longer necessary.
Following this step, the updated code should look like this:
<svg viewBox = "0 0 40 75"> ... </svg>
5.
Emplace Container Div. Now place a <div> start-tag above the <svg> element, and its corresponding end-tag below that element, such that the code now looks like this:
<div id = "SVGContainer_0"> <svg viewBox = "0 0 40 75"> ... </svg> </div>
The purpose of the id attribute is to allow sizing of the image, which is necessary given ourresolution-independence mandate. Obviously, you could use a class attribute instead, if that suits your goal, or you could omit any id or class attribute, and scale the image using adescendant selector.
6.
Create CSS. Create a CSS definition that will control the size of the graphic. For example:
#SVGContainer_0 { width : 10em; float : right; }
These steps cause the arrow graphic, when rendered natively on the user agent you are using to consume this text now, to give the image you see in the sidebar here.
Finally in this section, a caveat on inline SVG: SVG editors often emplace id attributes in the code they generate, and (in Inkscape at least) these are usually single letters like ‘a’, ‘b’ and ‘c’. Normally, a human editor would (indeed, should) use more descriptive values, but the actual values employed are of no consequence to a renderer – all that matters is that they are unique within the code that describes the image in question. This can cause a problem if you have more than one instance of inline SVG code in a given tract of HTML, as different images can possess id attributes of the same value. That is, while an id attribute-value of, say, ‘b’ will be unique within a given image, it is not guaranteed to be unique within the HTML code as a whole. In other words, a given image can possess an element with the same id as an element in a different image in the same piece of HTML.
This causes two problems. First, it makes the entire HTML code body invalid. Second, it can ruin the appearance of a given image. That is, the image will look different when rendered in a given user agent to the way it looks in your image editor, drastically so in most cases.
The solution to both problems is to edit the SVG code for the images in question manually, setting their id attibutes to values that are globally unique, and setting the references to those elements elsewhere in the SVG code such that they point to the new id values. For example, if you have two images and both use id values of ‘a’, ‘b’ and ‘c’, you could re-name those values to ‘ImageA_a’, ‘ImageA_b’ and ‘ImageA_c’ in the SVG for the first image, and re-name the id values used in the second image to ‘ImageB_a’, ‘ImageB_b’ and ‘ImageB_c’. This technique is feasable, but the time and exactitude it requires on your part can render it impracticable, so do think twice before emplacing more than one body of inline SVG within a tract of HTML.
One particularly attractive idea is causing elements of an SVG image to act as links, such that a click/touch on the element takes the reader to another part of the content. This is an elegant concept that can only contribute to the value of an electronic publication – if a picture is worth a thousand words, a picture that embodies indexing semantics must be worth quite a bit more – and the technique has clear application in engineering, scientific and technical contexts. Children's books come to mind too.
Happily, therefore, the technique works perfectly in web sites, and, in line with our concerns here, it works beautifully in the EPUB format. Unhappily, it does not work in at least a few flavours of the Kindle brand. This is because it collides with Amazon's assumption that a short touch on an image means that you want to go back or forward a page, and that a long touch means that you want to examine the image in detail.
This limitation thwarted a plan for Chapter Seven, Production, in this guide, where the master production flowchart would have taken the place of the table-of-contents that you see at the start of the other chapters and appendices. A touch/click on a given step in the flowchart would have taken the reader to the corresponding section in that chapter, but this rather nifty idea proved impossible to implement using the canonical technique, and even the workaround given below did not work reliably. Nevertheless, and in case the technique does become viable at some point on Kindles (or you will be publishing EPUBs only), the steps you should take are given below.
Assuming you are using Inkscape, you should right-click on the appropriate element or element group in the image in question, and then click Create Link. A pane will open up in the user interface, into which you should provide two values:
1.
An href Value. This should indicate the location in the book to which you want the link to take the reader. It is just the same as any other href value you would give for an ordinary HTML link. Note that you must provide the full filename, as well as any id attribute if you intended to use the graphic in more than one chapter. That is, if you want the link to point to an element with an id attribute-value of ‘Ipsum’ in a file called ‘Lorem.htm’, then the href value should be ‘Lorem.htm#Ipsum’. That will allow you to use the graphic in any chapter in the book.
2.
A value of ‘_top’. Enter this into the ‘target’ field that you see (don't worry what about this means, just stick it in verbatim).
You must then make the SVG graphic in-line with the rest of the HTML (seeabove), and, assuming you are following the three-stage production processadvocated in Chapter One, you should then import the HTML file into your EPUB editor. However, if you are using Sigil, you will find that another tiresome problem enters the equation at this point. That is, Sigil re-writes the HTML unbidden, such that the link element is still present but wraps the relevant SVG element no longer. This renders the link ineffective.
To demonstrate, the example below shows the general form of the code prior to importation. Do not let the xlink:href attribute concern you, it is simply the way that links are implemented in SVG code. Similarly, the ellipses indicate simply that a real implementation includes a lot more code, which the example elides in the interest of clarity:
<a xlink:href = '../Text/Lorem.htm#Ipsum' target = '_top'> <text ... > <tspan ... >Lorem Ipsum</tspan> </text> </a>
The next example shows what the code looks like after Sigil has had its way with it:
<a xlink:href = '../Text/Lorem.htm#Ipsum' target = '_top'> </a> <text ... > <tspan ... >Lorem Ipsum</tspan> </text>
Notice how the <text> element (an SVG tag-type) is no longer nested within the <a ... > element. Sadly, code re-writing is a general feature of Sigil, in that importing a beautifully formatted piece of code into an EPUB within that tool sees it destroy the layout. It seems, the programmers behind the application have their own ideas about what constitutes good layout, and it is an equally sad fact that this kind of arrogance over layout is all too common in programming.
Notably, Sigil offers the option to turn code re-writing off, which stops it re-writing link-related code, but this causes other problems, and so is no solution. This leaves two possible resolutions:
A.
Re-edit the code within Sigil. This is extremely tedious when you have to go through a number of iterations of the production process, and when the image in question has a number of links.
B.
Unzip and Edit. You can produce the EPUB in the usual fashion and then use the technique mentioned inAppendix A. That is, you can un-zip the EPUB in question, and replace the copy of the relevant HTML file with the original that you imported into Sigil, after which you re-zip etc. This too is an extremely tedious procedure and is a rather technical affair for amateurs to take on.
All of this is, of course, academic, given that link-elements within SVG images do not work in at least some flavours of the Kindle brand, and so the following gives a solution that may work for you:
The trick is to abandon the idea of placing links within the SVG image in question, and to make the image the background of a <div> element instead. You then populate the div with a set of link elements that you give a display property of ‘block’, which will make them expand laterally to fill the div, and to flow down that element. You then use an ID selector for each link to give them font sizes that will cause them to cover the correct (approximately) amount of vertical space.
This takes considerable experimentation in your browser's debugger, and you need to give the links a temporary opacity value of 0.5, which will allow you to see the links and the graphic underneath. Once you have the correct alignment, you then give the links a color value of transparent. When rendered in the final deliverable, the links are present and invisible, but still react correctly to a click or touch.
Sadly, this approach is unreliable because different Kindles calculate text sizes differently, and so while you may get the textual links to sit over the graphics in the right places on an e-ink Kindle, they will be somewhat out of place on a Kindle Fire. This is the problem that precluded the use of the workaround in Chapter Seven, Production.
It is also very inflexible, because it allows clickable image elements along the vertical axis only. You could try applying ‘display :inline-block’ and width rules, which will allow horizontal and vertical link positioning, but you will run into the same ‘registration’ problem mentioned above, now in two dimensions.
In case you are wondering, experimentation with this technique followed a number of other spirited attempts on the part of this author, using other approaches, which consumed considerable time. None of those worked either, each for different reasons.