Playing around with SVG filters, I ran into an issue with referencing an SVG filter from CSS. In some situations, applying a filter will remove the element to which the filter is applied from the page. I thought that there could be 2 causes:
To test this, I created a MWE that demonstrates the issue. For me, this renders in Firefox and Chrome with nothing in the left box and a gray circle (the expected result) in the right box. This eliminates cause 1, I think. After I did this, I tried:
url(.#filter-id)
, so with a leading dot. This did not change the result.defs
in the same svg
element as where the circle is. This fixes the issue.My question: is it still possible to somehow reference a filter that is defined in a separate SVG element? I would very much prefer to do it that way in my application. I have read that there are problems with external files, but a different element in the same file should surely be possible?
I think the problem is the display:none
in the hidden
class, you can use another way to hidden, this for example:
svg.hidden {
height:0;
margin:0;
border:none;
}
var svg = d3.select('#container').append('svg'),
defs = svg.append('defs'),
dsFilter;
svg.attr('width', 400).attr('height', 200);
dsFilter = defs.append('filter').attr('id', 'grayscale-d3')
dsFilter.append('feColorMatrix')
.attr('type', 'matrix')
.attr('values',
'0.3333 0.3333 0.3333 0 0 ' +
'0.3333 0.3333 0.3333 0 0 ' +
'0.3333 0.3333 0.3333 0 0 ' +
'0 0 0 1 0')
svg.append('text').attr('x', 2).attr('y', 2).text('appended by D3');
svg.append('circle').attr('class', 'd3').attr('cx', 200).attr('cy', 120).attr('r', 60);
body {
margin: 0;
font-size: 0;
}
circle {
fill: #bada55;
stroke: #000;
stroke-width: 1px;
}
circle.of {
filter: url('#grayscale-of');
}
circle.d3 {
filter: url('#grayscale-d3');
}
svg {
display: inline-block;
margin: 1rem 0 0 1rem;
border: 1px solid #000;
}
svg.hidden {
height:0;
margin:0;
border:none;
}
text {
dominant-baseline: text-before-edge;
font-size: 1rem;
}
<script src="https://d3js.org/d3.v3.min.js"></script>
<svg class="hidden">
<defs>
<filter id="grayscale-of">
<feColorMatrix values="0.3333 0.3333 0.3333 0 0
0.3333 0.3333 0.3333 0 0
0.3333 0.3333 0.3333 0 0
0 0 0 1 0"
type="matrix">
</feColorMatrix>
</filter>
</defs>
</svg>
<div id="container">
<svg width="400" height="200">
<text x="2" y="2">already in page</text>
<circle class="of" cx="200" cy="120" r="60" />
</svg>
</div>