What’s the usual practice — do people code in SVG directly or they draw in for example Figma and generate a SVG file?
What’s the usual practice — do people code in SVG directly or they draw in for example Figma and generate a SVG file?
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.
Cool story but would you elaborate on this part?
walk across the hall to get the hex codes for the other color
Sorry - that wasn't clear. Across the hall were our Design folks. They had the appropriate colors (in hex) that I needed.
Thanks for clarification.
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?
it was the location of the cabinet of hex-codes. all neatly sorted alphabetically.
ah, the classic sneakernet
That... never occurred to me. Cool tip that actually might save me a lot of time some day.
That's a great tutorial.
One niggle: They refer to the SVG "tag." I had started HTMLing in the mid-1990s, and we always called everything "tags."
Then, XHTML came in, and people started screaming at us for calling them "tags." They were elements, dammit!
I say "element," these days, but my brain still says "tag."
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."
AFAIK, XML gets it from HTML (which was its inspiration), which got it from SGML (of which HTML was originally an application), all use "element".
But, yes, SVG is an application of XML.
Ah XHTML the web’s dark age of pedantry. Call them whatever you want man, we’re much chiller in the HTML5 era.
XHTML strictness would have been a great start but at that point the "best-effort" <p><div>cat was out of the bag</span>
I mean what is worse? Incorrectness, or losing ad revenue :-)
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]
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!
Satori was a really useful tip for me too.
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".
Might be hard to believe
This is condescending and unhelpful.
Why post a link that is off topic?
Examining the output seems like another interesting way to learn SVG until one can speak it natively.
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.
Agreed.
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.
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
Very nice. It would be nice to see an example or two with text + an image, as this is the battle I'm currently fighting.
Alignment is a trip, let me tell you...
While I've played around with Inkscape, I'm definitely on the "writing XML" side of the fence in order to create what I need.
Alignment is a trip
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.
With text I wasn't experimenting too much, apart from the example where it follows a line.
I know there is text anchor: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/t...
And someone suggested the foreignObject tag that might be useful here: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/for...
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...
https://standardebooks.org/contribute/producing-an-ebook-ste...
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.
[0] GitHub link in profile.
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.
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?
Good catch. Yes, I rearranged some chapters and I missed this link. Thank you, fixed
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?
Damn, something is always broken. Let me look into it.
As for foreignObject, I also didn't knew about it. That's awesome
This is really neat! New SVG concept per lesson. Thanks for sharing!
As usual, a lot of these things I could learn if I decided to, but it’s nice when someone puts it together in a pretty package and shows up on HN.
Thank you. Let me know if you have any feedback. It's still under fine-tuning. And of course if you share it, that helps a lot :)
This is very cool and fun!
For Day 10, I don't see a snowman. I think you lose the background somewhere so it's white on white, I'm on my phone though so I can't dig in too far.
Yes, there's some bug with using gradients that I couldn't figure out yet. Are you looking at it on mobile? On desktop it works for me
I'm on Chrome for Android. I tried turning up the brightness and turning off the eye comfort shield and couldn't see it.
I took a look on my desktop and I can just barely see it. I think if you kept the blue background it would be easier on both platforms.
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.
https://chat.openai.com/share/49e91be6-bdef-4f4d-a263-80a884...
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.
Yep! As always, there’s both pros and cons to a programming approach and a necessity to understand them.
Yes, since HTML5 you can inline an SVG. You don't need Webpack or anything like that, it just works.
One of the examples in this tutorial is also a data-driven diagram generated from React. You can do pretty cool things by combining the two.
The advent calendar UI is nice but makes it hard to quickly browse the available content. Here's a full list of the articles:
- How to Draw Basic Shapes with SVG - https://svg-tutorial.com/svg/basic-shapes
- How to Build a Christmas Tree with SVG - https://svg-tutorial.com/svg/polygon
- How to Make a Gingerbread Figure with SVG - https://svg-tutorial.com/svg/gingerbread-figure
- How to Build a House with SVG - https://svg-tutorial.com/svg/house
- How to use clip-path with SVG - https://svg-tutorial.com/svg/clip-path
- How to Draw a Basic Path with SVG - https://svg-tutorial.com/svg/basic-path
- How to Draw a Star with SVG - https://svg-tutorial.com/svg/transform
- How to Draw a Snowflake with SVG - https://svg-tutorial.com/svg/use
- How to Draw a Forest with SVG - https://svg-tutorial.com/svg/forest
- How to Use Gradients with SVG - https://svg-tutorial.com/svg/gradient
- How to Draw Quadratic Bézier Curves with SVG - https://svg-tutorial.com/svg/quadratic-bezier
- How to Draw Cubic Bézier Curves with SVG - https://svg-tutorial.com/svg/cubic-bezier
- How to Draw a Bell with SVG - https://svg-tutorial.com/svg/bell
- How to Draw an Arc with SVG - https://svg-tutorial.com/svg/arc
- How to Draw a Ribbon with SVG - https://svg-tutorial.com/svg/ribbon
- How to Draw a Bear with SVG - https://svg-tutorial.com/svg/bear
- How to Draw Text Along a Path with SVG - https://svg-tutorial.com/svg/text-path
- How to Animate Along a Path with SVG - https://svg-tutorial.com/svg/path-based-animation
- How to Add Animation on Hover of an SVG element - https://svg-tutorial.com/svg/animation-on-hover
- How to Animate a Snowing effect with SVG and CSS - https://svg-tutorial.com/svg/snowing
- How to Create Background Patterns with SVG and CSS - https://svg-tutorial.com/svg/background-pattern
- How to Draw a Clock with SVG and JavaScript that Shows the Actual Time - https://svg-tutorial.com/svg/clock
- How to Add Interaction to SVG elements with JavaScript - https://svg-tutorial.com/svg/interaction
- How to Generate an SVG Diagram from JavaScript - https://svg-tutorial.com/svg/data-driven-diagram
- How to Break Down an SVG Image into Multiple Components - https://svg-tutorial.com/svg/multiple-components
Generated by running this in Firefox DevTools:
copy(Array.from(document.querySelectorAll('.day'), el => {
const title = el.querySelector('.title').textContent;
const url = el.href;
return `- ${title} - ${url}`
}).join('\n\n'))
Lol :) Maybe I should just put this below the calendar. What do you think?
That would be great!
Added a Table of Contents below. Probably it helps SEO as well :)
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 :)
Ouch. Some browsers might not support every feature. Gradients also have some issues. Luckily it seems to be all right so far in desktop browsers.
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 ^^)
Not working on Edge on android either.
All in all, excellent ressource! Great and super clear examples.
Minor nitpick @clip-path; they propose the following code:
<svg width="200" height="200" viewBox="-100 -100 200 200">
<defs>
<clipPath id="ball">
<circle cx="0" cy="20" r="70" />
</clipPath>
</defs>
<circle cx="0" cy="20" r="70" fill="#D1495B" />
<polyline
clip-path="url(#ball)"
points="-120 40 -80 0 -40 40 0 0 40 40 80 0 120 40"
fill="none"
stroke="#9C2D2A"
stroke-width="20"
/>
<circle
cx="0"
cy="-75"
r="12"
fill="none"
stroke="#F79257"
stroke-width="2"
/>
<rect x="-17.5" y="-65" width="35" height="20" fill="#F79257" />
</svg>
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: <svg width="200" height="200" viewBox="-100 -100 200 200">
<defs>
<circle cx="0" cy="20" r="70" id="round"/>
<clipPath id="ball">
<use href="#round"/>
</clipPath>
</defs>
<use href="#round" fill="#D1495B" />
(rest unchanged)You don’t even need the second <use>, you can just render the <circle> normally and use it in the clipPath:
<svg width="200" height="200" viewBox="-100 -100 200 200">
<defs>
<clipPath id="ball">
- <circle cx="0" cy="20" r="70" />
+ <use href="#round" />
</clipPath>
</defs>
- <circle cx="0" cy="20" r="70" fill="#D1495B" />
+ <circle cx="0" cy="20" r="70" fill="#D1495B" id="round" />
(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!
That is true, good idea. I might update it with a note on this
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.
Why not make the CSS dynamic? Or even manipulate the SVG itself in script? D3 has been doing the latter for a long time.
Yes, that's what I wanted to do, change the CSS values (based on ids, I guess).
I'm pretty sure I've heard of D3, I'll have to check it out. Thanks.
This is fantastic! I especially like the examples with curves, which I continue to struggle with, along with clipping.
Personally, I'm partial to path which can do almost anything and tends to be less verbose than other methods.
Long time student, but I see that I still have lots to learn.
I suck so much at drawing and dislike images so much that for ease and performance, I built my entire side project with svg.
After today, it looks like I have quite a bit of refactoring to do. Thank you, OP!
Thank you, I'm glad it helped. Cool comics!
Thank you, Hunor. I found your CodePen. Wow. Looks like I'll be busy today :-)
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 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".
True. When you make art with CSS then you don't start with Illustrator either
Can I somehow put the css classes inside the svg to have it self contained without resorting to inline styles?
Yeah, just add the style tag in there like you would with HTML:
https://developer.mozilla.org/en-US/docs/Web/SVG/Element/sty...
And SVG elements can have classes: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/c...
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/
Super cool effect. Yes, SVGs can be a rabbit hole. This is just scratching the surface of it
flaps too slow, i got shit to do ;D
oh wait, it's december. no i don't xD
Yes, and imagine if I would have figured out how to do the view transitions properly :)
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.
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.
[1]: https://github.com/epiccoleman/react-circle-of-fifths
[2]: https://epiccoleman.com/posts/2023-04-05-svg-circle-of-fifth...
I love focused tutorials like this!
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!
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.
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.
For complicated shapes/curves I'll sometimes run it through an online editor to help visualize, this is a good one: https://yqnn.github.io/svg-path-editor/
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.
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.
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 :)
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 "clapper".
I am still on the steep end of the SVG learning curve, but also generally start in Illustrator and then export, clean up, and hand-code the details.
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.
I was trained as a graphic designer, so I either drew stuff in Inkscape, or imported it from some other program.
Had to do quite a bit of work to get filesizes down to something reasonable for:
http://shapeoko.github.io/Docs/
One late development was working up a mechanism where an image could be clicked on to open it in a new window:
http://shapeoko.github.io/Docs/content/tPictures/PS20028-100...
and then the part names in the parts list could be clicked on to highlight the matching part in the diagram.
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.
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
With these new transformer-based vector models, like Adobe's (https://www.adobe.com/products/illustrator/text-to-vector-gr...), generating SVG will become easier than ever.
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.