Positioning SVG elements using CSS

CssSvg

Css Problem Overview


Assume the following svg document:

<svg version="1.1" baseProfile="full" width="300" height="200" xmlns="http://www.w3.org/2000/svg">
<text x="20" y="20">My text</text>
</svg>

Now what i want to do is reposition this text using css.

I have tried adding style="dx:20" and style="transform: translate(20)". Both have no effect in firefox and safari. Adding these as normal attributes works fine but then i can't split the positioning from the actual code. Setting x, y, left and top in the style isn't working either.

Is there a way to position an svg element using css?

Css Solutions


Solution 1 - Css

I've managed to move some SVG text in chrome using the following CSS:

text.identity{
transform: translate(74px,0px);
-ms-transform: translate(74px,0px); /* IE 9 */
-webkit-transform: translate(74px,0px); /* Safari and Chrome */
-o-transform: translate(74px,0px); /* Opera */
-moz-transform: translate(74px,0px); /* Firefox */
}

However, it's not budging in Firefox...

Solution 2 - Css

I came here looking for a fix but fixed the issue myself, thought I would share:

transform: translate(100px, 100px)

Appears to work in all modern browsers except for Internet Explorer, right up until Microsoft Edge (which isn't even out yet) which is quite disappointing. The elements I've tested on are:

<path>
<polygon>
<g>

The only issue I've had is with <text> elements, and the solution there is to wrap the <text> in a <g> and apply the transformation to that. That should also work for any elements I haven't yet tested that have issues with transform: translate().

I haven't found a decent fallback for Internet Explorer, instead I've made sure that the transforms aren't vital to the function of the SVG.

Solution 3 - Css

Here is a hacky possibility to position specifically text-elements purely by CSS, by abusing the attributes ‘letter-spacing’ for the x-coordinate and ‘baseline-shift’ for the y-coordinate:

<defs>
    <font><font-face font-family="cssPosAnchor" />
        <glyph unicode="." horiz-adv-x="0" />
    </font>
    <style type="text/css"><![CDATA[
#cssPos {
    font-family:cssPosAnchor;
    letter-spacing:10px; /* x-coordinate */
}
#cssPos>tspan {
    font-family:serif;
    letter-spacing:normal;
    baseline-shift:-30px; /* negative y-coordinate */
}
]]>
    </style>
</defs>
<text id="cssPos">.<tspan>CSS-Positioned Text!</tspan></text>

‘baseline-shift’ is only applicable on ‘tspan’ Elements, thus making the inner <tspan> necessary in the presented code. Positive values for baseline-shift move the text upwards, opposite of the normal direction in the svg.

‘letter-spacing’ needs an initial letter to have an effect, thus making the . necessary. To eliminate the width of this first letter, we use the special made font cssPosAnchor, where the dot has no width and no shape. The following <tspan> additionally restores font and letter-spacing.

Scope

Should work in every conforming SVG implementation.

There is one indefinite limitation though for negative x-coordinates. The specification for the ‘letter-spacing’ attribute says: “Values may be negative, but there may be implementation-specific limits.”

Compatibility

Text ‘direction’ change should work just fine, when imposed on the inner <tspan>.

A non-standard ‘writing-mode’ must be imposed on the outer <text>. There will most certainly be problems with that.

The probably more important ‘text-anchor’ values middle and end can be made possible like this:

<defs>
    <font><font-face font-family="cssPosAnchor" />
        <glyph unicode="." horiz-adv-x="0" />
        <glyph unicode=" " horiz-adv-x="0" />
    </font>
    <style type="text/css"><![CDATA[
#cssPos {
    font-family:cssPosAnchor;
    letter-spacing:100px; /* x-coordinate */
    word-spacing:-200px; /* negative double x-coordinate */
}
#cssPos>tspan {
    font-family:serif;
    word-spacing:normal;
    letter-spacing:normal;
    baseline-shift:-30px; /* negative y-coordinate */
}
#cssPos {
    text-anchor=middle;
}
]]>
    </style>
</defs>
<text id="cssPos">.<tspan>CSS-Positioned Text!</tspan> .</text>

The ‹space›. before the closing <\text> tag produces spacing equal to minus x-coordinate. So the inner <tspan> is moved around but preserves it's space in the <text> as if it was still there.

Since there may be implementation-specific limits on negative values for the spacing attributes, this is not guaranteed to work on all clients!

Solution 4 - Css

At the moment, it seems -according to http://www.alistapart.com/authors/p/shelleyp">Shelley Powers, in her http://www.alistapart.com/">A List Apart Article "http://www.alistapart.com/articles/using-svg-for-flexible-scalable-and-fun-backgrounds-part-i/">Using SVG for Flexible, Scalable and Fun Backgrounds: Part I" and "http://www.alistapart.com/articles/using-svg-for-flexible-scalable-and-fun-backgrounds-part-ii/">Part II"- that CSS is not currently best-suited to positioning of SVG. In fact it seems to be quite a minefield to incorporate SVG into a web-page, without directly embedding it within the html itself.

I hope that there are solutions to be found, and, indeed, Powers does offer a couple of workarounds, to enable proper separation of style and content for SVG. I'd hazard a guess that the current problems are the relative new-ness of the concept/standard (relative to, for example, .gif or even .png...), sadly.

I'm sorry I can't offer a better answer. =/

Solution 5 - Css

Use css positioning:

index.html

<link href="style.css" rel="stylesheet" />
<div class="parent">
  <div class="child">
    <svg version="1.1" baseProfile="full" width="300" height="200" xmlns="http://www.w3.org/2000/svg"><text x="20" y="20">My text</text>
    </svg>
  </div>
</div>

style.css

.parent {
  position: relative;
  height: 1000; /* bigger than your svg */
  width: 1000; /* bigger than your svg */
}

.child {
  position: absolute;
  top: 10px;  /* relative to parent container */
  left: 10px; /* relative to parent container */
}

Solution 6 - Css

polygon r="7" id="map_points_55" points="23,10 15,27 34,16 10,16 31,27" style="fill:lime;stroke:purple;stroke-width:0;fill-rule:nonzero;"

if you want to move the star then add to 10 or more in points like points="33,20 25,37 44,26 20,26 41,37"

Solution 7 - Css

I warn you i'm a relative beginner but what about "x" and "y" and assigning these with number and "px"

maybe:

left: 290px;	top: 1200px;

or

x:30px; y:50px;

and

text-anchor:start;

Sample:

<text
       xml:space="preserve"
       style="font-size:32;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Comic Sans MS;-inkscape-font-specification:Comic Sans MS Bold"
       x="131.42857"
       y="269.50504"
       id="text2383"
       sodipodi:linespacing="125%"><tspan
         sodipodi:role="line"
         id="tspan2385"
         x="131.42857"
         y="269.50504">Position ze text</tspan></text>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionYorick SijslingView Question on Stackoverflow
Solution 1 - CssplukeView Answer on Stackoverflow
Solution 2 - CssryanpitherView Answer on Stackoverflow
Solution 3 - CssTobias SimonView Answer on Stackoverflow
Solution 4 - CssDavid ThomasView Answer on Stackoverflow
Solution 5 - CssIsaac PakView Answer on Stackoverflow
Solution 6 - Cssbhaveshvirani63View Answer on Stackoverflow
Solution 7 - CssChasbeenView Answer on Stackoverflow