25 ms·
SVG Triangle of Compromise
- rawoke083600 2y agoActually there is very important 4th point about implementation (browser) A few years ago a made a Monopoly-Deal-Clone game using mostly SVG + CSS + Svelte. I was intrigued by the promise of SVG: - Loss-Less Scaling - Looks the same (or somewhat) the same on all browsers - Text would also scale and be readable up and down. Build playing cards on the fly with SVG elements dynamically (base-card-svg + text + icon/image/glyph) All of these were never true-enough even for even a card-based game. The SVG text never looked good-enough or readable at all sizes used. Depending on scaling the text/icons and lines got blurred worse. The "fix" for many of these were endless and browser version-dependent magic-css properties and values. TL;DR I wouldn't use SVG for more than 50% of your game or professional product that uses images/visual-elements. Its not worth the pain and effort !
- myfonj 2y agoI went the rabbit hole of exploring SVG "decimal precision-related" glitches in browser implementations and to my grief I must confirm that there really are blatant cross-browser issues. It's fact that my tests went a bit over-the-top with dimensions -- who would make 1e9 or 1e-9 wide viewBox in real world anyway? -- but since refraining from doing so is not discouraged in the specs, one would expect it would scale (pun intended) at least few orders of magnitude. The results for my particular testcase showed that "safe" range was only between 2e3 and 2e5: [1]. https://myfonj.github.io/tst/SVG-decimal-precision-results.html https://myfonj.github.io/tst/SVG-decimal-precision-results.h...
- michaelt 2y ago> who would make 1e9 or 1e-9 wide viewBox in real world anyway? Back in about 2008 I made an SVG diagram showing the height of various satellite orbits above earth, specifying the SVG at 1:1 scale - making the image 84,000 km wide. Sadly a load of file viewers choked on it, so I had to settle for a downscaled version. It seems the 'scalable' in 'scalable vector graphics' only goes so far.
- myfonj 2y agoHa, nice! I secretly hoped someone would mention their real-world usage of "ridiculously" large SVG dimensions, so thanks for the reference! Your story implies there actually were some viewers that could handle it correctly? Could you recall more details what were they? (My testing was pitifully limited to current browsers only, but I know there must be vast amount of other viewers.) And if I may ask, did you map one SVG "point" to some length unit (e.g. meter, so getting 84e6 wide wiewBox), or did you assume 90 DPI "pixel" mapping to ~0.2822 mm?
- codetrotter 2y agoFrom looking at the following pages - https://docs.aspose.com/svg/net/drawing-basics/coordinate-systems-and-units/#svg-viewport https://docs.aspose.com/svg/net/drawing-basics/coordinate-sy... - https://www.w3.org/TR/SVG2/coords.html https://www.w3.org/TR/SVG2/coords.html - https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Positions https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Po... You can use “cm” and “mm” in SVG. It will then be up to the viewer program (web browser or which ever program you are using) to make it correct for the DPI of your display.
- michaelt 2y agoI've just re-tested, and you're right. This SVG won't display properly with chrome, firefox, inkscape or imagemagick <?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg width="84000000000mm" height="84000000000mm" viewBox="0 0 84000000000mm 84000000000mm" version="1.1" id="svg5" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <ellipse style="fill:none;stroke:#000000;stroke-width:0.812697;stroke-opacity:1" id="path111" cx="42000000000mm" cy="42000000000mm" rx="42000000000mm" ry="42000000000mm" /> </svg> However the browsers don't crash or run out of memory, so they've got that going for them. And if you embed the image in a web page with <img src='84km.svg' width=1000 height=1000> chromium almost manages to display it. SVG lets you specify sizes in a bunch of different units, but there's actually a fixed ratio between them - in SVG, 1mm means is 3.78px regardless of your display or printer's DPI. So I didn't scale mm to SVG's arbitrary length units - but the standard did.
- masfuerte 2y agoAlso, browsers seem to render svg circular arcs using bezier curves. At high zoom levels there can be quite a discrepancy between the actual curve (drawn using lots of straight line segments, say) and what the browser renders for a circle.
- myfonj 2y agoDo they? I thought this is more issue on the source code side, rather than implementation: this is actually my pet-peeves, that most SVG *authoring tools* never output circular arcs and always use cubic béziers approximations instead. So we nearly ever see real circles or their segments, even though authors use them in their designs all the time. // Coincidentally played with this test yesterday: https://myfonj.github.io/sandbox.html#%3C!doctype%20html%3E%3Chtml%20lang%3D%22en%22%20style%3D%22color-scheme%3A%20dark%20light%3B%22%3E%0A%3Cmeta%20name%3D%22viewport%22%20content%3D%22width%3Ddevice-width%2C%20initial-scale%3D1%22%3E%0A%3Ctitle%3E%0ACubic%20b%C3%A9zier%20%22circular%20arcs%22%20versus%20real%20circular%20segments%0A%3C%2Ftitle%3E%0A%3Cstyle%3E%0Asvg%20%7B%0A%20position%3A%20fixed%0A%7D%0Asvg%3Alast-child%20%7B%0A%20color%3A%20canvas%0A%7D%0A%3C%2Fstyle%3E%0A%3Cbody%3E%0A%0A%3Cscript%3E%0A%2F%2F%20https%3A%2F%2Fpictogrammers.com%2Flibrary%2Fmdi%2Ficon%2Fcheck-circle%2F%0A%3C%2Fscript%3E%0A%0A%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Ctitle%3Echeck-circle%3C%2Ftitle%3E%3Cpath%20d%3D%22M12%202A10%2010%200%200012%2022%2010%2010%200%200012%202M10%2017%205%2012%206.41%2010.59%2010%2014.17%2017.59%206.58%2019%208Z%22%20fill%3D%22currentcolor%22%20%2F%3E%3C%2Fsvg%3E%0A%0A%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Ctitle%3Echeck-circle%3C%2Ftitle%3E%3Cpath%20d%3D%22M12%202C6.5%202%202%206.5%202%2012S6.5%2022%2012%2022%2022%2017.5%2022%2012%2017.5%202%2012%202M10%20%0A17L5%2012L6.41%2010.59L10%2014.17L17.59%206.58L19%208L10%2017Z%22%20fill%3D%22currentcolor%22%20%2F%3E%3C%2Fsvg%3E%0A https://myfonj.github.io/sandbox.html#%3C!doctype%20html%3E%...
- masfuerte 2y agoIt was a few years ago and I'm unable to reproduce it. Circles and circle approximations from straight lines seem to coincide exactly in Firefox and Edge now. I was generating diagrams using my own code so I'm positive they were circular arcs. Tangents weren't tangent and it took me a while to realise that the problem was the browser rendering something that wasn't quite a circle. I assumed it was a bezier approximation but I didn't verify that. Whatever it was it seems to be fixed.
- myfonj 2y ago(Missed edit:) I even asked about formalized precision SVG limits on SO: https://stackoverflow.com/q/78692079/540955 https://stackoverflow.com/q/78692079/540955
- mort96 2y agoAnother thing I've noticed is that Chrome doesn't seem to render SVGs with anti aliasing (at least not always?). This makes SVGs unsuitable for lots of kiosk-style systems, where you often have Chrome showing a web page on a relatively large low resolution screen.
- HenriTEL 2y agoYou can specify an svg file with the use tag like this: <use xlink:href="/your/icons.svg#whatever"> It pretty much solves the cache issue to me.
- jorams 2y agoThere's an important caveat with this: It does not work cross-origin, and there is no way to make it work except for including some JS like svg4everybody. CORS does not apply.
- HenriTEL 2y agoIt works out of the box with most browsers and like you said there are polyfills for older browsers. BTW the syntax with svg 2.0 is just href. About the cross-origin issue, you mean it lacks something like a crossorigin attribute? That's only an issue if you plan to load svgs from other websites, I don't think it's a very common usecase. If you use them at multiples places in your website, you should probably have them served from your sever anyway, if not then I guess caching is less of an issue.
- spankalee 2y agoSomething like this <html-include> element should be able to hit all three requirements, if you allow for JavaScript: https://www.npmjs.com/package/html-include-element https://www.npmjs.com/package/html-include-element
- oneeyedpigeon 2y agoI think there are lots of solutions if you allow a JavaScript dependency. In the article, the author demonstrates dynamic 'styling' by just swapping out an image - just like we used to do it back in the 20th century! You could fix the caching problem by dumping your SVG contents into localStorage.
- quink 2y agoOr just use any modern DOM-manipulating JavaScript framework like React - in effect putting an `<svg>` tag in very cacheable JavaScript. <div style={...}><p className="...">...</p><svg viewBox="..."><g fill="...">...</g></svg></div>, whichever. It's a first class citizen, put it in a React Component, anything goes. Cacheable, stylable, and dimensional.
- geokon 2y agoAnother option would be to including SVG files from SVG elements, though the whole thing is a bit cursed. I'm not 100% sure how it plays with CSS and caching Example: svg poster - includes svg diagrams - that include svg maps (maps are generated programmatically) https://kxygk.github.io/imergination/ https://kxygk.github.io/imergination/ Though.. if you open the SVG itself (in a separate window/tab) most elements refuse to display for "security" https://raw.githubusercontent.com/wiki/kxygk/imergination/agu2023-poster.svg https://raw.githubusercontent.com/wiki/kxygk/imergination/ag... It's honestly an unreliable format for anything that's mildly complex.. this poster will render differently in different browsers (and inkscape) and can't be turned into a PDF consistently. It's a mess
- akira2501 2y ago> but might waste bandwidth if used for SVGs used often, like a logo or icon. You can put SVGs into a <TEMPLATE>. I've used this for "site and social icons" to great effect.
- genezeta 2y agoIn case the author reads this: I would suggest editing your Venn diagram a bit so that it makes more sense. Something like this <circle class="property stylable" cx="190" cy="145" r="70"></circle> <text class="stylable" x="150" y="140" fill="black">stylable</text> <circle class="property cacheable" cx="310" cy="145" r="70"></circle> <text class="cacheable" x="300" y="140" fill="black">cacheable</text> <circle class="property dimensional" cx="250" cy="260" r="70"></circle> <text class="dimensional" x="210" y="280" fill="black">dimensional</text> This way, the region where your three circles overlap actually disappears, signifying that you can't indeed get all three at the same time.
- LoganDark 2y agoThere's a diagram on this page? Holy shit there is. When my dark theme is enabled, the diagram is black on black. Amazing. (all that's visible is the emoji!)
- Modified3019 2y agoDarkreader does a really good job of preserving visibility in most cases, and is available on both mobile and desktop browsers. Definitely reconnect checking it out.
- LoganDark 2y agoThis is the site's native theme upon seeing that my OS is set to dark (their CSS checks `prefers-color-scheme`). I already use and enjoy Dark Reader.
- mort96 2y agoFor me (Firefox on macOS, also tested with Chrome on macoS), the site's dark theme has a purple background for the diagram which makes it readable even though the background is black. However, the SVG seems to get all its color from CSS; the color is not part of the SVG itself. Maybe that's not working in your browser?
- 2y ago
- ABNW 2y agoReally interesting, am a big fan of the utility that SVG's provide, an undersung hero of the web imo. One thing I've always particularly liked is you can wrap elements inside of an <svg> tag with an <a> tag, useful in the battle against a "square" web!
- chrismorgan 2y agoI’m not confident of what is meant by “stylable”, but I’m pretty sure it’s a misnomer. If you mean applying static styles, you can do that with any form of SVG (that is, <img> qualifies as well). If you mean inheriting styles from the parent document, you can only do that with inline SVG (that is, <iframe> doesn’t qualify). But by the actual usage in the article (that it’s <svg> and <iframe> but not <img>), I think what is actually meant is interactive—that you can run scripts, have :hover styles, links, things like that.
- parasti 2y agoIt's talking about styling properties of SVG elements (e.g. path, circle) via CSS. Not about styling the svg element itself.
- chrismorgan 2y agoIt can’t be that, because you can do that in any SVG document, regardless of technique.
- deleted 2y ago[deleted]
- Lvl999Noob 2y agoIt is actually that. If you are including an svg using <img> then you can no longer, say, change the stroke color. It also does not inherit your css from the rest of your site even on first load. Your svg is treated like any other regular png or such.
- chrismorgan 2y agoPlease review my earlier comment. “Styling properties of SVG elements via CSS” is, on reflection, slightly ambiguous, but largely refers to static styling, which you can do anywhere. If you’re talking about changing things, at runtime, you’re talking about the SVG being interactive, not stylable. And heritability is, as I remarked, another different thing, which doesn’t work for <iframe>, so that can’t be what it’s talking about.
- GeoAtreides 2y agoSeeing that svg is text, enabling gzip compression on server will certainly help with reducing size; especially if using lots of inlined repeating svg elements (like icons, glyphs, etc). I also imagine SPA that compile to one index.js file can massively benefit from inlining svg + server compression (also, very cacheable!)
- vardump 2y agoHe wasn't talking about text, but the rendered image.
- GeoAtreides 2y agoUnless I'm missing something, svg is an xml-based vector image format, being sent by the server as text (xml) and rendered by the user's browser.
- berkes 2y agoSvg can, and often will, include (embed) raster images. But even when not: in practice an SVG will have hundreds or thousands of XML elements (nodes) to draw rather simple-looking shapes even.
- GeoAtreides 2y agoSVG often includes raster images? That's very surprising to me. I can see some use cases here and there, sure, but using a vector format to 'often' include raster images... i dunno. Thousands of XML elements is the ideal case, compresses extremely well.
- squidbeak 2y agoAn example, many of Inkscape's filters depend on raster samples that need to be embedded. Complex gradients are also rasterised.
- 2y ago
- Narhem 2y ago[flagged]
- tannhaeuser 2y agoActually, for interactivity you don't have to use CSS but can also use SMIL animations to set SVG (or CSS) properties for things like clicking/hovering, timed transitions, and even animation sequences. Never understood the CSS march of progress narrative when CSS just piecemeally incorporares concepts (paint servers, filters, etc) SVG had for 20 years now, and what's so great about having those available in CSS" wild unchecked syntax, especially when you'd need (or prefer) JS anyway. SVG at least can be targetted as a reasonable output format by vector drawing tools.
- mrled 2y agoOhh, interesting, I have never heard of SMIL. For this post I was thinking mostly of static styling (... and got a little carried way with interactive stuff in the diagram...) but I'll have to look into SMIL in the future.
- runarberg 2y agoSMIL animations is definitely one of the underrated features of SVG.
- lucideer 2y agoDoesn't the <use/> tag tick all three boxes? (the OP does mention the <use/> tag in the final notes but only for in-document fragment references, not for remote URLs)
- svieira 2y agoThe `<use />` tag introduces another dimension to the analysis: "Is a first-class citizen of the web". Most resources can be included from anywhere and the serving and the hosting pages can limit that universality but the web defaults to "open". SVG's `<use>` is more limited. Cross-site `use` doesn't always work (and there's no way to opt-in to it). `data:` URLs were just removed for some reason (there are mumbles about security but no explanations why this one tag is so much worse for security than say `iframe srcdoc`). All that said, if you're doing an include from the same host as the parent page, yes, `use` absolutely does tick all three boxes!
- Springtime 2y agoFor the particular purpose mentioned in the article another solution is to use CSS' `mask-image`/`-webkit-mask-image` and fragment identifiers in a single SVG that get swapped between hover/regular states. Avoids any inline markup and as a bonus the element color is stylable via the parent page's CSS, albeit one isn't manipulating the inner SVG (though in the OP's case it's a static shape).
- AlienRobot 2y agoAll 3: Javascript. Just load a .svg and put it into a <SVG>.
- baggy_trough 2y agoI like using external svg files for icons because they are tiny and cacheable. I get around the colorization problem by creating different icon files for each color. In practice, I only have a small number of colors to worry about. So: /images/icons/9bac00/door.svg /images/icons/ffffff/door.svg
- OskarS 2y agoIsn't the fundamental issue here not so much anything to do with `<svg>`, but with the fact that you can't easily include HTML snippets from other files in HTML? Like, the only reason not use the <svg> tag seems to be "it's not cached, and it contains a BUNCH of svg, and it has to be loaded with the main HTML page" Can't you say that about anything in HTML? Like, imagine you had a huge `<head>` tag that contained a bunch of stuff, but it's essentially the same (except for, like, the title) for all documents. Don't you wanna do this? <html> <head> <<< include head.html >>> <title>Cool page!</title> </head> <body> <svg> <<< include logo.svg >>> </svg> </body> <html> Where the `<<< include ... >>>` is a pretend bit of HTML that makes the browser fetch that from somewhere else. A preprocessor, more or less. I realize this is what templating languages are for, but if this happened on the HTML layer, the browser could do way better caching.
- panstromek 2y agoYes, I want this and it would solve quite a few issues - particularly lazy loading and SPA-style content swapping could be done with better performance, because html can be easily processed and rendered during download by the browser (unlike the classic AJAX -> Json.parse -> render pipeline, which requires each step to be completed before the next one starts). Lazy loading would also not require JavaScript.
- nbadg 2y agoI think whether or not this makes sense on the client-side is up for debate. Alternatively, though, SVGs in ``<svg>`` elements could just, yknow, retain their stylability. (is there a reason they don't? this has been a long-running frustration of mine)
- cubefox 2y agoYou mean <img>. <img> is not stylable.
- ndriscoll 2y agoHTML does have a preprocessor. It's called XSLT, and it has includes, though they have no deferred fetch. Also, being a preprocessor, you can't interact with it after page load (unless you use a javascript implementation). It's been built into browsers for 20+ years. Still works great, but browsers never supported versions past 1.0 so it shows its age some.
- panstromek 2y agoI like to use sprite files for conditional styling of icons, because using separate file for each state creates a visible delay on state changes, which doesn't look great. You can make them with <defs> and <use> tags pretty easily if you understand svg a bit. I usually bundle two-state icon into a single svg file, and then use `object-position: left/right` property on the <img> tag to switch between the variants. You can also combine this with some simple css animations.
- mrled 2y agoOh man, you're right, I didn't realize they worked this way. This basically means there is no compromise at all, I'm going to update the post. Thanks!
- panstromek 2y agoWell, there's still a compromise to be fair. It's defintely more work to manage these sprites and it's especially annoying when there's more than one state. I think it's possible to write some tool to automate it, but I haven't found one.
- deleted 2y ago[deleted]
- douglee650 2y agoThere are preprocessors that will do this. Conceptually, we would: include sprite-1.snippet include sprite-2.snippet and it would write the defs into the page. Then later in the page, `<use>` the defs you included.
- WhyNotHugo 2y agoAny examples of further material on this? Sounds pretty convenient, but I'm not familiar with <def> or <use> (or `object-position`, for that matter).
- 2y ago
- beardyw 2y agoI can add: In CSS: hold it as a background-image with the SVG in a data URL (requires some encoding). Works for me.
- TheRealPomax 2y agoStill waiting for HTML imports. And that work was discontinued...