Inline SVG control with css


Yikes. It's apparently been forever since I last wrote something. I've since one full time at Planned Parenthood Federation of America. It was part time and temporary for the last year and a half or so, but now it's legit. Benefits and everything. 

We're doing some pretty amazing stuff with phase two of the site. There's a little bit of a preview you can check out here. I'm really happy with the markup and the editing, and there's a ton that I've learned putting it together that I could talk about. 

So, trying to get myself back in the habit of blogging to share some of this stuff. Starting off with something kind of simple that I've been working on the last couple of days; using an inline svg file as a play / pause icon for a video.


The Challenge

I'm working on some embedded youtube player for an upcoming section of the site, and need to get the play / pause icons created as an svg. I went through a lot of research trying to figure out the 'best' way to do it. There are a ton of different ways that it could happen.

I ended up going with embedded directly mostly because I had four different states to deal with. It's more complicated than is shown here, but there were a lot of css transitions and other considerations that went into the decision. But needing stopped, stopped hover, playing, playing hover, paused, paused active, a thumbnail was one of the main reasons. I wasn't able to get the control I needed with many of the other options. 

The Simplified Version

See the Pen JoVOJK by Jeremy Werst (@herent) on CodePen.

No fancy transitions or actual video. But it's basically how everything works. Keep reading for more details on what's going on. 

Prepping the Files

When I first got the files, they were four different .svg files. Thankfully, simple items like these icons are actually really small as far as actual text content. They're also just xml, so picking out the paths was pretty simple.

Thing is, the xml in the files that I got from the designers had a lot of extra cruft from Illustrator. And a lot of whitespace. I'd need to clean it up. After a lot of searching for an online generator, I finally found a node.js command line tool called svgo that was much more functional. I'm sure it will get a lot of use on future projects. There really weren't any tools that worked as well, so no easy links for people that don't like the command line. 

Embrase the command line. It will do you good. ;)

So, with a single command, I converted an entire folder of .svg files (including the other icons on the site that I'll be doing this with) in less than a second. They went from something like this:

It really is pretty amazing how small you can get with .svg files. Some of the ones I was processing ended up being less than 500 bytes total. That's insane compared to old school images. Looking at the source like this, it's really obvious why that is. 

Integrating Into Markup

Now that I had my files, I needed to figure out what to keep from each one. I opened one of the files and copied it wholesale into my html file.

The first item is the paths. That's what defines the entire shape. I took one from the play icon, and one from the pause. Then I gave each one a class so it could be targeted with my css.

Next up was grabbing the fill and opacity values from the different files they gave me. I wasn't aware that you could target the fill of a shape with css like that, but apparently you can. So I was able to strip them off of the paths. 

After that, it's down to just the class and the 'd' attribute - everything else is gone. 

Writing the SASS

It's a little hard to see it here, but a lot of the reasoning behind markup here is influenced by my overall code architecture. The pages are set up with a lot of different sections and I kind of scope from there. So it might not make the most sense to people looking at the code above why it's nested like that. Just kind of my preference, I guess. One of the main reasons I love SASS is this nesting - I've been able to really precisely control the inheritance, and by doing this I can avoid having a lot of un-semantic classes.

So what is in the CodePen above uses opacity instead of display because of how I'm extending the hover states. It could use display: none; or any other way to show and hide the paths as needed. The full version also has the option for users to add a tinted color to the player when it's not actually playing; that also needed to be animated with opacity. If it just had visibility, then the overlay (even if clear) means that you don't get the pointer cursor... Lots of little stuff like that.

There were some blind alleys on the way

Like I said beore, there are a lot of different ways to use .svg files. So I tried doing it with the image tag but couldn't target the paths. So then tried as a background image in css as a data-uri. I did get the svgs showing that way, and it was nice to kind of just have them directly in a single sass file available to use everywhere you need. It's not something that you'd want to use a lot for perfomance reasons, but for small items it would be great.

Subject of another post, regardless, I couldn't target the paths that way. Could change the image shown, but that was it.

What's Next?

Well, I'll be using this on a lot of different things, but sadly it's not going to work everywhere. I'm lucky enough that most of our target browsers handle it. It feels like I'm just kind of scratching the surface, though. So much potential.