[HN Gopher] SVG Triangle of Compromise
       ___________________________________________________________________
        
       SVG Triangle of Compromise
        
       Author : mrled
       Score  : 250 points
       Date   : 2024-07-25 16:45 UTC (4 days ago)
        
 (HTM) web link (me.micahrl.com)
 (TXT) w3m dump (me.micahrl.com)
        
       | rawoke083600 wrote:
       | 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 wrote:
         | 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 wrote:
           | _> 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 wrote:
             | 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?
        
               | codetrotter wrote:
               | From looking at the following pages
               | 
               | - https://docs.aspose.com/svg/net/drawing-
               | basics/coordinate-sy...
               | 
               | - https://www.w3.org/TR/SVG2/coords.html
               | 
               | - 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 wrote:
               | 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 wrote:
               | 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 wrote:
             | 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 wrote:
           | 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 wrote:
             | 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 beziers 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 wrote:
               | 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.
        
           | myfonj wrote:
           | (Missed edit:) I even asked about formalized precision SVG
           | limits on SO: https://stackoverflow.com/q/78692079/540955
        
         | mort96 wrote:
         | 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.
        
       | spankalee wrote:
       | Something 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
        
         | oneeyedpigeon wrote:
         | 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.
        
       | HenriTEL wrote:
       | 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 wrote:
         | 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 wrote:
       | 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 wrote:
       | 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
        
       | akira2501 wrote:
       | > 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 wrote:
         | This is actually what popped out of my head as I read the
         | article. Did you observe other trade-offs with this approach?
        
           | akira2501 wrote:
           | It requires javascript to instantiate the actual elements.
           | Otherwise, none.
        
       | genezeta wrote:
       | 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 wrote:
         | 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!)
        
           | Modified3019 wrote:
           | 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 wrote:
             | 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 wrote:
               | 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?
        
           | madeofpalk wrote:
           | > 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 wrote:
             | 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 wrote:
               | Weird. Neither my Firefox or Chrome show this issue.
        
           | mrled wrote:
           | 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 wrote:
             | 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 wrote:
               | 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 wrote:
               | Seeing only inverted smilie over black background on my
               | iPad, dark mode or light both.
        
               | mrled wrote:
               | 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 wrote:
               | 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 wrote:
               | Dude, it's available everywhere since like 2023. My
               | browser happens to be from 2022. I do not update software
               | until I need a new feature myself.
        
             | LoganDark wrote:
             | I'm in 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.
        
         | szundi wrote:
         | You must have some pretty important work to do with this level
         | of procrastination ongoing.
        
           | shermantanktop wrote:
           | Without side projects to avoid deadlines on now-forgotten
           | odious tasks, we'd all be living in grass huts.
        
         | mrled wrote:
         | 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.
        
       | ABNW wrote:
       | 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!
        
       | chrismorgan wrote:
       | 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 wrote:
         | It's talking about styling properties of SVG elements (e.g.
         | path, circle) via CSS. Not about styling the svg element
         | itself.
        
           | chrismorgan wrote:
           | It can't be that, because you can do that in any SVG
           | document, regardless of technique.
        
             | Lvl999Noob wrote:
             | 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 wrote:
               | 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 wrote:
               | 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 wrote:
               | 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 wrote:
               | So, I think that's what everybody else has been saying as
               | well.
        
         | rhdunn wrote:
         | 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 wrote:
           | 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 wrote:
             | 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.
        
       | GeoAtreides wrote:
       | 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 wrote:
         | He wasn't talking about text, but the rendered image.
        
           | GeoAtreides wrote:
           | 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 wrote:
             | 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.
        
               | GeoAtreides wrote:
               | 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 wrote:
               | An example, many of Inkscape's filters depend on raster
               | samples that need to be embedded. Complex gradients are
               | also rasterised.
        
               | vardump wrote:
               | 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 wrote:
               | One would assume the browser already renders the svgs
               | once and the caches it. Maybe, who knows, probably
               | depends on the browser.
        
             | vardump wrote:
             | SVG is rendered (rasterized) by the browser. The browser
             | can then cache the rendered image to avoid wasting CPU
             | cycles.
        
       | tannhaeuser wrote:
       | 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.
        
         | mrled wrote:
         | 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.
        
         | runarberg wrote:
         | SMIL animations is definitely one of the underrated features of
         | SVG.
        
       | lucideer wrote:
       | 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 wrote:
         | 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!
        
       | Springtime wrote:
       | 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 wrote:
       | All 3: Javascript.
       | 
       | Just load a .svg and put it into a <SVG>.
        
       | baggy_trough wrote:
       | 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
        
       | OskarS wrote:
       | 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.
        
         | panstromek wrote:
         | 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.
        
         | nbadg wrote:
         | 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 wrote:
           | You mean <img>. <img> is not stylable.
        
         | ndriscoll wrote:
         | 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 wrote:
           | XSLT is an XML transformation language, but HTML is not XML.
           | Does XSLT work on regular HTML?
        
             | dekhn wrote:
             | 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.
        
             | ndriscoll wrote:
             | I'm not sure what you mean, but you can output HTML that a
             | browser will be happy with, and that conforms to the spec.
             | See e.g. https://stackoverflow.com/questions/3387127/set-
             | html5-doctyp...
        
               | kbolino wrote:
               | 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.
        
               | nayuki wrote:
               | 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
        
               | ndriscoll wrote:
               | 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
        
             | LegionMammal978 wrote:
             | 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...
        
           | dspillett wrote:
           | _> 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.
        
         | danbee wrote:
         | 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.
        
         | jwells89 wrote:
         | 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).
        
           | ndriscoll wrote:
           | 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.w3s
           | cho...
           | 
           | [1] https://www.youtube.com/watch?v=2yYY7GJAbOo
        
           | PaulDavisThe1st wrote:
           | 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 wrote:
             | 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.
        
         | tannhaeuser wrote:
         | 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).
        
         | spankalee wrote:
         | There's this HTML spec issue for an include feature that I
         | think could always use more support:
         | https://github.com/whatwg/html/issues/2791
         | 
         | One of the things said in there is that they look for usage of
         | userland solutions. I mentioned in another comment, but there
         | are custom elements that do client-side includes, like:
         | https://www.npmjs.com/package/html-include-element
        
         | recursive wrote:
         | 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 wrote:
           | A server side include wouldn't fix this problem because the
           | SVG would be inlined everywhere. That defeats caching by
           | duplicating the content.
        
             | Izkata wrote:
             | 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...
        
         | tracker1 wrote:
         | 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.
        
       | panstromek wrote:
       | 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 wrote:
         | 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 wrote:
           | 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 wrote:
             | 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 wrote:
               | 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).
        
           | prutya wrote:
           | Hey, I wrote a small blog post on <defs> and <use> and how to
           | optimize icons using them:
           | https://www.prudkohliad.com/articles/reuse-svg-
           | icons-2023-08...
        
             | panstromek wrote:
             | cool, that one is about doing that inside html, but I
             | usually do it in external SVG files.
        
           | jarek-foksa wrote:
           | 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 wrote:
             | 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 wrote:
               | 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 wrote:
           | 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 wrote:
         | 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 wrote:
           | 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 wrote:
             | 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.
        
       | beardyw wrote:
       | I can add:
       | 
       | In CSS: hold it as a background-image with the SVG in a data URL
       | (requires some encoding).
       | 
       | Works for me.
        
       | TheRealPomax wrote:
       | Still waiting for HTML imports. And that work was discontinued...
        
       ___________________________________________________________________
       (page generated 2024-07-29 23:00 UTC)