score:4

Accepted answer

The <br> tag you're using doesn't have a meaning in SVG -- the fact that Chrome is interpreting it the way you want is in violation of the standard. To get multiline text in SVG, you have basically two options:

  • Use multiple text or tspan elements.
  • Use foreignObject to embed HTML and use e.g. <br> there.

Some more information and pointers in this question.

Edit: These options do not apply to the title element (thanks to AmeliaBR for pointing it out).

score:5

The SVG <title> element is treated inconsistently between browsers, because of the fact that it has a similar function but different rules compared with the HTML title attribute. Browsers seem to selectively choose which HTML rules they apply to the SVG and how.

The SVG <title> element specs indicate:

  • The title is primarily for accessibility purposes.

  • Browsers may display the title as a tooltip.

  • The top-level title in a stand-alone SVG document must be displayed, however (usually in the title bar, same as an HTML <title> element).

  • The title may contain content from other namespaces, with proper XML namespace attributes, but there is no indication of how these should be rendered when creating tooltips.

  • Any content not in another namespace should presumably be subject to the general SVG whitespace-handling rules, which require newlines to be ignored.

The HTML title attribute specs indicate that:

  • The title represents additional "advisory information" about the element.

  • Browsers must make the title information available to users, preferably in a device-independent manner (although most only show it on hover).

  • Linebreaks within the attribute must be respected when displaying the tooltip.

  • No other markup is allowed (because it is an attribute, not HTML code).

But...

Browser makers re-use the code for displaying HTML tooltips to display the SVG tooltips, and so things get confusing.

Follow along with this fiddle (remembering that this applies to inline SVG in an HTML document): http://fiddle.jshell.net/5npxba9L/6/

  • Hard line breaks and extra whitespace within an SVG <title>:

    • are preserved in Chrome 36, Opera 24 and Firefox 31 (i.e., the HTML attribute rules are applied)

    • are ignored in IE 11 (i.e., the SVG whitespace rules are applied)

  • Markup <br/> elements within an SVG <title>:

    • are stripped from the tooltip in Firefox 31

    • are displayed as linebreaks in Chrome 36, Opera 24 and IE 11

    • are completely ignored in all browsers when XML namespace prefixes are used (this might work differently in an XHTML document)

  • Other markup elements within an SVG <title>, such as SVG <tspan> elements:

    • are stripped from the tooltip in Firefox 31 and IE 11

    • are displayed as plain text (i.e. angle brackets printed out) in Chrome and Opera

  • Hard line breaks and extra whitespace are preserved in HTML title attributes, and extra markup is rendered as plain text, in all browsers tested (correctly)

So, the completely hacky and not according to specs way to get a multi-line tooltip in inline SVG, is to use both <br/> tags (un-namespaced or with a change in the default namespace) and hard line breaks within your <title> element:

<svg>
    <circle cx="250" r="50">
        <title><span xmlns="http://www.w3.org/1999/xhtml">Title with <br/>
a line break</span></title>
    </circle>
</svg>

Works in current versions of Chrome, Opera, Firefox and IE (haven't tested in Safari or mobile), although the webkit-based browsers will create an extra blank line.

Be warned, however: you won't be able to create the above markup with the d3 selection.html() method in most browsers, because that function relies on the HTMLElement.innerHTML DOM property, which isn't defined on SVG elements. You'd need to create text nodes and a <br> element separately. The easiest approach is to use a dummy HTML element as a parent, use innerHTML property to create the mixed content, and then append that to the title element:

dot.enter().append("circle")
      .attr("class", "dot")
      .attr("r", "50")
      .attr("cx", function(d,i){return i*100 + 50;})
  .append("title")
  .append(function(d, i){
      //when the parameter to `append()` is a function
      //it will be run for each element in the active selection
      //(in this case, the title elements)
      //and must return the actual element node to append.

      var span = document.createElement("span");
      span.innerHTML = "This is element <br/>\n #" + i;
      //the \n will be converted in Javascript to a line break
      return span;
  });

http://fiddle.jshell.net/cLLsgdmk/

That's all mostly a curiosity. If you want a more reliable solution, follow Lars' answer for a link to how to create a <foreignObject> tooltip, or check out this Codepen demo for information about how to use Javascript to overlay an absolutely positioned <div> on top of your SVG.


Related Query

More Query from same tag