Open stramel opened 4 weeks ago
thanks, for hard working and supporting \
Can you explain how you are implementing the <use>
behavior? Does the user need to author their SVG to be a sprite, and you detect that and use <use>
Or it is a configuration to enable that, or a prop, or?
If a developer removes an SVG element from the DOM (using client-side JS) that holds the symbols (I.e. the source), will that break other SVGs on the page using that symbol?
If a developer removes an SVG element from the DOM (using client-side JS) that holds the symbols (I.e. the source), will that break other SVGs on the page using that symbol?
Yes, that will break the rest of the SVGs using that symbol. This is one of the nuances to using this sprite setup. Another option would be to put all the symbols into a single SVG that could be placed on the page (perhaps in a layout for simplicity). This would avoid that nuance but would complicate things in the future from a lazy loading perspective, generating the build, and would a slightly more code (though this is probably negligible)
Can you explain how you are implementing the
<use>
behavior? Does the user need to author their SVG to be a sprite, and you detect that and use<use>
Or it is a configuration to enable that, or a prop, or?
The user doesn't need to author the SVG in any certain way for it to be used as a sprite.
The sprite behavior is:
<svg>
element<svg>
element<symbol>
element with the viewBox
attribute and the unique id<use>
element with an xlink:href
attribute that references the unique id (this is the link between the symbol and use)<svg>
element that applies the attributes and additional props on it<symbol>
and <use>
elements as children to the new <svg>
elementAll future SVGs will not create and add the <symbol>
element leaving only the <use>
element which references the original definition.
If a developer removes an SVG element from the DOM (using client-side JS) that holds the symbols (I.e. the source), will that break other SVGs on the page using that symbol?
Yes, that will break the rest of the SVGs using that symbol. This is one of the nuances to using this sprite setup. Another option would be to put all the symbols into a single SVG that could be placed on the page (perhaps in a layout for simplicity). This would avoid that nuance but would complicate things in the future from a lazy loading perspective, generating the build, and would a slightly more code (though this is probably negligible)
I can imagine this will present some difficult support scenarios, especially if adding a framework-specific way on top of this is a future goal as you've mentioned in the original RFC.
Would there be any downside to having a separate SVG defining the symbol
s on the page without that specific element being responsible for rendering anything itself (i.e. only holding the symbol
s, not displaying them)?
Thinking outside the box a bit here, I could imagine a setup like this:
symbol
or use
injected. symbol
and use
setup by importing a special component and putting it in their page:
---
import { SvgSymbol } from 'astro:assets' // naming tbd
import Logo from '../assets/logo.svg';
import Layout from './layouts/BaseLayout.astro'
---
With the above case, a user is specifically opting-in to the sprite behavior and it is clear where it is used. My mind is thinking a bit on how View Transitions were implemented: https://docs.astro.build/en/guides/view-transitions/#adding-view-transitions-to-a-page
There are more gotchas when using Sprites which is why we should make that opt-in rather than the default. Even with using a Sprite component to hold the aggregate of SVGs on the page.
Would there be any downside to having a separate SVG defining the symbols on the page without that specific element being responsible for rendering anything itself (i.e. only holding the symbols, not displaying them)?
As I was mentioning previously, this does complicate the implementation, could prove hard for SSR lazy-loading later, and very slight increase in code size.
That being said, I think it might be worth it for the trade-off for avoiding an edge-case on the Sprite usage and possible improvement for framework usage.
Would love @natemoo-re's thoughts on it.
Just wanted to say that doing this:
---
import ThumbIcon from '../assets/icons/ui/thumbs-up.svg?raw';
---
<Fragment set:html={ThumbIcon} />
Has been pretty great for me. I like the idea of "it just works" rather than having to find this in the docs. But I'd rather not overcomplicate things if it creates problems elsewhere.
A QoL thing: It'd be nice if I can style the svg without having to use a global
modifier, if I import it within the component.
A QoL thing: It'd be nice if I can style the svg without having to use a
global
modifier, if I import it within the component.
I'm not quite sure I'm following. Can you provide an example or for details?
I'm not quite sure I'm following. Can you provide an example or for details?
Yes!
---
import RandomSVG from ".@src/imgs/duck_icon.svg";
---
<RandomSVG />
<style>
svg { /* This would target the svg element that this results in. */ }
</style>
I'm not quite sure I'm following. Can you provide an example or for details?
Yes!
--- import RandomSVG from ".@src/imgs/duck_icon.svg"; --- <RandomSVG /> <style> svg { /* This would target the svg element that this results in. */ } </style>
I'm not sure there is much we can do about that. The styling is primarily leaning on the feature-set of Astro. You could use the style
/class
attributes.
Summary
This RFC proposes adding native support for importing and rendering
.svg
files as Astro components, with optimized rendering techniques to minimize performance impact. It aims to allow.svg
files to be treated as components that accept props and be optimized for repeated use on a page using<symbol>
and<use>
elements.An SVG can be imported directly into an Astro component and used as a component that will only embed itself once.
Results in:
Links