Woodshop SVG: Studs and Shelves

Published 7 months, 4 weeks past

As I’ve worked on my indoor workspace, I’ve continued to find SVG useful for planning purposes, and putting it to use in my planning has pushed me to learn more about the language.  (That last sentence is actually a play on words, for reasons that I hope will become clear by the end of the post.)

For example, the basement room I’m partially turning into a workspace has a set of exposed framing studs (exposed once I removed a couple of cabinets, anyway) that I wanted to turn into a set of rough shelving, so that I could organize the various bits ‘n’ bobs I accumulate: leftover bolts, extra pullchain, and so on.  These studs are perched on foundation cinderblock, about 48 inches off the floor, and run up to the ceiling from there.

Each stud is 28 inches tall, running from a 2×6 base up to a stacked pair of 2×6 crossbeams.  They also have strips of 2×10 mounted vertically at their bottoms, running between each stud.  (I’m not entirely sure why the 2×10s are there, but I’m not about to start ripping them out now.)

The distances between subsequent studs is also not consistent: they’re mostly close to 16 inches on-center, but not perfectly so, and the last set is only 12 inches apart because the framing ends where a set of stairs begins.  So I created a schematic, including a red box to mark where a 1-gang electrical box. protrudes from the other side of the wall.

The middle stud is taller as a reminder to me that, if not for the crossbeams, it could keep going up past the ceiling joist.  The others are essentially centered on the joists above them (centered within half an inch or so, anyway).

Why does that matter?  Because to make the shelves, I decided to mount 2×6s in front of the framing studs, to allow for shelves 11 inches deep.  So in cases where the studs are centered below ceiling joists, I can run the front-mounted 2×6es up to them.  In that middle case, I’ll actually need a longer 2×6 to run up next to the joist.

This all might sound like a lot of work to deal with odd circumstances, but that was part of the point of this part of the project.  We don’t always get to work in ideal circumstances.  Learning how best to work around the existing limitations is a valuable lesson in itself.

I tried out a lot of different shelf configurations.  At first, I was just using <rect> elements like this.

<rect x="1.5" y="9"    width="14.5" height="0.5" />
<rect x="1.5" y="19.5" width="14.5" height="0.5" />

That’s two shelves, ten inches apart, in the leftmost stud bay.  (The shelves are a half-inch thick.)  That worked okay for a while, but then I decided to show the support rails that would both tie the 2×6s to the studs behind them, and also hold up the shelves.  So that meant more <rect>s, like so.

<rect x="1.5" y="9"    width="14.5" height="0.5" />
<rect x="1.5" y="19.5" width="14.5" height="0.5" />
<rect x="1.5" y="9.5"  width="0.75" height="1.125" />
<rect x="15.25" y="9.5"  width="0.75" height="1.125" />
<rect x="1.5" y="20"  width="0.75" height="1.125" />
<rect x="15.25" y="20"  width="0.75" height="1.125" />

Again, that’s just for the first stud bay: two shelves, and then four supports, two for each shelf.  And I have five bays to do.

Still, it it took deciding to show the storage bins I wanted on the shelves to push to look for a better way.  Basically, what I wanted was a way to define a primitive of a shelf and two support rails, and then just place that.  And then a way to do the same for collections of storage bins, which could be stacked atop each other.

SVG provides for exactly this, through the combination of <defs> and <use>.  I set up a basic shelf set like this:

<defs>
    <g id="shelf">
        <rect x="0" y="0" width="14.5" height="0.5" />
        <rect x="0" y="0.5"  width="0.75" height="1.125" />
        <rect x="13.75" y="0.5"  width="0.75" height="1.125" />
    </g>
</defs>

If you think of that as its own little SVG, it defines a horizontal shelf 14.5 coordinate units wide, and half a unit tall, starting at 0,0.  It then places the two support rails just below, starting half a unit down from the top.

With that in hand, the two shelves I was drawing before collapsed from six lines to two:

<use xlink:href="#shelf" x="1.5" y="9" />
<use xlink:href="#shelf" x="1.5" y="20" />

Suddenly, rather than fiddling with the X,Y coordinates of several pieces just to move a shelf, I could adjust the X,Y of one <use> element.  To say this sped up my workflow would be a monumental understament.  Trying out different shelf spacing and shelf counts went from being a chore to being almost too easy.

This was only magnified when I wrote the definitions for storage-bin primitives.  At first, I drew them the same way I had the shelves, down and right from 0,0, but that was difficult in a number of ways.  Different bin sizes meant I had to do different math to get the bins to sit on the shelves.  And then I remembered that SVG is unbounded on both axes—which meant I could draw the bins up from 0,0, meaning I could give them the same y coordinate as the shelves.

Wait, what?  Let me show you.  Inside <defs>, I wrote:

