Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions plugin/src/svg/serialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,18 @@ export function createSymbol(symbolId: string, data: SvgData): LosslessEntry {
* Assembles a complete sprite sheet SVG from an array of `<symbol>` entries.
*
* The sprite is an `<svg>` element with `xmlns` and `xmlns:xlink` attributes,
* hidden via `style="display:none"`, containing all the symbols.
* hidden via `aria-hidden` and `position:absolute;width:0;height:0;overflow:hidden`
* so it occupies no space and is invisible to assistive technology.
* `display:none` is intentionally avoided — Firefox has a bug where `<defs>`
* content such as `<linearGradient>` and `<clipPath>` does not render correctly
* when referenced via `<use>` from a sprite container with `display:none`.
*
* @param symbols Array of `<symbol>` lossless entries (from `createSymbol`).
* @returns The sprite SVG as a string.
*
* @example
* const sprite = assembleSprite([symbol1, symbol2]);
* // → '<svg xmlns="..." style="display:none"><symbol id="a" ...>...</symbol><symbol id="b" ...>...</symbol></svg>'
* // → '<svg xmlns="..." aria-hidden="true" style="position:absolute;width:0;height:0;overflow:hidden"><symbol id="a" ...>...</symbol></svg>'
*/
export function assembleSprite(symbols: LosslessEntry[]): string {
const entries: LosslessEntry[] = [
Expand All @@ -53,7 +57,8 @@ export function assembleSprite(symbols: LosslessEntry[]): string {
$attr: {
xmlns: 'http://www.w3.org/2000/svg',
'xmlns:xlink': 'http://www.w3.org/1999/xlink',
style: 'display:none',
'aria-hidden': 'true',
style: 'position:absolute;width:0;height:0;overflow:hidden',
},
},
...symbols,
Expand Down
2 changes: 1 addition & 1 deletion plugin/test/e2e/vanilla.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ test.describe('Vanilla DOM — embedded sprite (animations page)', () => {
test('animated sprite is inlined in animations.html', () => {
const html = readDistFile('vanilla', 'animations.html');
expect(html).toContain('<svg');
expect(html).toContain('display:none');
expect(html).toContain('position:absolute');
expect(html).toContain('<symbol');
});

Expand Down
6 changes: 4 additions & 2 deletions plugin/test/unit/serialize.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,14 @@ describe('assembleSprite', () => {
expect(sprite).toContain('xmlns:xlink="http://www.w3.org/1999/xlink"');
});

it('hides the sprite with display:none', () => {
it('hides the sprite container without display:none', () => {
const data = parseSvg(readFixture('simple.svg'));
const symbol = createSymbol('abc123', data);
const sprite = assembleSprite([symbol]);

expect(sprite).toContain('style="display:none"');
expect(sprite).toContain('aria-hidden="true"');
expect(sprite).toContain('position:absolute');
expect(sprite).not.toContain('display:none');
});

it('includes multiple symbols', () => {
Expand Down
Loading