return to table of content

SVG Triangle of Compromise

OskarS
26 replies
1d5h

Isn'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.

ndriscoll
11 replies
1d3h

HTML 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.

kbolino
8 replies
22h58m

XSLT is an XML transformation language, but HTML is not XML. Does XSLT work on regular HTML?

kbolino
2 replies
21h50m

As I understand XSLT, it takes an XML document as input and an XML document describing the transformation, and produces an XML document as output.

But most HTML in the wild today is not valid XML. There is XHTML as mentioned by a sibling comment but it's rarely used. So if you were to start with an existing base of HTML documents, you couldn't easily add XSLT preprocessing to them. The issue is with the input rather than the output.

ndriscoll
0 replies
21h36m

If you're using it as a template language for your own pages, you can of course just write it correctly (this is not different than needing to use correct syntax for react code to compile).

If you have someone else's documents, or need to mass convert your own to fix them, there's HTML tidy[0]. This one is quite useful to be able to run XML processing CLI tools on scraped web pages.

But the real power is in delivering XML to the client, not HTML. This lets you work in the domain model directly on the frontend, and use XSLT to transform that into HTML for display. So of course you'd use well-formed XML in that case.

Imagine if you didn't have a distinction between APIs and pages; you just returned the data along with a link to a template that says how to display it and (ideally) a link to a schema definition. Modifying templates for components could be as easy as modifying CSS attributes in the browser console, giving the next generation an easy way to peak and play around with how it all works as they're growing up. We were so close, and then things veered off into the hellworld that is the modern web.

[0] https://github.com/htacg/tidy-html5

nayuki
0 replies
21h43m

The fastest way to confirm that a given HTML document is not valid XML is to change the HTTP Content-Type from "text/html" to "application/xhtml+xml".

Here is what I know about using XHTML in practice: https://www.nayuki.io/page/practical-guide-to-xhtml

LegionMammal978
1 replies
20h29m

XSLT 3.0 can be directed to output HTML5 [0]. However, browsers only implement XSLT 1.0, and as far as I am aware there is no open-source XSLT 3.0 implementation.

Still, it's possible with XSLT 1.0 to produce documents in the common subset of XML and HTML5 ("XHTML5"). It can't produce the usual <!DOCTYPE html> at the top of the document, but it can produce the alternative <!DOCTYPE html SYSTEM "about:legacy-compat">.

On the input side, every XSLT version only accepts valid XML, as far as I am aware.

[0] https://www.w3.org/TR/xslt-xquery-serialization-30/#html-out...

o11c
0 replies
16h44m

`xsltproc --html` is an example of HTML input (probably HTML4 parsing rules though?) if you really need it. This is an XSLT 1.0 processor, wrapping libxslt which most browsers use.

As for output, the difference is largely irrelevant for browser purposes since they just want a tree.

I'm not sure how many extensions the browsers allow, but a major part of the reason XSLT 2/3 failed to take off is because libxslt already provides most of the useful features from newer versions as extensions (many via EXSLT-namespaced modules, at least partially supported in browsers - see MDN); what it doesn't do is implement the unnecessary complexity that the Java world loves.

dspillett
0 replies
19h30m

We were going to move on to XHTML after HTML4, for those variants (did it go beyond XHTML1.1?) HTML is XML compliant. That got caught in slow design-by-committee hell though so HTML5 became the defacto standard instead. There is XHTML5 which is an attempt to direct that back towards compliance, but I've never seen it used in the wild.

dekhn
0 replies
22h38m

At the time HTML was converted from SGML to XML: https://en.wikipedia.org/wiki/XHTML so if you authored XHTML, you could XSLT it. There is also XHTML5, an XML serialization of HTML5. I imagine in the real world there is a great deal of web that is HTML, accepted by browser, but not XML.

dspillett
1 replies
19h34m

> though they have no deferred fetch

Also, at least back when we excised the last bits of it from our old codebase, no useful caching of either stylesheets or included resources (other stylesheets), so if you tried to mix client-side processing with HTTPS you were in for quite some pain unless you had a fast, very low latency, uncongested, link.

