SVG + React is really underrated, IMO. You get all the power and abstractions of React, but instead of rendering DOM, you can render arbitrary graphics. I've used this for rendering graphs and charts, and for a certain subset of use-cases, it demolishes Canvas. For instance, if you need a little bit of interactivity, but you don't need anything too graphically crazy like per-pixel manipulation.
e.g., doing hover effects in Canvas is a huge pain because you have to do all the work to figure out which element the mouse is on top of. With SVG you just use builtins like onmouseover!
Totally - the fact that you can hook up click listeners and use CSS to style SVG just like it's regular ol' html feels pretty magical at times, and React / JSX makes it really easy to utilize.
One of the biggest downsides is that there is none of the percentage-based sizing that you get with HTML. Otherwise, it could replace HTML for virtually everything.
True - although in certain ways, this can be an advantage. When I've built SVG components, I use viewbox with height and width constants to define the SVG's "internal" dimensions, and then if you want to do something like finding the midpoint, you just do the right math on your constants. Then, the component can easily be scaled via CSS.
The problem, of course, is that there's not really a good way to do dynamic sizing if you want to be able to change the aspect ratio, which is where layout engines like Grid and Flex become so useful in HTML / CSS. But in my (fairly limited) experience, if I'm reaching for SVG it's because I need the tight control that comes with it, so it hasn't been an issue for my own projects.
Yeah - foreignObject is super interesting, I had never heard of it before this thread. I even have a potential use case for it one of my projects, definitely need to check it out.
This sounds like an area I would enjoy a lot but am barely a beginner in React. Any working examples that might give me the right direction / inspiration ? Thanks
It's not exactly a primer, but my blog post[1] that I linked elsewhere in the thread is, I think, a pretty good example. It goes through some SVG basics, and then the following post in the theory talks through adding interactivity via event listeners hooked up in a React-y way.[2]
I can't promise that it's like, the best code or the best approach to the problem, but I did get the component working, which is worth something. Check it out - I'd love to hear what you think!
I've made an image segmentation + tagging component with Preact.js and SVG for a client – turned out pretty neat. Can recommend for this kind of applications.
Totally. There are many cases when HTML Canvas is way more performant, but if you don't build the next Figma, then working with SVG is way more convenient
But that means describing the big circle twice. If you want to change the size of the circle you will have to modify it in two places. Since we're already using defs it would be better to write this IMHO:
(Personally I’d also drop the <defs>-wrapping. Never did understand why structuring them that way is recommended, I don’t think it actually gets you anything except for the vanishingly rare case where you want to put something that would render if it were not in a <defs> tag—I say “vanishingly rare” because situations like you showed—//defs/circle—should normally actually use <symbol>.)
I like to do the defs in one svg in one part of the html page, and use them elsewhere in other svgs. It's clean and readable that way. But to each their own I guess!
This is really cool! SVG is such a neat and flexible format, I'll definitely be taking some time to work through these tutorials, as it's directly related to some side projects I have going.
Like some of the other commenters here, I've found a lot of fun in building React components that are backed by SVG. React and JSX make it easy to add the interaction, and SVG lets you do some pretty cool UIs that wouldn't be easily possible with just HTML.
I actually have published a React component that renders an interactive "Circle of Fifths," which I built for a music theory side project I was working on (although this project is currently languishing among many other half-baked repos). There's still a lot to do with the component, but it's in a usable state[1].
I wrote what I think is probably my best blog post[2] about the process of figuring out how to build the Circle of Fifths with SVG. I'm particularly proud of the little explainer section in the middle that follows the drawing of a somewhat complex <path> element.
I'm currently building out a fretboard diagram generator using a very similar approach, and having that post on hand for reference has been pretty useful. This is maybe my favorite thing about writing up the stuff I work on, it's nice to be able to "replay" how I thought through a problem.
Love this resource! I've coded a few inline svgs in react for some fun svg interactivity, and its a lot of fun to play with.
The <foreignObject> tag is especially useful, as it allows you to put normal html inside svg, so you can use html for things that html does better (links, images, basic flexbox styling etc) within a svg art project.
For the author, btw, a few links on the site are not working: your bio.link on the bottom of the page, and in Day 11: How to Draw Quadratic Bézier Curves with SVG, there is a link to an interactive bezier curve demo that is down.
Okay, I fixed the links to the interactive demos (somehow deep links do not always work on that site, probably because it's made with Vue). I don't see the problem with bio.link. What issue do you see?
Also at the bottom of page https://svg-tutorial.com/svg/transform the link to the "next example" is /svg/path which throws a 404; the correct link is /svg/use I think?
Several years ago I was working on an interface and we were using SVGs for some graphics. We had two color schemes but one of the graphics was only in one of them, so I walk across the hall to get the hex codes for the other color. The design guy was blown away when we popped open the svg file and simply find-and-replaced all the colors to get the second color.
What’s messing with me is that you seemed to have a computer that drew hex colors. Also, you knew the hex value you wanted. Kinda hate second guessing your actions from the 20th century but why did you walk?
There was a green version as well. I don't really remember why I didn't have a green graphic that I could pull the correct values from. I just recall going across the hall to talk about a Green version of the graphic and with the designer we changed the value in the SVG code instead of Illustrator (Or whatever program he was using.)
As for "Why walk across the hall?", there are times when going to someone's desk to discuss a situation is faster and more effective than an email or a chat.
Thank you for the great feedback, I really appreciate it. I fixed some errors you found. Let me know if something still doesn't work. It's still a bit in the process of fine-tuning.
For instance, does anyone know why the thumbnail preview does not work on Twitter? It works with the sub-pages.
While most of the SVG text examples I've seen have a "word art" type of feel to them, I was mostly thinking it would be nice to show another common use case.
Recently, I've been using Standard Ebooks' toolkit to convert my Master's Defense into EPUB. SE uses SVG as its image format for covers - along with a few scaled JPGs. Unsurprisingly, all of this starts out as text and there is extensive use of text-anchor to get the alignment right.
Although they use XHTML as the primary input format, foreignObject is a concept I haven't encountered before, might be worth checking out...
Oh man, text is definitely a hassle. I ginned up some Python code to generate a table with svgwrite[0] and getting text where I wanted it was hell. I ended up just fudging a bunch of stuff and calling it close enough. I second the request for an example with non-trivial text positioning.
Inkscape's alignment functions works for me. For things where I needed more precision, what I do is press ctrl+shift+x and type in the coordinates there. (Inkscape's XML editor seem to crash very often for me, but it's workable if I remember to save after every edit).
I suspect my frustration here is that although Inkscape's controls sort of look like Word or any number of other word processors, since it can modify a document's underlying XML, it requires keeping both paradigms in your head as you work.
I know people use it and like it, but in trying to get something done in a way that would save time, this approach didn't really click for me.
Also having a formal GD background, I tend to do the same... Trying get things like type polished enough for proper design work without using a graphical editor is a fool's errand. Depending on the use case, I often end up using the results inline. That way, I can easily modify/animate/script it with my code editor without having to jump back-and-forth between environments, and things like element IDs stay consistent.
Design people will use their editor of choice - Illustrator/Sketch/Inkscape/etc. Some coders might tweak things using that software, but usually I'll edit the SVG directly, especially if there's interactivity.
There is also Boxy SVG (https://boxy-svg.com) which combines both designer and developer oriented functionality and uses SVG as its native file format.
Unlike Illustrator/Sketch/Inkscape it can also create and manipulate SVG animation elements (https://boxy-svg.com/blog/21) - a very powerful feature which is now supported by all major browsers.
I dont mean to be rude but is there a reason why firefox is not supported ? Is it " it will never work there because the mandatory feature X is missing and will never be implemented in firefox " or "some features are broken " in which case a disclaimer "we dont test in firefox so use at your own peril" would be great :)
Looks great! I vaguely recall checking it out at some point but must have forgotten to bookmark.
It seems like a fairly straightforward mapping of UI -> SVG features, which must have taken a ton of effort. I'll have to take a closer look at the animation tool, I've often wondered if web technologies would ever get close to Flash's capabilities.
For more complex graphics you would probably still use a designer tool. But for some simple ones, you can probably code them yourself. Like if you need an arrow or a hamburger menu icon, you can just jump straight into code. Sometimes I also just start with pen and paper and then figure out the coordinates from there, and adjust till it looks good enough.
In projects I've worked on, I've used Inkscape to create or edit files, then link them in like a typical image. On occasion, I've had a few static pages that needed a unique graphic that would be embedded into the page, though the graphics in those cases were not very complex
As a frontend dev who also works in UX and graphics from time to time, I find it helpful to be able to do both, looking at SVGs as both a vector graphics format and a human-readable XML. IME the workflow depends more on whether any SVG is meant to be illustrative (like art) or quantitative (like charts) or interactive and animated/mutable (like a game).
For something like this bell example (https://svg-tutorial.com/svg/bell), you can certainly hand-code it if you're really math-inclined and can estimate the formulas of curves just by looking at them, but for us mere mortals, it's easier to just draw out the curves in a graphics app (like https://youtu.be/5x2uHUB_pzw?si=fSLjRKlZNgVKVcOx&t=123 for Figma) then export as an SVG. And for things like the ringer (is that what you call it? the orange ball thing at the bottom of the bell that strikes the bell to make the sound), being able to visually draw it on a canvas, change its size, drag it around and play with its colors and dimensions, etc. is really helpful. Figma is fine for simpler graphics, but it's really more of a UX tool than a graphic design tool, and Illustrator is a lot more powerful. Inkscape is a FOSS option.
In other circumstances, though, manipulating the SVG XML directly is also very helpful. Let's say you want to programatically generate a bar chart. If you have a big dataset, it's going to take a designer forever to manually plot them and change them every time the data changes. But it's easy for a dev to use Javascript (or any language) to draw each rectangle, programmatically adjust their heights and colors based on the data, add tooltips, etc. And that way you can dynamically update them in real-time whenever the data changes (like if the user selects a different date range, or new events come in). A lot of this is made easier by libs like https://frappe.io/charts or https://apexcharts.com. But before you take that approach, you should know that for complex charts, sometimes Canvas rendering (or just generating graphics in the backend) can be more performant than SVG.
SVGs can also be animated and interactive, not just with CSS transitions but by directly manipulating the XML geometries, like http://snapsvg.io/demos/ or https://www.svgator.com/ or https://codepen.io/collection/XpwMLO/. This is fine for product pages and such, but for really graphics-intensive apps (full games) it's probably slower than other rendering pipelines. (Not my specialty, won't speculate too much.)
TLDR Drawing them in a graphics app is usually easier for the designers, but the XML can be programmatically manipulated afterward to great effect. The ideal workflow depends on what you're trying to accomplish, and also who you have on your team.
The funny thing about writing tutorials like this as a non-native speaker myself is also googling how to call things like the "clapper". I also didn't know what it was called before writing this article.
One of the things that kinda clicked for me recently was learning that I can inline SVG tags in a react application as if they were JSX tags.
I dunno specifically if that’s first class or webpack is covering it, but it really feels good in a few cases to make an SVG component with some logic built in. So now I can have an SVG and some react-driven logic modifies its shape, colour, omitting sections of it, etc.
This is good for simple SVGs, or cases where you will have many variations.
But when you online SVG code, the browser can't cache the image. So if the SVGs are larger, or have only a few variations, you may prefer to have a separate endpoint for each image variant.
Yeah, I've seen React pages where a tiny icon (like a little star) is inlined a hundred times on the same page. That's a lot of extra bytes :(
At least if they're in the same JSX component, the server can gzip that SVG string so it's not as big over the wire. But if the same icon gets used in different pages, the costs multiply.
It's nice to have the OPTION of treating SVG as code when you want it to be code, but otherwise, it's better for the user to treat it as a graphic and let the usual caching mechanisms (server+browser) do their jobs.
In XML terminology (where XHTML derives from), "tags" are the delimiters of "elements". So we have "start-tags", "end-tags", and "empty-element-tags".[1] "Element" refers to the composition of the delimiting tags and all of their (nested) content.[2]
Depends on what you’re talking about, to be honest. The “element” is the “thing”. The “tag” is how you tell the browser what you want.
This is why you have DOM functions like “getElementsByTagName”, which allows you to say “I know the tag name is “hr” (and the tag is <hr />), but I want to get references to all the elements which are defined by that tag.
As a general rule, if you’re thinking about a “thing” on a webpage, you’re think about an element. If you’re thinking about what you need to write to get that element to appear on the webpage, you’re thinking about a tag.
Most of the time, folks will understand what you mean even if you use the wrong one though.
In XML, they are referred to as "empty-element tags" and are functionally equivalent to a start tag immediately followed by an end tag, such as <br></br> or <hr></hr>. If a tag has no content, it can in principle also be written as an empty-element tag, for example: </p>. However, such use is not recommended: "For interoperability, the empty-element tag SHOULD be used, and SHOULD only be used, for elements which are declared EMPTY."[1] "For interoperability" is defined as: "Marks a sentence describing a non-binding recommendation included to increase the chances that XML documents can be processed by the existing installed base of SGML processors which predate the WebSGML Adaptations Annex to ISO 8879."[2a] "SHOULD" is explicitly[2b] used as defined in RFC 2119: "This word [...] mean that there may exist valid reasons in particular circumstances to ignore a particular item, but the full implications must be understood and carefully weighed before choosing a different course."[3]
As others have pointed out, elements and tags are different things and always were. An element is the thing comprised of tags and the content between them. eg <tag>content</tag> is an element.
It's an interesting point. Writing tutorials like this also made me realize what's the difference between a function property and a function argument. I just used them completely interchangeably before. So element is more accurate here?
SVG is basically an expression of XML, and XML uses "element" for everything, so it would be more appropriate, but, TBH, I really don't think anyone reading gives a damn.
I have done a ton of tutorials, myself, and have found that using vernacular, and expressing in basic, readable language, always works best. Being too pedantic can make it seem "stilted."
I love this article and the fact that someone is giving more attention to "write SVG code directly just like HTML+CSS", rather than the usual "just draw with the mouse in Inkscape/Illustrator/etc. and export as SVG".
Another way is to write HTML/CSS and use satori [0] to convert that to SVG. It's meant for Open Graph images (the images that show up when you link a site in Discord, Slack, Twitter, etc.), but it works quite well for anything.
This is obviously not as flexible as true SVG, but it is familiar to author for anyone who's written a React application. I've used it on the backend to generate match reports for League of Legends [1]
Yeah, there are lots of tools to help with this. Why post a link that is off topic?
Might be hard to believe, but some folks want to learn stuff and understand how things work under the hood, which is a group that OP's site appears to target.
Actually I've been working on a task that needs me to generate SVGs today, and satori looks like it's going to be much easier to achieve what I want. So thanks
shepherdjerred!
The parent comment was just offering alternative approaches to the problem that the thread's link addresses. That seems like a perfect use for a comment on this thread. It's the furthest thing from "off topic".
Very cool stuff, and great work. Minor UI nitpicks (my personal bugbear):
- Lesson content section has unnecessary horizontal scrollbar visible
- No visual distinguishing or handling for scrollable area (vs the finished display area) had me trying to scroll with my mouse hovering on the lefthand side often, and momentarily confused why it wouldn't go. Make the whole main body section scroll the content, ideally.
Yes, I was thinking of fixing the second point, but then I was annoyed with it and left it like that. If I knew that it blows up here on Hacker News I would have fixed it.
I'm not sure where you see horizontal scrollbars though. Are you on Windows?
I just switched over to SVGs from bitmap images. I was using PNG images for
different icons which worked fine until I had to upscale to higher resolutions.
The SVGs work great and are probably smaller too (depending on the complexity).
I want to render them to a canvas with different (dynamic) color configurations
and I'm exploring different ways to do this.
Awesome resource! I wrote a blog post just last week that is very similar in nature to this, but about achieving a specific effect in SVGs: https://daniel.do/article/making-noisy-svgs/
This programmatic approach to drawing shapes is very familiar to anyone whose made custom controls for desktop applications (think Quartz/Cocoa and Cairo/GTK). I think you could use this approach when building a website and avoid much of CSS and HTML.
The advent calendar design was such a good idea since you're releasing this in December! My favorite is the clock that tells you your time at 22 and the functioning Christmas lights at 23!
On day 5 they draw an ornament with motif. Funny how it's rendered in Firefox on Android on my phone- none of the images contains motif clipped to the ornament :)
Thanks a lot for your website it's really nicely written. Can you add a disclaimer for this one to say it does not work on firefox android (i also hit the issue ^^)
e.g., doing hover effects in Canvas is a huge pain because you have to do all the work to figure out which element the mouse is on top of. With SVG you just use builtins like onmouseover!