Skip to content

Commit

Permalink
Override fill and stroke styles on descendants
Browse files Browse the repository at this point in the history
I incorrectly assumed the style element would override style attributes on descendants. This changes the specificity to the svg element and all descendents. It appears the scope of the style element is limited to the SVG and does not affect other SVGs.

Additionally, the !important property force overrides any style attributes in descendant elements. It is still possible that an element may have a style attribute with !important that we can not override. Hopefully that is a rare case though.
  • Loading branch information
nickpeihl committed Apr 5, 2022
1 parent 526d01e commit 8cb8a11
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 29 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export class SymbolIcon extends Component<Props, State> {
async _loadSymbol() {
let imgDataUrl;
try {
const styledSvg = await styleSvg(this.props.svg, this.props.symbolId, this.props.fill, this.props.stroke);
const styledSvg = await styleSvg(this.props.svg, this.props.fill, this.props.stroke);
imgDataUrl = buildSrcUrl(styledSvg);
} catch (error) {
// ignore failures - component will just not display an icon
Expand Down
16 changes: 9 additions & 7 deletions x-pack/plugins/maps/public/classes/styles/vector/symbol_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,17 @@ export function buildSrcUrl(svgString) {
return domUrl.createObjectURL(svg);
}

export async function styleSvg(svgString, symbolId, fill, stroke) {
export async function styleSvg(svgString, fill, stroke) {
const svgXml = await parseXmlString(svgString);
svgXml.svg.$.id = symbolId;

// Elements nested under svg root may define style attribute
// Wildcard descendent selector provides more specificity to ensure root svg style attribute is applied instead of children style attributes
svgXml.svg.style = `
#${symbolId} * {
${fill ? `fill: ${fill}` : '#000'};
${stroke ? `stroke: ${stroke}` : '#000'};
stroke-width: 1;
vector-effect: non-scaling-stroke;
svg * {
${fill ? `fill: ${fill}` : '#000'} !important;
${stroke ? `stroke: ${stroke}` : '#000'} !important;
stroke-width: 1 !important;
vector-effect: non-scaling-stroke !important;
}
`;
const builder = new xml2js.Builder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,35 @@ describe('styleSvg', () => {
it('Should not add style property when style not provided', async () => {
const unstyledSvgString =
'<svg version="1.1" width="11px" height="11px" viewBox="0 0 11 11"><path/></svg>';
const styledSvg = await styleSvg(unstyledSvgString, 'unstyled-symbol');
const styledSvg = await styleSvg(unstyledSvgString);
expect(styledSvg).toMatchSnapshot();
});

it('Should add fill style property to svg element', async () => {
const unstyledSvgString =
'<svg version="1.1" width="11px" height="11px" viewBox="0 0 11 11"><path/></svg>';
const styledSvg = await styleSvg(unstyledSvgString, 'filled-symbol', 'red');
const styledSvg = await styleSvg(unstyledSvgString, 'red');
expect(styledSvg).toMatchSnapshot();
});

it('Should add stroke and stroke-wdth style properties to svg element', async () => {
const unstyledSvgString =
'<svg version="1.1" width="11px" height="11px" viewBox="0 0 11 11"><path/></svg>';
const styledSvg = await styleSvg(unstyledSvgString, 'filled-stroked-symbol', 'red', 'white');
const styledSvg = await styleSvg(unstyledSvgString, 'red', 'white');
expect(styledSvg).toMatchSnapshot();
});

it('Should override any inherent fill and stroke styles in SVGs', async () => {
const unstyledSvgString = `
<svg version="1.1" id="square-11" xmlns="http://www.w3.org/2000/svg" width="11px" height="11px" viewBox="0 0 11 11">
<g>
<path style="fill: #54B399; stroke: #C57127" d="M9,10H2c-0.5523,0-1-0.4477-1-1V2c0-0.5523,0.4477-1,1-1h7c0.5523,0,1,0.4477,1,1v7C10,9.5523,9.5523,10,9,10z" />
</g>
</svg>
`;

const styledSvg = await styleSvg(unstyledSvgString, 'blue', 'black');
expect(styledSvg).toMatchSnapshot();
})
});

0 comments on commit 8cb8a11

Please sign in to comment.