ndriscoll
0 replies
18h30m

Currently it looks like at least Firefox and Chromium both cache stylesheets and included files as you'd expect. In fact, you can use this to increase cacheability in general. e.g. when this site is having performance issues, it often works logged out/when serving static versions of pages. It's easy to make every page static by including a `/myuser.xml` document in the xsl template and using that to get the current logged in user/preferences to put on the page. This can then be private cached and the pages themselves can be public cached. You can likewise include an `/item-details.xml?id=xxxx` that could provide data for the page to add the logged in user's comment scores, votes, etc. If the included document fails to fetch, it falls back to being empty, and you get the static page (you could detect this and show a message).

jwells89
3 replies
1d3h

To me at least this feels like a fairly natural addition to HTML. You can already pull in external scripts, stylesheets, images, video, etc, so why not page partials too? A sibling comment mentions XSLT which is cool, but nobody knows about it because it doesn’t follow any patterns set in HTML and HTML doesn’t have any breadcrumbs that might lead someone to discover XSLT. Something like <partial src=“header.html”> flows with expectations much better.

Something I find a bit funny now is that for the longest time back in the 2000s, nearly the entirety of my usage of PHP was comprised of PHP includes to make up for this gap in HTML functionality (I had no idea XSLT existed then).

PaulDavisThe1st
1 replies
21h18m

One reason that this is slightly more complicated than it appears is that you have to decide what ignore when doing the inclusion. Including an image will not override anything specified in the "parent" HTML, but including HTML might result in conflicts. Who wins, who loses, etc. etc.

harry8
0 replies
19h49m

Why isn't it exactly the same as if the doc had the includes filled out and then processed semantically, much like C?

All <<<include whatever.html>>> could be replaced with contents first. Then it's just a page of html as now.

ndriscoll
0 replies
22h55m

It had breadcrumbs back in 2004 (e.g. those neat "valid XHTML 1.1" badges from W3C back when badges on your website were cool, and e.g. W3 Schools actually put it above javascript[0]. XHTML was supposed to be the next big thing). These days it seems that browser vendors just don't like it for whatever reason (tinfoil hat on: because almost all of them benefit from javascript-based spyware, and so prefer a world where even static pages require javascript to be enabled to show anything), and so documentation acts like it is some legacy thing instead of what it is: a perfect fit for the 99% of websites that need some templates and don't have much dynamic interaction.

Other cool web tech that should have "won": XForms[1]. Imagine if HTML forms had things like declarative data-binding (with XPath expressions! Imagine jq built directly into the browser 20 years ago and usable by forms) and types/constraints/validation built right in. This would be 1000x more useful for your average web dev than something like USB or GPU support or Wasm. You'd be able to make complex interactive forms in much the same way that you do a spreadsheet.

[0] https://web.archive.org/web/20040727061732/http://www.w3scho...

[1] https://www.youtube.com/watch?v=2yYY7GJAbOo

recursive
2 replies
1d2h

We had this 25 years ago in the form of "Server Side Includes". https://en.wikipedia.org/wiki/Server_Side_Includes

You could put something like this in your markup

    <!--#include file="footer.html" -->
And the web server would apply it and inline the contents. It had a bunch of other directives, but this was the good one.

spankalee
1 replies
1d2h

A server side include wouldn't fix this problem because the SVG would be inlined everywhere. That defeats caching by duplicating the content.

Izkata
0 replies
1d

If we're talking just SVG, it could be done as a one-time inlining that uses <defs> to define shapes, that get pulled into the page later with <use>. The defs are page-wide and work across <svg> elements. That would fix the duplication, though not necessarily caching on its own with GP's include.

https://developer.mozilla.org/en-US/docs/Web/SVG/Element/def...

nbadg
1 replies
1d4h

I 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
0 replies
1d1h

You mean <img>. <img> is not stylable.

tracker1
0 replies
1d

I may be completely off and/or misremembering, but isn't this what <object> was meant to be able to do/support? Seems that this could be done by convincing Apple/Google/Firefox to reframe/update how the object element works in modern browsers.

