232

I want to display some text inside SVG rect. Is it possible?

I tried

<svg xmlns="http://www.w3.org/2000/svg">
  <g>
    <rect x="0" y="0" width="100" height="100" fill="red">
      <text x="0" y="10" font-family="Verdana" font-size="55" fill="blue"> Hello </text>
    </rect>
  </g>
</svg>

But it does not work.

peterh
  • 11,875
  • 18
  • 85
  • 108
Jakub M.
  • 32,471
  • 48
  • 110
  • 179
  • 5
    possible duplicate of [insert text between a rectangle drawn in svg.](http://stackoverflow.com/questions/5449899/insert-text-between-a-rectangle-drawn-in-svg) – Jonas Jul 17 '11 at 19:25
  • Does this answer your question? [Insert text between a rectangle drawn in SVG](https://stackoverflow.com/questions/5449899/insert-text-between-a-rectangle-drawn-in-svg) – Stephan Weinhold Dec 28 '20 at 18:19

5 Answers5

325

This is not possible. If you want to display text inside a rect element you should put them both in a group with the text element coming after the rect element ( so it appears on top ).

<svg xmlns="http://www.w3.org/2000/svg">
  <g>
    <rect x="0" y="0" width="100" height="100" fill="red"></rect>
    <text x="0" y="50" font-family="Verdana" font-size="35" fill="blue">Hello</text>
  </g>
</svg>
Vereb
  • 14,388
  • 2
  • 28
  • 30
KeatsKelleher
  • 10,015
  • 4
  • 45
  • 52
  • 27
    Is there a way to not have to manually set height and width on the rect? – George Mauer Dec 20 '12 at 17:01
  • Depends on the situation and what you mean by 'manually'. You can script in in JavaScript if you like (see narendra's answer below) – KeatsKelleher Dec 20 '12 at 19:26
  • 9
    Using my html knowledge - which might well not apply here - it seems like the `g` element has an implicit size here and I'd like the rectangle to expand to it's size. – George Mauer Dec 20 '12 at 20:36
  • 3
    The group fits to its content not the other way. I think the elements are still relative to the parent svg. – shuji Jan 27 '16 at 21:03
  • 1
    is the group element important here? – dmo May 31 '17 at 18:07
  • @dmo, No at all. However, it may be useful when we want to do styling or transformation that affects for both rect and text elements as a group. – Lex Soft Aug 04 '19 at 15:06
  • @GeorgeMauer Width and Height can be set to `100%` instead of `100`, which is much better. – mbomb007 Dec 18 '19 at 19:15
  • Great answer, this solution worked in my case as well. Thank you! Also, I did specify a group as the answer mentions. – Binita Bharati Feb 03 '20 at 10:44
  • I think this is a better case for me - https://codepen.io/techhysahil/pen/POJWpW – Will Aug 25 '22 at 09:54
74

Programmatically using D3:

body = d3.select('body')
svg = body.append('svg').attr('height', 600).attr('width', 200)
rect = svg.append('rect').transition().duration(500).attr('width', 150)
                .attr('height', 100)
                .attr('x', 40)
                .attr('y', 100)
                .style('fill', 'white')
                .attr('stroke', 'black')
text = svg.append('text').text('This is some information about whatever')
                .attr('x', 50)
                .attr('y', 150)
                .attr('fill', 'black')
Jared Forsyth
  • 12,808
  • 7
  • 45
  • 54
  • 14
    This produces markup that *displays* like OP wants, but it doesn't do what OP is trying to do (which isn't legal). This still produces ``. – Joshua Taylor Sep 22 '15 at 01:42
  • 14
    Javascript != SVG. The question is tagged with svg, text and rect. Nothing indicates that the user has access to a programming language. (Making this remark since I came here looking for a static solution.) – aioobe Feb 04 '18 at 20:22
  • 10
    While its true this doesn't pertain to the question me and apparently many other people came here for D3 – cosmichero2025 May 18 '18 at 19:11
  • 1
    Is it possible to autofit the rect to the width of the text – Colin D Apr 08 '19 at 11:57
  • 1
    @Colin D That's what I am looking for too. But It looks impossible to expect it done automatically. Instead, we have to do so manually by ourselves to achieve that. It will need some measurements of dimension (width and/or height) of both elements (rect and text). – Lex Soft Aug 04 '19 at 14:53
31

You can use foreignobject for more control and placing rich HTML content over rect or circle

    <svg width="250" height="250" xmlns="http://www.w3.org/2000/svg">
        <rect x="0" y="0" width="250" height="250" fill="aquamarine" />
        <foreignobject x="0" y="0" width="250" height="250">
            <body xmlns="http://www.w3.org/1999/xhtml">
                <div>Here is a long text that runs more than one line and works as a paragraph</div>
                <br />
                <div>This is <u>UNDER LINE</u> one</div>
                <br />
                <div>This is <b>BOLD</b> one</div>
                <br />
                <div>This is <i>Italic</i> one</div>
            </body>
        </foreignobject>
    </svg>

enter image description here

Carson
  • 6,105
  • 2
  • 37
  • 45
e03050
  • 1,392
  • 15
  • 12
  • 2
    Unlike the `text`-tags-only option, this one actually placed the text inside the path instead of hiding it in some invisible space above it! The `x` and `y` attributes weren't necessary for me but the `width` and `height` were or it also was nowhere to be seen! – Matt Arnold Jan 31 '20 at 16:46
  • 2
    This is a fantastic answer. Only drawback is that IE11 doesn't support foreignObject; but support for this browser is going away, so this might not be an issue. It is way simpler than using a bunch of tspan. – Melanie Oct 01 '20 at 20:44
  • 2
    Dont use foreignObject, its not supported properly, and likely never will be with browsers like Safari. It has bugs since a decade back https://bugs.webkit.org/show_bug.cgi?id=23113 – umbriel Apr 04 '22 at 10:24
6
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
    <g>
  <defs>
    <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%" style="stop-color:rgb(145,200,103);stop-opacity:1" />
      <stop offset="100%" style="stop-color:rgb(132,168,86);stop-opacity:1" />
    </linearGradient>
  </defs>
  <rect width="220" height="30" class="GradientBorder" fill="url(#grad1)" />
  <text x="60" y="20" font-family="Calibri" font-size="20" fill="white" >My Code , Your Achivement....... </text>
  </g>
</svg> 
3

Programmatically display text over rect using basic Javascript

 var svg = document.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'svg')[0];

        var text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
        text.setAttribute('x', 20);
        text.setAttribute('y', 50);
        text.setAttribute('width', 500);
        text.style.fill = 'red';
        text.style.fontFamily = 'Verdana';
        text.style.fontSize = '35';
        text.innerHTML = "Some text line";

        svg.appendChild(text);

        var text2 = document.createElementNS('http://www.w3.org/2000/svg', 'text');
        text2.setAttribute('x', 20);
        text2.setAttribute('y', 100);
        text2.setAttribute('width', 500);
        text2.style.fill = 'green';
        text2.style.fontFamily = 'Calibri';
        text2.style.fontSize = '35';
        text2.style.fontStyle = 'italic';
        text2.innerHTML = "Some italic line";

       
        svg.appendChild(text2);

        var text3 = document.createElementNS('http://www.w3.org/2000/svg', 'text');
        text3.setAttribute('x', 20);
        text3.setAttribute('y', 150);
        text3.setAttribute('width', 500);
        text3.style.fill = 'green';
        text3.style.fontFamily = 'Calibri';
        text3.style.fontSize = '35';
        text3.style.fontWeight = 700;
        text3.innerHTML = "Some bold line";

       
        svg.appendChild(text3);
    <svg width="510" height="250" xmlns="http://www.w3.org/2000/svg">
        <rect x="0" y="0" width="510" height="250" fill="aquamarine" />
    </svg>

enter image description here

e03050
  • 1,392
  • 15
  • 12