Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

inline svg in html - how to degrade gracefully?

See the code below - I am trying to include inline svg in my website. I am following a neat suggestion to use the svg switch element so that it degrades gracefully on older browsers. The idea is that browsers which support svg use the first element in the switch block; those which don't ignore all the svg tags and just show the img buried in the second element (i.e. the foreignobject tag) of the switch block.

It works really well ... except that my svg (which is sheet music) necessarily includes text elements and they get rendered (as well as the foreignobject) by older browsers.

Ironically it is easy to deal with this in IE8 and below using conditional comments.

For other older browsers I have a javascript work-around inside the foreignobject which redefines the class of the svg text. It works ... but it feels like a real hack.

Is there a better way to do this (better javascript, a css solution, another way of doing the svg text ...)?

Anyway here is the bare bones of the code:

<html>
<head>

<!-- this deals with elements using the svgtext class in old IE browsers -->
<!--[if lte IE 8]>
<style type="text/css">
.svgtext { display: none; }
</style>
<![endif]-->
<style type="text/css">
.donotdisplay { display: none; }
</style>

</head>
<body>

<svg ...>
<switch>
<g>
<!-- the svg goes here -->
<text class="svgtext">this gets rendered unless I deal with it</text>
</g>
<foreignObject ...>
<script type="text/javascript">
window.onload=function(){
  var inputs=document.getElementsByTagName('text');
  for(i=0;i<inputs.length;i++){
    inputs[i].className='donotdisplay';
  }
}
</script>
<!-- the replacement img tag goes here -->
</foreignObject>
</switch>
</svg>

</body>
</html>
like image 617
Chris Walshaw Avatar asked May 06 '12 09:05

Chris Walshaw


1 Answers

Here's an idea for for browsers other than IE8 and earlier (which need the JS based shiv to recognise the text element.) for a CSS-only solution,

<!DOCTYPE html>
<html>
  <head>
    <title>Test Case</title>

<!--[if lte IE 8]>
    <script type="text/javascript">
      document.createElement("text");
    </script>
<![endif]-->

    <style type="text/css">
      @namespace svg "http://www.w3.org/2000/svg";
      text { display: none; }
      svg|text { display: inline; }
    </style>
  </head>
  <body>

    <svg>
      <switch>
        <g>
          <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>
          <text x="20" y="120">this gets rendered unless I deal with it</text>
        </g>
        <foreignObject>
          <p>Use an SVG capable browser</p>
        </foreignObject>
      </switch>
    </svg>

  </body>
</html>

The idea here is that browsers that support SVG inline, do so by putting the SVG elements into the "http://www.w3.org/2000/svg" namespace, which can then be addressed in the css.

Tested in Firefox 12, IE9, Chrome 18 Opera 11.6, which show the SVG, and Firefox 3.6 and Safari 5.0 which show the fall-back.

JSFiddle at http://jsfiddle.net/rGjKs/

like image 76
Alohci Avatar answered Oct 27 '22 17:10

Alohci