<g id="bins4">
    <rect x="0" y="-4" width=".15" height="4" />
    <rect x="4" y="-4" width=".15" height="4" />
    <rect x="0" y="-1.5" width="4.15" height="1.5" />
    <rect x="4.2" y="-4" width=".15" height="4" />
    <rect x="8.2" y="-4" width=".15" height="4" />
    <rect x="4.2" y="-1.5" width="4.15" height="1.5" />
    <rect x="8.4"  y="-4" width=".15" height="4" />
    <rect x="12.4" y="-4" width=".15" height="4" />
    <rect x="8.4"  y="-1.5" width="4.15" height="1.5" />
</g>

Everything is drawn starting from above the y=0 line, and reaches down to y=0.  So that first <rect> with height="4" starts at a Y coordinate of -4.  -4 plus 4 equals zero.

That allowed the following:

<use xlink:href="#shelf" x="1.5" y="9" />
<use xlink:href="#bins4" x="2.5" y="9" />
<use xlink:href="#shelf" x="1.5" y="20" />
<use xlink:href="#bins4" x="3.0" y="20" />

See how the y coordinate is the same for both shelf and associated bins?  If I decide to move a shelf up an inch and a half, I just take 1.5 off the y value for the shelf’s <use>, and then use that same value for the y attribute on the bins’ <use>.

Could I have made this even better by combining shelves and bins into a single primitive definition, and only having one <use>?  Yes, if there would only be one set of bins per shelf.  That’s how I dd it in this particular arrangement.  (In this case, the brown vertical studs are actually the 2×6s mounted in front of the wall studs, so they’re taller and based lower.)

However, I also considered stacking bins on each other between shelves, as in this configuration.

That wound up being pretty close to what I did, in the end.

There were a couple of things I wished I could do (or wish I had figured out how to do) in SVG.  The first was a way of varying the width on the <use> elements.  The rightmost stud bay is 12 inches wide, not the 14½ inch bays the others have.  I ended up defining a separate primitive definition for those shelves.

<g id="shelf-sm">
    <rect x="0" y="0" width="12.5" height="0.5" />
    <rect x="0" y="0.5"  width="0.75" height="1.125" />
    <rect x="11.75" y="0.5"  width="0.75" height="1.125" />
</g>

I guess I could have done X-axis scaling transforms on the regular #shelf primitive.  Actually, looking back on it, that probably makes a lot more sense than what I did.  It would have squished the support rails a tiny bit, but not enough to throw off precision cuts or anything.  (There really were no precision cuts in this project—this is carpentry at its roughest.)

The other thing I wanted was the ability to draw “backwards” by giving negative height and width values.  So as an example, I’d have liked to write the rightmost support rail like this:

<rect x="14.5" y="0.5" width="-0.75" height="1.125" />

I know, I know, a negative distance doesn’t really make sense when talking about physical units.  I still wanted to do it.  I mean, it made sense to me in my head.

Just like the idea of hand-authoring SVG to plan out workshop projects made sense to me.  I’m sure I could have done it a little faster and a little more intuitively in a vector editor, but I’d have had to buy one (my copy of Illustrator no longer runs on my Mac, more’s the pity) and if I’d gone that route, I wouldn’t have learned a lot more about SVG and its capabilities.  Either way, the end result is pleasing to me… at least for the time being.


Comments (4)

  1. Interesting that I stumbled upon this post as I am trying to better understand xlink:href in particular.

    I saw on MDN that it is deprecated since SVG2 (https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href) and is no longer recommended. Yet, it seems particularly useful in your examples.

    Do you have any insight into the scope of its deprecation? Is it only for certain elements? The article referenced above isn’t specific.

  2. Hey, Bridget! I used xlink:href because it’s what SVG 1 recommends, and there appears to be little to no interest from browser vendors in implementing SVG 2. And I’d be really surprised if browsers ever removed SVG 1 support, even if they do change direction on SVG 2. See https://css-tricks.com/on-xlinkhref-being-deprecated-in-svg/ for more.

  3. I guess I could have done X-axis scaling transforms on the regular #shelf primitive. […] It would have squished the support rails a tiny bit, but not enough to throw off precision cuts or anything.

    This is a problem with just about any image format I can name and it frustrates me to no end!!

    Image scaling and real-world scaling end up meaning slightly different things nine times out of ten. I wish they could be approximated with two different operations.

  4. Hi Eric. This is a cool use of SVG and a great project! As I was reading and thinking, I found myself comparing this to OpenSCAD syntax . Anyway, I think you’d enjoy playing around with that a bit, too. Have a great day!

Add Your Thoughts

Meyerweb dot com reserves the right to edit or remove any comment, especially when abusive or irrelevant to the topic at hand.

HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <em> <i> <q cite=""> <s> <strong> <pre class=""> <kbd>


if you’re satisfied with it.

Comment Preview