Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to align a text vertically using SVG with cross-browser compatibility?

Mind the following snippet:

<svg style="" width="60" height="60">
    <rect 
        x            = "0"
        y            = "0"
        rx           = "1"
        ry           = "1"
        width        = "17"
        height       = "15"
        fill         = "rgb(254,199,186)"
        stroke       = "rgb(152,119,111)"
        stroke-width = "1">
    </rect>
    <text 
        x                  = "8"
        y                  = "8"
        fill               = "rgb(50,39,37)"
        font-size          = "16"
        font-family        = "monospace"
        alignment-baseline = "middle"
        text-anchor        = "middle">
        a
    </text>
</svg>

Chrome renders that snippet as:

chrome

Whereas on FireFox, this is the result:

firefox

How can I replicate this snippet in a cross-browser compatible manner?

like image 942
MaiaVictor Avatar asked Dec 15 '22 13:12

MaiaVictor


2 Answers

The "alignment-baseline" is not supported by Firefox. Try to use the attribute "dominant-baseline", it should work for both (Chrome & Firefox but not for IE, see below).

Look at this old answer

According to SVG spec, alignment-baseline only applies to "tspan", "textPath", "tref" and "altGlyph". My understanding is that it is used to offset those from the "text" object above them. I think what you are looking for is dominant-baseline.

It works for Chrome and Firefox but not for IE. If you also want to have a vertical-centered text in IE you have to use a work-arournd like this:

<svg style="" width="60" height="60">
<rect 
    x            = "0"
    y            = "0"
    rx           = "1"
    ry           = "1"
    width        = "17"
    height       = "15"
    fill         = "rgb(254,199,186)"
    stroke       = "rgb(152,119,111)"
    stroke-width = "1">
</rect>
<text 
    id                 = "default-text"
    x                  = "8"
    y                  = "8"
    fill               = "rgb(50,39,37)"
    font-size          = "16"
    font-family        = "monospace"
    alignment-baseline = "middle"
    dominant-baseline  = "middle"
    text-anchor        = "middle">
    a
</text><script>
    window.onload = function() {
        var text = document.getElementById("default-text"),
            bbox = text.getBBox(),
            actualHeight = (4 - bbox.y),
            fontSize = parseInt(window.getComputedStyle(text)["fontSize"]),
            offsetY = (actualHeight / 2) - (bbox.height - fontSize);

        text.setAttribute("transform", "translate(0, " + offsetY + ")");
    }
</script>

like image 105
Simone Pessotto Avatar answered Dec 17 '22 02:12

Simone Pessotto


The simplest cross-browser solution is just to use the dy attribute with an em value.

As long as the font is the same (it would be better to choose a specific font rather than a generic one like "monospace"), this trick should work for any font size.

<svg style="" width="60" height="60">
    <rect 
        x            = "0"
        y            = "0"
        rx           = "1"
        ry           = "1"
        width        = "17"
        height       = "15"
        fill         = "rgb(254,199,186)"
        stroke       = "rgb(152,119,111)"
        stroke-width = "1">
    </rect>
    <text 
        x                  = "8"
        y                  = "8"
        fill               = "rgb(50,39,37)"
        font-size          = "16"
        font-family        = "monospace"
        text-anchor        = "middle"
        dy                 = "0.25em">
        a
    </text>
</svg>
like image 36
Paul LeBeau Avatar answered Dec 17 '22 03:12

Paul LeBeau