Editing an SVG by hand: a short tour
A walk through an icon file in a text editor, from the root element to paths and attributes, plus small edits you can safely make without a design tool.
5 min read
An SVG file is text. Changing a color, adding an accessible name, or fixing a cropped edge does not require a design tool: open the file in a code editor, change a few characters, save, and reload it in a browser. This tour shows you what you are looking at and which edits are safe to make by hand.
Opening a file
Any plain text editor works, though a code editor with XML or HTML syntax highlighting makes the structure easier to see. To preview, drag the .svg file into a browser tab. Keep that tab open: after each save, reload it to see the change.
If you do not have a file at hand, download any logo from the icon library as SVG and open it alongside this guide.
A tour of an icon file
Here is a small but realistic icon, a faceted diamond on a dark coin:
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="none">
<g id="token">
<circle cx="16" cy="16" r="16" fill="#27272a"/>
<path d="M16 6l7 10-7 10-7-10z" fill="#e4e4e7"/>
<path d="M16 6l7 10-7 4z" fill="#a1a1aa"/>
</g>
</svg>
Line by line:
The root <svg> element.
xmlns="http://www.w3.org/2000/svg"marks the file as SVG. Never delete it from a standalone file; without it, the browser shows the file as unknown XML instead of drawing it.widthandheightare the default display size. CSS can override them.viewBox="0 0 32 32"defines the coordinate grid: 32 units across and down, starting at the top-left. Every number inside the file uses this grid. Understanding the SVG viewBox covers it in full.fill="none"sets a default for everything inside. Many design tools add it. Each shape below sets its own fill, which overrides this default.
The <g> group. A group bundles shapes. It can carry attributes that apply to all its children, such as opacity, transform or a shared fill. Here the id="token" is just a label left by the design tool, harmless unless something references it.
The shapes. circle uses a center (cx, cy) and radius (r). The two path elements describe their outlines in the d attribute: here, a diamond, then a triangle covering its right-hand facet in a slightly darker gray. SVG paths explained teaches you to read those commands.
Order is stacking. Later elements paint on top of earlier ones. The coin comes first, the diamond on top of it, the facet on top of that. Move the circle to the end and it covers everything.
Where colors actually come from
Before changing a color, find out where it is set. SVG accepts styling in three places, and they do not have equal weight:
| Where | Looks like | Priority |
|---|---|---|
| Presentation attribute | fill="#e4e4e7" |
Lowest |
<style> block with a class |
.cls-1 { fill: #e4e4e7; } |
Higher, by normal CSS rules |
style attribute |
style="fill: #e4e4e7" |
Higher still |
So if you change fill="#e4e4e7" and nothing happens, look for a style attribute on the same element or a <style> block near the top of the file. Files exported from some tools use classes like cls-1, cls-2 defined in a <style> block; change the color there.
Colors can also be inherited. A shape with no fill of its own takes the fill of its nearest ancestor that has one, and falls back to black if none does. That is why deleting a fill attribute can turn a shape black.
Edit 1: change a fill
Find the hex value and replace it. To recolor the coin above to near-black:
<circle cx="16" cy="16" r="16" fill="#09090b"/>
For a single-color icon that should follow the surrounding text color when inlined in a page, replace the fills with currentColor:
<path d="M16 6l7 10-7 10-7-10z" fill="currentColor"/>
If a fill says url(#something), the shape is painted with a gradient or pattern defined elsewhere in the file, usually inside <defs>. Change the stop-color values on that gradient's <stop> elements instead. If the file is someone else's logo, recoloring it is also a brand question; the project's brand guidelines usually say which color variants are allowed.
Edit 2: add a title
A <title> element as the first child of <svg> gives the drawing a name:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" role="img" aria-labelledby="token-title">
<title id="token-title">Example token</title>
...
</svg>
When the file is inlined in a page, role="img" with aria-labelledby pointing at the title gives screen readers a reliable name. Keep that id unique on the page. When the file is used through <img>, the alt attribute on the image tag is what counts, and the title inside the file is not used as its text alternative. Accessible SVG markup covers the details.
Edit 3: fix the viewBox
Three viewBox fixes come up often:
- Missing viewBox. If the root has
width="32" height="32"but no viewBox, addviewBox="0 0 32 32"using the same numbers. The icon will then scale instead of being cropped or stuck in a corner. - Edges cut off. Grow the box by the same amount on every side:
0 0 32 32becomes-1 -1 34 34for one extra unit of room. - Too much padding. Shrink it:
0 0 32 32becomes2 2 28 28to remove two units on each side.
Keep the last two numbers equal for square icons, and shift the first two by the same amount you add or remove on each side.
Edit 4: remove clutter
It is safe to delete comments, an <?xml ...?> declaration, <metadata> blocks, and attributes in editor namespaces such as inkscape: or sodipodi:. Remove an id only after searching the file for # followed by that ID; if anything references it, it must stay.
Check your work
SVG is XML, which is stricter than HTML. One typo and the browser refuses to draw the file. Chrome shows "This page contains the following errors" with a line and column number; Firefox shows an "XML Parsing Error". The usual culprits:
- a tag not closed (
<path d="..." >instead of<path d="..."/>); - a missing or mismatched quote around an attribute value;
- a bare
&in text, which must be written&; - the same attribute twice on one element.
Fix the line it points to, save, reload. Once the file renders, compare it at a small size (16 or 24 px) and a large one (256 px) with the original before replacing it anywhere.