I'm trying to understand <text>
positioning in an svg.
Say you have <svg viewBox="..."><text>...</text></svg>
, where the viewBox is correctly sized to fit the text given its (known) font, font weight, and font size. Without giving the <text>
an x="..." y="..."
translation, it won't be positioned "correctly" in the viewBox: it will be too high, and a little to the right.
Can I calculate those x
and y
translation values? That could be without analyzing the drawn <text>
if it the translation isn't dependent on the font's characteristics, or analyzing the drawn <text>
if it does depend on the font's characteristics.
Here's an example (also a jsfiddle: https://jsfiddle.net/enry/Lnzxx0jx/). This was exported from Sketch — that's why I don't have access to the calculation that went into the x and y translations. The <svg>
is the thing with the red outline. The thing to notice is that these specific x and y translation values are needed to position the text in the viewBox in such a way that if the <svg>
's overflow is hidden the entirety of the <text>
is visible.
text {
fill: #000;
fill-rule: evenodd;
font-weight: 700;
font-family: Helvetica-Bold, Helvetica;
font-size: 36px
}
/* just for demo purposes */
html {
padding: 20px;
background: #ccc
}
svg {
outline: 1px solid red;
background: #fff;
overflow: hidden /* in case you want to play around with the translation */
}
translated
<svg viewBox="0 0 258 34" xmlns="http://www.w3.org/2000/svg">
<text x="-2" y="26"><!-- << the question:
if these values weren't provided,
how would you calculate them? -->
my sample text
</text>
</svg>
not translated
<svg viewBox="0 0 258 34" xmlns="http://www.w3.org/2000/svg">
<text><!-- fwiw, the getBBox of the text without translation is
somewhere around -33 - -34, depending on the svg's actual size-->
my sample text
</text>
</svg>
So why are the translation values x="-2" and y="26"? I've tried various percentages of the viewBox dimensions; various percentages of font-size; and fractions relating the viewBox to the font-size… but can't figure it out.
They could be dependent on the kerning and leading — the space around the letters. In that case I suppose we can't know the necessary translation until after draw, at which point maybe the space around the characters could be measured with js/jquery? If so, how would this be done (I don't have any experience using a script to analyze printed characters). Fwiw (this was brought up in the discussion), the untranslated text's getBBox is x:0, y:-[something very nearly 34, depending on the svg's actual size] — so, y is very nearly -(viewBox y). Because getBBox doesn't need the svg to have a viewBox, this could be used to determine the viewBox y dynamically… but it doesn't seem to help with the translation calculation.
Or is it some calculation based on the viewBox? In my experiments, the translation values are dependent on font and font-size… but then so is the viewBox, so maybe the viewBox dimensions are all we need in order to calculate the translations.
My guess: The kerning makes sense for the x translation - I can imagine svg getting tripped up by leading whitespace, and that would explain why it has to be pulled to the left a little. Part of the y translation is moving the baseline down to the bottom of the viewBox, but given the fact that x has to be translated I expect y is baseline plus some adjustment… and that calls for calculating both the adjustment (maybe leading?) and the text height (cap height + potentially an ascender height + potentially a descender height - ["typeface anatomy" illustration])