Montag, 3. November 2014

How SVG Fragment Identifiers Work




CSS-Tricks





How SVG Fragment Identifiers Work



I've talked a good bit about SVG's <use> around here and using it to build an icon system. The beauty of <use> is that you can reference just a part of some SVG defined elsewhere and draw just that part somewhere else. That ability allows you to build a whole system out of it, solving the "many images in one request, because that's super efficient" problem that we've solved in the past with CSS sprites and icon fonts.


But <use> means inline SVG. It doesn't help you when you want to use a part of a larger SVG in SVG-as-<img> or SVG-as-background-image. That's where fragment identifiers come in.



Getting the SVG Ready For It


One way to do this is to lay out the SVG (sprite, I guess, let's just call it a sprite) like a graphical "CSS" sprite.



We're specifically doing it this way, because we ultimately are going to shift some viewBox numbers around to only reveal a part of this image, just like we used to do with CSS sprites.


In this little mini demo, we're using three icons that are 32x32 each. So the document is 32x96. We could think of the viewBox shenanigans this way:



















Whole document viewBox0 0 32 96
Just show top icon viewBox0 0 32 32
Just show middle icon viewBox0 32 32 32
Just show bottom icon viewBox0 64 32 32

The viewBox attribute goes: left, top, width, height. Note that second attribute, the top, notching up by 32 each time. We're just showing a different part of the whole document.


Adding those special viewBox's into the SVG itself


You can drop those special, specific viewBox values into the SVG in a <view> element, that is specifically for this:


<view id="icon-clock-view" viewBox="0 0 32 32" />
<view id="icon-heart-view" viewBox="0 32 32 32" />
<view id="icon-arrow-right-view" viewBox="0 64 32 32" />

Now we'll be able to reference and use those values from elsewhere.


The <view> elements can be stand-alone like this, or they can actually wrap other elements, in which case that viewBox takes hold when the ID matches, so


<!-- this viewBox takes over if current fragment identifer is #match-me -->
<view id="match-me" viewBox="0 64 32 32">
<rect ...>
</view>

Demo of this kind of thing in the spec.


Syntax for HTML


To apply those special viewBox values to SVG-as-<img>, you could do it like this:


<!-- top icon -->
<img src="sprite.svg#svgView(viewBox(0, 0, 32, 32))" alt="">

Or, if you set up <view> elements already, you can just reference them by name:


<!-- middle icon -->
<img src="sprite.svg#icon-heart-view" alt="">

Syntax for CSS


You can declare a special viewBox right in the image path in the CSS:


.icon-clock {
background: url("sprite.svg#svgView(viewBox(0, 0, 32, 32))") no-repeat;
}

Or reference a <view> element if you have those set up:


.icon-clock {
background: url(sprite.svg#icon-clock-view) no-repeat;
}

Although... if you're using SVG through CSS this way and went through the trouble to set up the SVG all spaced out like this, you might wanna just use the CSS sprite technique and shift the background around:


.icon-heart {
background: url("sprite.svg") no-repeat;
background-size: 32px 96px;
background-position: 0 -32px;
}

I just wanna stack the icons on top of each other.


If the icons all have the same viewBox and you essentially just want to hide/show them as needed, this can get a little easier.


Design them all in the same space (or use a build tool that does it or whatever). Here, I'm putting each icon in it's own group with a unique ID.



The trick to making the hide/show work then is embedding some CSS that 1) hides everything 2) reveals the one with a matching fragment identifier. CSS is up for the job, because of the :target selector.


All together in the SVG:


<defs>
<style>
g {
display: none;
}
g:target {
display: inline;
}
</style>
</defs>

<g id="icon-clock">
<path d="M20.6,23.3L14,16.7V7.9h4v7.2l5.4,5.4L20.6,23.3z M16-0.1c-8.8,0-16,7.2-16,16s7.2,16,16,16s16-7.2,16-16S24.8-0.1,16-0.1z
M16,27.9c-6.6,0-12-5.4-12-12s5.4-12,12-12s12,5.4,12,12S22.6,27.9,16,27.9z"/>
</g>
<g id="icon-heart">
<path d="M32,11.2c0,2.7-1.2,5.1-3,6.8l0,0L19,28c-1,1-2,2-3,2s-2-1-3-2L3,18c-1.9-1.7-3-4.1-3-6.8C0,6.1,4.1,2,9.2,2
c2.7,0,5.1,1.2,6.8,3c1.7-1.9,4.1-3,6.8-3C27.9,1.9,32,6.1,32,11.2z"/>
</g>
<g id="icon-arrow-right">
<path d="M32,15.9l-16-16v10H0v12h16v10L32,15.9z"/>
</g>

Browser Support


Can I Use tracks support for fragment identifier. Unfortunately it's not quite as simple as works-or-not, because depending on the browser it might work in HTML and not CSS or have quirks.


Here's my test page:


See the Pen SVG Fragment Identifiers in HTML and CSS by Chris Coyier (@chriscoyier) on CodePen.


I haven't made super detailed browser support notes for this, but here's the highlights:



  • Firefox does everything right.

  • IE 11 does everything right. IE 9 & 10 are a little weird with background-position (squishing) but otherwise works with all.

  • Current versions of Chrome/Safari/Opera (38/8/25) handle all the HTML <img> techniques well, but none of the CSS techniques, including the background-position one. Pre-Blink Opera was the same, interestingly enough.

  • The only thing iOS 8.1 can handle is <img> referencing a <view>.

  • The only thing Android 4.4 gets right is background-position (the one that's not really using fragment identifiers at all). Android 5 matches current Chrome/Safari/Opera as above.


Linkage!





How SVG Fragment Identifiers Work is a post from CSS-Tricks








Samstag, 1. November 2014

Sponsor: Wufoo




CSS-Tricks





Sponsor: Wufoo



I'm posting this just as a big ol' high five to Wufoo for being a long time sponsor of CSS-Tricks.


Wufoo is a web app for building web forms. Things like contact forms, conference registration forms, t-shirt selling forms, wedding RSVP's, you name it. You put the forms on your own site (if you like). They work on small screens. They don't get spammed. They save their data forever. They can be multi-page and use logic. Everything you need a form to do.


As many of you also know, I was a somewhat early employee of Wufoo back in the day. I'm still quite proud of the work we did at Wufoo and I'm happy with Wufoo today. I use the crap out of Wufoo. Every single day, it powers nearly every single form on all the sites I work on, and a bunch more that I built a long time ago and are just quietly still working great. It's reliable, feature-rich software that just does what it does very well.


Direct Link to ArticlePermalink



Sponsor: Wufoo is a post from CSS-Tricks