Style SVG with CSS only [duplicate] - html

I have an SVG file that I am applying CSS to. Most rules seem to work, but when I apply rules about the rounding of corners (rx:5; ry:5) it has no effect. 'Inline' style rules work, but I'm having no luck with embedded and external style sheets:
<svg ...>
<defs>
<style type="text/css" >
<![CDATA[
rect{ rx:5; ry:5; }
]]>
</style>
</defs>
<rect
height="170" width="70" id="rect7"
x="0" y="0" />
</svg>
Any idea where I am going wrong?

rx and ry are regular attributes rather than presentation attributes. Only presentation attributes can be styled by CSS. The various regular/presentation attributes are listed here
See also Presentation Attribute and Property from the SVG 1.1 specification.
The upcoming SVG 2 specification proposes that most presentation attributes become CSS properties. So far Chrome and Firefox have implemented this part of the draft specification. I imagine other UAs will implement this in due course.

Scripting can't be simpler, why not to use it:
yourRect.setAttributeNS(null, "rx", "5");
yourRect.setAttributeNS(null, "ry", "5");

Related

Firefox A11y Audit with inline SVGs - content with images must be labeled

If I have the following SVG image for example:
<svg role="img" viewbox="0 0 100 50" height="100px">
<title>Site Logo</title>
<rect x="0" y="00" width="100" height="10" fill="red"></rect>
<rect x="0" y="10" width="100" height="10" fill="salmon"></rect>
<rect x="0" y="20" width="100" height="10" fill="pink"></rect>
<rect x="0" y="30" width="100" height="10" fill="aqua"></rect>
<rect x="0" y="40" width="100" height="10" fill="blue"></rect>
</svg>
I should be hitting a11y svg guidelines by setting role=img and including a <title> element
However, when I run the Accessibility Audit in Firefox, it adds a warning for every element/graphic inside the SVG (path, rect, circ) with the following warning:
Content with images must be labeled. Learn more
But surely I don't need to mark up every individual path within the svg?
What should I do to improve a11y or indicate to FF what the correct alt text is?
Here's a demo page in fiddle that will reproduce this issue
I found that including a <title>Image title</title> tag within the <svg role="img"></svg> tags led FireFox to stop showing the error. Note the inclusion of the role attribute on the svg tag (as noted in an earlier comment), along with any other attributes you may need for the opening tag.
According to MDN Web Docs:
The element provides an accessible, short-text description of
any SVG container element or graphics element.
So, like an alt tag for an <img> element. It sounds like a <desc> tag could be used for additional descriptive information.
I am pretty sure this is a bug, or design flaw in FF's accessibility tool. I have reported it here.
Remember that automated accessibility audits can not catch every issue, and often report false positives. Try installing (e.g.) the WAVE accessibility add-on, which is another automatic accessibility auditor. It makes no such complaint.
w3 says
An img represents a single graphic within a document, whether or not
it is formed by a collection of drawing objects.
So you are right that role="img" on the SVG root should do The Right Thing. The accessibility API will not try to expose the children, but Firefox's current beta version of the accessibility tool obviously does.
I tried your code (wrapped in a bare bones HTML doc) with a screen reader (NVDA) and it didn't try to announce the rects, which is what I would expect. It did announce the accessible name. Actually it announces it twice (which is a known NVDA bug at time of writing).
I also tried putting a <g role="presentation"> element around the contents of the svg, but the accessibility tool still flagged warnings on all the children. This shouldn't be necessary.
So, I think you're good.
Elements with img role have the children presentational property set to true. So rect elements can't have an alternative name.
It's likely due to a bug in this Firefox plugin.
Note that (curiously?) the Accessible Name and Description guidelines state that the name can be:
generated from [...] a host language labeling mechanism, such as the alt or title attribute in HTML, or the desc element in SVG.
So according to this statement you should use the desc element. I'm not sure if it's an error in the documentation as the title element seems to be a more suitable choice.
This might come in late, but it helps all the time.
Since the svg does not have text, including aria-label="descriptive text here" and alt="svg description here" should help with the text label checks.
However, if the svg is just for presentational purpose, using empty alt helps out as well. This is to make screen readers recognise the svg, but will not describe the image (instead they'd just say "image", or similar).

SVG tag <use> doesn't work within polymer component in Firefox

Here is an example: http://miriti.ru/svgtest/
If you'll look at this example in any browser you will see two grey squares with green circles (labled "Symbol") inside. Except for Firefox (I am testing on Firefox 35.0.1 on windows and mac os x).
These SVGs are absolutely identical but the second one is placed inside the polymer component.
Code on GitHub: https://github.com/miriti/svgtest
Any suggestion about what can be the cause of this problem?
I seem to find a workaround for your problem. First of all, wrap your <svg> element with <div id="content">. This is necessary, because later we will reinitialize the inner content of this div.
<template>
<div id="content">
<svg width="400" viewBox="0 0 400 400">
...
</svg>
</div>
</template>
Then in the script section do the following woodoo-magic:
domReady: function() {
this.async(function() {
this.injectBoundHTML(this.$.content.innerHTML, this.$.content);
}, this);
}
Please don’t complain about the weirdness of this trick :)
You are done: FF is satisfied now.
Using SVG sprites I ran into issues that are similar to the one you describe but not the same. So what I propose is not exactly a solution to your problem, however you could avoid such issues altogether by using iron-iconset-svg (https://elements.polymer-project.org/elements/iron-icons?active=iron-iconset-svg), which in my opinion provides a cleaner/easier solution. Its simply a wrapper for your SVG sprite sheet, so you define your icons almost the same way and use them with iron-icon.
Defining a custom iconset (put it directly into the page or wrap it inside an element + set a name that describes the icons, here: 'your-iconset-name')
<iron-iconset-svg name="your-iconset-name" size="24">
<svg>
<defs>
<g id="your-icon-name">
<rect x="12" y="0" width="12" height="24" />
<circle cx="12" cy="12" r="12" />
</g>
</defs>
</svg>
</iron-iconset-svg>
If you wrap them, lets say in 'your-custom-iconset', you can include the iconset like this:
<your-custom-iconset></your-custom-iconset>
Using icons
When you need an icon you just include iron-icons (https://elements.polymer-project.org/elements/iron-icons) and place it like this:
<iron-icon icon="your-iconset-name:your-icon-name"></iron-icon>
You can then give it a class to apply styling and don't need to use 'fill' for its color, just use 'color'.
I fixed it in Polymer 1.0 like this:
attached: function () {
//Fix "svg-use" in Firefox!! -> Properly bad for Performance (Issue: https://github.com/Polymer/polymer/issues/1182)
this.async(function () {
this.$.content.innerHTML = this.$.content.innerHTML;
}, this);
}
but I don't use Bindings in my component (yet)

Best practice for using SVG images?

My research came up with a several ways to insert SVG images inside an html page.
Using <img> is the most simple one but lack of ability as coloring the icons, which is my main need. So, I've read about using <object> but this still doesn't let me styling it using css fill command.
Putting the bulk of <svg> data is also non acceptable since I want to use the images as a refernced images.
I've also read about jQuery solution but I use angularJS.
So, I've read a lot about the ability of SVG Icons, and how better they are rather than the old PNG-Sprite or the IconFonts hype. but unfortunatelly, I cant find any good reference for using it. Can anyone help me here?
tried this already, this doesn't work:
html:
<object data="your.svg" type="image/svg+xml" id="myImage"></object>
css:
#myImage {
fill: #fff;
}
For <img> manupulation, read How to change color of SVG image using CSS (jQuery SVG image replacement)?
For embedding you have 3 choices:-
<object id="myObj" data="image.svg" width="200px" height="200px" type="image/svg+xml"></object>
<embed id="myEmb" src="image.svg" type="image/svg+xml" width="200px" height="200px" ></embed>
<iframe id="myIfr" src="image.svg" width="200" height="200" style="border:0" ></iframe>
Say the image.svg contains this circle in red: <circle id="redcircle" cx="100" cy="100" r="50" fill="transparent" stroke="red" stroke-width="3""/>
To manipulate this color, try this function: ColObj('myObj','blue'), ColObj('myEmb','blue') or ColObj('myIfr','blue')
function getSubDocument(embedding_element)
{
if (embedding_element.contentDocument)
{
return embedding_element.contentDocument;
}
else
{
var subdoc = null;
try {
subdoc = embedding_element.getSVGDocument();
} catch(e) {}
return subdoc;
}
}
function ColObj(elem, color)
{
var elms = document.getElementById(elem);
var subdoc = getSubDocument(elms);
if (subdoc)
subdoc.getElementById("redcircle").setAttribute("stroke", color);
}
This guide from CSS tricks is the best reference I've found so far.
Your options are, unfortunately, pretty limited to use CSS to style an SVG that's not inlined. It involves either embedding the styles inside the SVG file or linking to the stylesheet from within the SVG itself.
Both techniques are discussed in the CSS tricks guide.
Here's a JSFiddle demonstrating the linked CSS technique.
Here's how it works:
Link to the stylesheet from within the CSS and add classes to the individual paths:
<?xml-stylesheet type="text/css" href="mysvg.css"?>
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48">
<path class="demo-content" d="M11.31 44.5l12.69-12.3 12.691 12.3 7.809-8.2-12.69-12.3 12.69-12.3-7.809-8.2-12.691 12.3-12.69-12.3-7.81 8.2 12.691 12.3-12.691 12.3 7.81 8.2z" fill="rgb(98.34%, 88.24%, 32.2%)"/>
<path class="demo-border" d="M11.31 44.5l12.69-12.3 12.691 12.3 7.809-8.2-12.69-12.3 12.69-12.3-7.809-8.2-12.691 12.3-12.69-12.3-7.81 8.2 12.691 12.3-12.691 12.3 7.81 8.2z" stroke="#ccc" stroke-linecap="square" fill="none"/>
</svg>
Create the css file, in this case mysvg.css:
.demo-content {
fill: #FF0000;
}
If you're trying to conditionally style the SVG, though, you may have no chose other than embed it.

Unexpected behaviour of <use> in svg

I stumbled upon a problem.
I am using Chrome 34.0.1847.116 m - latest verstion.
The <use> seems to work OK on <circle> but not on <foreignObject> tag.
<svg height="400" width="400">
<foreignObject id="first" x="120" y="120" width="180" height="180">
<div xmlns="http://www.w3.org/1999/xhtml" style="height: 800px">
<ul>
<li><strong>First</strong> item</li>
<li>
<em>Second</em> item
</li>
<li>Thrid item</li>
</ul>
</div>
</foreignObject>
<!--<circle id="first" cx="150" cy="50" r="100" fill="lime" />-->
<polygon id="second" class="poly-in" points="300,200 200,300 100,200 200,0" style="fill:blue;stroke:purple;stroke-width:1" />
<use id="use-first" xlink:href="#first" href="#first" />
Sorry, your browser does not support inline SVG.
</svg>
This doesn't work (bug) ...
But, I can get <use> to work when referencing a <circle>
And, I can get <foreignObject> to work when not referenced by a <use>
I am very confused and don't know if I am misunderstanding something or is it a bug. I've been reading w3c paper on SVG and cannot figure it out.
I am looking identical behaviour than in example 2 but for the code posted here with <foreignObject>.
The "unexpected behaviour" is actually an expected -- if not very well documented -- limitation of the <use> element.
The W3 specs you linked to only allow to reference , or a graphics element -- a <foreignObject> tag is not a valid reference for <use>.
You could technically get around the specs by referencing a <g> or <svg> tag which then contains the <foreignObject> as a child. However, most browsers don't support foreign objects in a <use> element however it is worded.
Although your example of a bulleted list is harmless, there would be serious implementation difficulties from supporting arbitrary copies of any and all HTML, especially when you factor in the way style properties are supposed to be inherited from the <use> element. See this thread on the W3 SVG mailing list for more discussion (use the "next in thread" link to read all the responses).
Browsers currently have enough problems with interactive graphics properties and <use> elements, I would not expect to see an extension of <use> to foreign objects any time soon (although hopefully SVG2 will have clearer language indicating that it isn't possible).
Working around the issue will really depend on the specifics of what you're trying to do. #gilly3 made some suggestions. You may need to resort to Javascript if you want to copy a large chunk of HTML for use in multiple contexts.
If you wrap your <foreignObject> in a <switch> and add a corresponding fallback element (such as <text>) you can reference the <switch> from the <use> and the fallback element will display. Obviously, this is less than ideal. And it doesn't work in FireFox or IE.
http://jsfiddle.net/Uz6XZ/4/
As an alternative, if your goal is just to bring the <foreignObject> to the front, I've found you can do so by specifying position: relative on the <div>. That's a bit of a hack and only works in Chrome, not FireFox or IE.
http://jsfiddle.net/Uz6XZ/3/

How to hide SVG tag from IE8

I have HTML page where I render SVG and all works fine in modern browsers and IE9+. IE8 however doesn't display svg and all I see is empty box. I'm trying to make IE8 and older browsers not to render it at all but all attempts at usual display: none;, width: 0 etc failed. I tried to hide it via JS call but nothing seems to work. If I change width/height directly in HTML it seems to work though. My SVG part is below, if anyone could give me an idea how to get IE not to display this SVG tag that would be great.
<div class="slide panel">
<svg width="1000" height="500">
<mask width="1000" height="500" maskUnits="userSpaceOnUse" maskContentUnits="userSpaceOnUse" id="m1">
<circle cx="200" cy="200" r="200" fill="white" />
</mask>
<image preserveAspectRatio="xMidYMid slice" mask="url(#m1)" xlink:href="<?php echo get_template_directory_uri(); ?>/images/banner1.jpg" width="1000" height="500" class="target"/>
</svg>
<!-- the rest of HTML code -->
EDIT: this is wordpress site so an option would be detecting what browser made request in php and returning different HTML for IE8 only. Is this reliable solution though? How usually is it done?
EDIT2: Found solution.. I ended up wrapping svg in another div and setting it to display: none; for IE8 only, changing size via JS, css etc didnt work at all on SVG tag itself.. God, I hate IE :/
You don't have to wrap your SVGs into another element. It's sufficient to add proper namespace declarations and target those, like:
[xmlns="http://www.w3.org/2000/svg"] {
display: none;
}
You could also use modernizr, a custom test or a simple html tag switch with conditional comments to add the classes inlinesvg and no-inlinesvg (or something similar), respectively, to the HTML tag:
.no-inlinesvg [xmlns="http://www.w3.org/2000/svg"] {
display: none;
}
Hope this helps!
I would not hide SVG, instead use this little hack that gets the job done.
<img src="image.svg" onerror="this.onerror=null; this.src='image.png'">
Additional Info
Late answer here, but in my testing, Josh C's solution won't work, presumably because since IE8 doesn't know what an <svg> is, it isn't able to apply styles to it.
What worked in my case was to wrap the <svg> in a <div id="svgWrapper">. Then a modification of Josh's solution works quite nicely:
<!--[if lte IE 8]>
<style type="text/css">
#svgWrapper { display: none; }
</style>
<![endif]-->
In my particular case, I was already adding an outer wrapper class in the case of IE, so all I needed was a new style targeting .ie8 #svgWrapper and it seemed to test well.
EDIT: I need to learn to read better. Clearly the OP reached the same conclusion and answer was totally unnecessary.