tannhaeuser
0 replies
1d2h

HTML was invented as an SGML vocabulary, and SGML does have those inclusion mechanisms (called entities), though browsers basically never implemented those. To this date, self-acclaimed web folks ridicule XML (a simplified subset of SGML originalky invented as the base for additional vocabularies on the web, of which SVG and MathMl made it) for daring to incorporate something as basic as text variables/entities ie the "billion laughs atrack" (SGML could already limit the recursive entity expansion depth).

panstromek
0 replies
1d4h

Yes, 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.

danbee
0 replies
1d3h

Turbo Frames (https://turbo.hotwired.dev/handbook/frames) does this. It does mean pulling in a JavaScript library (and the user having JS enabled) but you don't have to write any.

I'd definitely love to see something like this built into the browser.

genezeta
18 replies
1d9h

In 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
14 replies
1d9h

There'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!)

mrled
7 replies
1d3h

Huh. I'm the OP, and I do have a dark mode that respects `prefers-color-scheme: dark` -- or at least, it works for me (tm). Would you mind sharing details about your dark mode theme? Is it a third party extension or maybe a browser I haven't tested?

Grom_PE
5 replies
1d2h

I think the main cause of black rectangle is the lack of support for nested CSS. At least that's what I'm seeing in my browser.

mrled
4 replies
1d2h

Ohhh interesting. To anyone hitting this, I'm curious what specific browser you're using - I thought it was available ~everywhere now? https://caniuse.com/css-nesting

everybodyknows
2 replies
1d1h

Seeing only inverted smilie over black background on my iPad, dark mode or light both.

mrled
1 replies
1d

I can't replicate on mine. If this is due to nested styles, I think you are behind on your software updates :). But also, maybe I need to hold off a bit longer before moving to nested styles.

rav
0 replies
21h4m

According to a forum post [1], e.g. iPad Mini 4 was discontinued March 2019 and is stuck on iOS 15, which doesn't support nested styles. Perhaps the issue is that people want to continue using old tablet devices that are no longer getting OS updates?

[1] https://education.apple.com/resource/250012027

LoganDark
0 replies
19h52m

It's only been available everywhere since like 2023. My browser happens to be from 2022.

LoganDark
0 replies
20h1m

I'm on Windows and in the system-level settings app, there's a toggle for dark mode. When I turn that on, then `prefers-color-scheme: dark` starts matching. There are zero third-party extensions or styles here, and my browser is Chromium 118.

madeofpalk
2 replies
1d7h

When my dark theme is enabled

Like it injects/modifies the styles of pages willy-nilly? The beauty of browsers is that you're fully able to do that, but seems like a great way to just have a broken browsing experience all the time...

The page is already pretty dark!

LightHugger
1 replies
1d6h

In my case, i have the standard browser dark preference active and the website obliges and shows a broken dark theme. If i instead use the style-injecty version such as dark reader, it actually fixes the website's broken dark theme and i can see the graph. So in this case, it is completely the website's fault.

madeofpalk
0 replies
1d6h

Weird. Neither my Firefox or Chrome show this issue.

Modified3019
2 replies
1d9h

Darkreader 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
1 replies
1d9h

This 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
0 replies
1d8h

For 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?

szundi
1 replies
1d9h

You must have some pretty important work to do with this level of procrastination ongoing.

shermantanktop
0 replies
1d3h

Without side projects to avoid deadlines on now-forgotten odious tasks, we’d all be living in grass huts.

mrled
0 replies
1d3h

This is a great point. I'm going to test some of the `<use>` suggestions I got in this thread, but if those don't pan out I'll definitely do this.

panstromek
14 replies
1d4h

I 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.

WhyNotHugo
10 replies
1d4h

Any examples of further material on this? Sounds pretty convenient, but I'm not familiar with <def> or <use> (or `object-position`, for that matter).

panstromek
1 replies
1d4h

cool, that one is about doing that inside html, but I usually do it in external SVG files.

prutya
0 replies
2h59m

That makes a lot of sense. If you use some client-side routing (e.g. Next.js), you might be fine, because the page does not reload during navigation. But if you don't, every HTML page will contain all the SVGs increasing the HTML size unnecessarily.

P.S. I actually went ahead and changed the implementation to a separate file on my website after I saw your comment :D

panstromek
2 replies
1d4h

It's something like this (I just quickly took this from my project, not sure if it works in this form now). This one uses the defs/use trick to reuse a path, but you can also just put two different svgs next to each other and not use the defs/use at all.

The icon:

  <!--   the icon width is 2x wider, to accommodate both 26x26 variants  -->
  
  <svg xmlns="http://www.w3.org/2000/svg" width="52" height="26">
    <defs>
      <!-- here's the icon defined, you can basically put anything here and
           mark it with an id (you can even use another svg) -->
      <path id="icon" path="..."/>
    </defs>
  
    <!-- first variant with no fill -->
    <use stroke="#fff" href="#icon"/>
  
    <!-- second variant with fill, shifted by 26 (dimensions of the icon) -->
    <use x="26" fill="#00ACA0" stroke="#00ACA0" href="#a"/>
  </svg>
  
HTML:

    <!-- make sure you use dimensions of the single variant -->
  <img src="icon.svg" width="26" height="26" class="hover-icon">
  
CSS:

  .hover-icon {
    /* make sure that only first block of the image is visible */
    object-fit: cover;
    object-position: left;
  }
  .hover-icon:hover {
    object-position: right;
  }

myfonj
1 replies
1d3h

Sandbox (with fixes): https://codesandbox.io/p/sandbox/pan-stromek-svg-object-posi...

Btw, for such simple re-colouring I'd probably rather used CSS hue shift filter or similar effect, and kept the SVG "dumb". But for having different shapes or geometric properties this approach is indeed nifty.

panstromek
0 replies
1d1h

Yes, I do that, too. The benefit of using the sprite system is that it's pretty general, so once you have some CSS for it, it's easy to keep adding new icons. CSS filters are usually more special for each case, but I use them too (mostly for brightness and greyscale things that are repeated on multiple places, e.g. tabs or disabled state).

jarek-foksa
2 replies
1d3h

Boxy SVG editor comes with built-in support for creation and editing of SVG icon sprites.

You can play with a sample SVG sprite on https://boxy-svg.com/#demo-symbols. Individual icons are shown under "Defs Panel -> Symbols". To edit an icon just double-click its thumbnail. To make part of an icon recolorable, select that part and then click "Fill Panel -> Paint -> Type -> Inherit".

You could then create separate symbols which contain a recolored instance of the original symbol. The underlying markup will look something like this:

  <?xml version="1.0" encoding="utf-8"?>
  <svg viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <defs>
      <symbol id="recolorable" viewBox="0 0 100 100">
        <rect width="100" height="100" style="fill: inherit;"/>
      </symbol>
      <symbol id="blue" viewBox="0 0 100 100">
        <use width="100" height="100" style="fill: blue;" xlink:href="#recolorable"/>
      </symbol>
      <symbol id="green" viewBox="0 0 100 100">
        <use width="100" height="100" style="fill: green;" xlink:href="#recolorable"/>
      </symbol>
    </defs>
  </svg>
Finally, use a fragment identifier to show a specific icon in HTML:

   <img src="sprite.svg#green">

panstromek
1 replies
1d1h

hmm, I didn't know you can use fragment identifiers in src attribute, that changes the game quite a bit. I remember looking for stuff like that, though. Not sure why I didn't anything, because it seems like it's been supported for quite a while. I only found the reuse inside svg in the same parent html document.

jarek-foksa
0 replies
21h36m

Fragment identifiers in "src" attribute seem to be supported by all modern browsers, but now I realized my example was wrong - you can reference <view> elements, but not <symbol> elements directly.

To make it work you would have to either replace <img src="sprite.svg#green"/> with <svg ...><use href="sprite.svg#green"></use></svg> or add views to the sprite file:

  <?xml version="1.0" encoding="utf-8"?>
  <svg viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <defs>
      <symbol id="recolorable" viewBox="0 0 100 100">
        <rect width="100" height="100" style="fill: inherit;"/>
      </symbol>
      <view id="blue"  viewBox="  0 0 100 100"></view>
      <view id="green" viewBox="100 0 100 100"></view>
    </defs>

    <use x="0"   y="0" width="100" height="100" style="fill: blue;"  xlink:href="#recolorable"/>
    <use x="100" y="0" width="100" height="100" style="fill: green;" xlink:href="#recolorable"/>
  </svg>

danielvaughn
0 replies
1d3h

You might want to check out old tech articles, as sprites were a very common approach from roughly 2005-2012-ish. Lots of interesting little techniques.

mrled
2 replies
1d2h

Oh 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
1 replies
1d1h

Well, 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.

douglee650
0 replies
23h6m

There 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.

rawoke083600
12 replies
1d10h

Actually 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
10 replies
1d9h

I 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.h...

michaelt
5 replies
1d8h

> 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
3 replies
1d7h

Ha, 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?

michaelt
1 replies
1d5h

I'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.

myfonj
0 replies
1d1h

So at this point we don't know about any viewer capable of handling Earths orbit sized SVG? That's sad.

However the browsers don't crash or run out of memory

Good news for your sample. Yet in some browsers there prevail some open issues, just the limits are now farther. For example feeding this SVG to my Firefox almost instantly exhausts my RAM and makes the browser window unusable for a while:

    data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg"
     viewBox="-1e11,-1e11,2e11,2e11"><circle r="1e11"/></svg>
I guess for more beefed machines would be necessary to bump exponents slightly higher. It's a known issue [1].

[1] https://bugzilla.mozilla.org/show_bug.cgi?id=1864374

nayuki
0 replies
21h37m

I tried to make a daily timeline in SVG where 1 unit = 1 second. There are 86400 seconds in a day. Both Firefox and Chrome did not render the image properly, so I had to scale the numbers down too. What a shame.

masfuerte
2 replies
1d4h

Also, 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
1 replies
1d4h

Do 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%...

masfuerte
0 replies
1d2h

It 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.

mort96
0 replies
1d8h

Another 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.

chrismorgan
12 replies
1d9h

I’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
6 replies
1d8h

It's talking about styling properties of SVG elements (e.g. path, circle) via CSS. Not about styling the svg element itself.

chrismorgan
5 replies
1d8h

It can’t be that, because you can do that in any SVG document, regardless of technique.

Lvl999Noob
4 replies
1d7h

It 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
3 replies
1d3h

Please 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.

asimpletune
2 replies
1d1h

Very interesting, so dynamic styling are things that are set with a script or with user initiated actions, like :hover.

Can you give an example of statically styling an element of an SVG image, that’s linked in an html document via the img tag?

chrismorgan
1 replies
23h28m

I’m not sure if I understand your request.

What you can do is just the totally basic style element or attribute:

  <svg …>
    <style>path { fill: red }</style>
    <path d="…" style="stroke: green" />
  </svg>
But I’m not saying you can apply styles to the inside of an image from outside; that, as I have remarked, is a different matter, about heritability—you can’t do that with any technique but inline SVG. Not <img>, not <iframe>, because it’s not cross-document.

asimpletune
0 replies
22h5m

So, I think that's what everybody else has been saying as well.

rhdunn
4 replies
1d7h

Stylable here means applying styling from the HTML files CSS file to change the colour, etc. For example:

1. changing the foreground and background of the SVG based on the web page theme or light/dark mode;

2. using the SVG in a link or button and styling the image according to the hover, pressed, etc. state, e.g. when providing custom checkbox/radio/toggle buttons.

chrismorgan
3 replies
1d4h

I return to what I said in my comment.

For your first example:

If you’re talking about using the prefers-color-scheme media query, you can do this with any technique—<img> qualifies as well. That’s applying static styles.

If you’re talking about things like styling based on an <html class="…"> value, <iframe> doesn’t qualify: that’s inheriting styles from the parent document and you can’t do it.

For your second example: that’s about whether the SVG is interactive.

However I look at it, “stylable” is simply the wrong word.

rhdunn
2 replies
21h51m

CSS stands for Cascading Style Sheets. Therefore, stylable is a suitable word for this -- i.e. having the SVG pick up the HTML document's styles.

Interactivity is different -- i.e. the SVG using JavaScript to be interacted with.

For the second example, it's just applying CSS styling:

    input:checked > svg { color: red; }
    button:hover > svg { color: teal; }
No need/use of JavaScript.

chrismorgan
1 replies
12h11m

Yet again I direct your attention to the ticks and crosses. In the article, <iframe> has been marked as stylable. But if you’re talking about controlling the styles of the SVG from the parent document, you can’t do that. So the original article cannot be using the term in the way you are.

What CSS stands for is quite immaterial in the definition of “stylable”. Especially the C. Cascading says nothing about cross-document application.

And when I speak of interactivity, I believe I’m using a term that has been employed in some of the specs and implementations to control most or all of the distinctions I’m talking about, though I have a vague feeling there was some other magic term too that I just can’t remember. I can’t trivially find the relevant definition in the SVG spec, and the HTML Standard these days says that <img src> refers to a “non-interactive, optionally animated, image resource that is neither paged nor scripted”, admittedly separating interactivity and scripting. Interactivity includes things like links and hover states.

rhdunn
0 replies
9h7m

The iframe section states:

To solve this, we could create an HTML file that contains only the <svg> tag, and reference it on the site via an <iframe>

Therefore you can attach the stylesheet containing the styles for the button/checkbox/etc. in the head of that document.

I don't know exactly how you would do this (w.r.t. propagating hover, etc. state) as I've used the embedded SVG element approach when I need styling.

GeoAtreides
8 replies
1d7h

Seeing 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
7 replies
1d7h

He wasn't talking about text, but the rendered image.

GeoAtreides
6 replies
1d7h

Unless 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
4 replies
1d7h

Svg 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.

vardump
1 replies
1d6h

SVG can be rasterized into a cache and just blitted or composited as necessary.

No point to waste CPU cycles rasterizing same SVG image repeatedly.

GeoAtreides
0 replies
1d6h

One would assume the browser already renders the svgs once and the caches it. Maybe, who knows, probably depends on the browser.

GeoAtreides
1 replies
1d7h

SVG 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
0 replies
1d5h

An example, many of Inkscape's filters depend on raster samples that need to be embedded. Complex gradients are also rasterised.

vardump
0 replies
22h27m

SVG is rendered (rasterized) by the browser. The browser can then cache the rendered image to avoid wasting CPU cycles.

tannhaeuser
2 replies
1d6h

Actually, 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.

runarberg
0 replies
23h34m

SMIL animations is definitely one of the underrated features of SVG.

mrled
0 replies
1d3h

Ohh, 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.

akira2501
2 replies
1d10h

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.

tnzk
1 replies
1d9h

This is actually what popped out of my head as I read the article. Did you observe other trade-offs with this approach?

akira2501
0 replies
1d9h

It requires javascript to instantiate the actual elements. Otherwise, none.

oneeyedpigeon
0 replies
1d10h

I 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.

lucideer
1 replies
1d6h

Doesn'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
0 replies
1d6h

The `<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!

HenriTEL
1 replies
1d10h

You 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
0 replies
1d10h

There'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.

quink
0 replies
1d10h

Or 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
0 replies
1d10h

Another 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/

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/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

beardyw
0 replies
23h37m

I can add:

In CSS: hold it as a background-image with the SVG in a data URL (requires some encoding).

Works for me.

baggy_trough
0 replies
1d5h

I 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

TheRealPomax
0 replies
22h27m

Still waiting for HTML imports. And that work was discontinued...

Springtime
0 replies
1d6h

For 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
0 replies
1d5h

All 3: Javascript.

Just load a .svg and put it into a <SVG>.

ABNW
0 replies
1d9h

Really 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!