ryelle / WP-Dashboard-SVG

A demo of using an SVG sprite for the WordPress admin icons.
http://ryelle.github.io/WP-Dashboard-SVG/
21 stars 4 forks source link

Inline vs External SVG #1

Open ryelle opened 9 years ago

ryelle commented 9 years ago

Came in up chat: how should we include the SVG?

Currently using this method (but without the JS fallback): http://css-tricks.com/svg-use-external-source/

chriscoyier commented 9 years ago

This is what I think is the best way...

1. Folder full of SVG icons as the base.

screen shot 2015-03-12 at 1 27 10 pm

2. A build step of some kind to smoosh them into a file

Probably like icon-symbols.svg. Class build tool is like grunt-svgstore, but there are many.

<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0" class="visually-hidden">

 <symbol id="icon-whatever" viewBox="0 0 100 100">
    <!-- Not putting <title> or <desc> here on purpose, will use on case-by-case basis --?
    <path d="M6-0.076-0.02 …
    <path d="M16-0.36-1.09 …
  <symbol>

  <!-- and so on... put all of them in here -->

</svg>

This same build process should probably build PNG versions as well. Like star.svg should be processed into a star.png for use as a fallback. Possibly just use Grunticon?

3. Test for inline SVG support.

Best method:

var supportsSvg = function() {
  var div = document.createElement('div');
  div.innerHTML = '<svg/>';
  return (div.firstChild && 
    div.firstChild.namespaceURI) == 
      'http://www.w3.org/2000/svg';
};

4. Logic for support or non-support

Probably put this in the <head> - blocking but fast.

if (supportsSvg()) {

  // Ajax for the  icon-symbols.svg file

} else {

  // We’re going to need a fallback

}

5. If supported, Ajax...

Grab the file and drop it in body. The point of this is that it's browser cached. But... that depends on proper headers, can you count on that in WordPress land?

var ajax = new XMLHttpRequest();
ajax.open("GET", "icons-symbols.svg", true);
ajax.responseType = "document";
ajax.onload = function(e) {
  document.body.insertBefore(
    ajax.responseXML.documentElement,
    document.body.childNodes[0]
  );
}
ajax.send();

Alternative is to PHP include the icon-symbols.svg right onto the page. The only issue there is it's a bit bloaty for non-supporting browsers that

6. If NOT supported, fallback...

There are a variety of fallback methods...

  1. Grunticon method - set a background-image on the <svg> element itself, load a CSS file that has all the .png icons in Data URI's in that stylesheet. Apply that class to the SVG's, like <svg class="icon-star" ... > - Grunticon builds the CSS file and provides a loading mechanism for it (e.g. grunticon([])). This really only works for IE 8 though, and IE 8 doesn't have background-size, so you have to be super careful to create the .png versions the exact size you need them.
  2. Grunticon with deeper fallback - insert the SVG's like <div class="icon-star"><svg ... ></svg></div> and apply the background-image to the div instead. Works back to IE 6 even, with the Grunticon loader detecting for Data URI support
  3. Trickery - insert the SVG like: <svg ...> ... <image src="star.png" /></svg> - supporting browsers ignore that (even prefetcher), non-supporting browsers ignore the SVG part but load the img. Bonus here is you can resize the PNG's. Negative is every single icon is a separate request.

Alternative to that whole setup...

Just use Grunticon wholesale. It would be simpler, it's just not my favorite because it locks you into that setup forever. You're using a meaningless <span> in the markup that requires Grunticon (both the build and the JS) to work.

It's probably best to define some more goals for this project. Like clearly defined browser support requirements, build tool possibilities, whether you need to support no-js or not, etc.

ryelle commented 9 years ago

Our browser support etc are determined by WP core. Pulled from our autoprefixer settings, we say we support Chrome 21+, Firefox 17+, IE7+, Opera 12.1+, Safari 6.0+, Android 2.1+ – But for the older browsers, like IE7, I know we can get away with "not broken".

I think we've had the no-js conversation for fallbacks before, I'll see if I can look that up.

joemcgill commented 9 years ago

Here's the exhaustive compatibility list for SVGs: http://caniuse.com/#feat=svg (click 'show all')

dechowdev commented 9 years ago

How about using SVGInjector by the Iconic team?

This inlines the SVG (making the styleable) using only an IMG tag - and it utilise a PNG fallback :)

https://github.com/iconic/SVGInjector

chriscoyier commented 9 years ago

The issue with SVGInjector is that the markup you use is:

<img class="inject-me" src="image-one.svg">

Which means that the prefetcher will trigger HTTP requests for each of those images individually. 20 icons on the page, 20 HTTP requests. It's kinda nice when building an icon system to get that down to 1.

dechowdev commented 9 years ago

First of SVGInjector is cacheable Secondly SVGInjector can utilise a data-src attribute:

Any DOM element, or array of elements, passed to SVGInjector with an SVG file src or data-src attribute will be replaced with the full SVG markup inline. The async loaded SVG is also cached so multiple uses of an SVG only requires a single server request.

This is one of the examples that they also show on the page

<style>
  .thumb-green {fill: #A6A93C;}
</style>
<img class="thumb-green inject-me" data-src="svg/thumb-up.svg" data-fallback="png/thumb-up-green.png">

So it does not make a subsequent request if that's what you are referring to?

However, there are some kickbacks from using a SVG spritesheet. Which is for one responsive, how can we trigger they correct icons on the different screen states? Also how are we letting plugin developers attaching their own icons to an example a menu item in the dashboard?

chriscoyier commented 9 years ago

That looks better for sure. It kinda seems like it doesn't address spriting though (like making sure only 1 request is made for all icons). Maybe that's not a big deal for WordPress? I dunno. It's always a big deal to me, but your icon system I think needs to be author-extendable, so maybe it's better if it's not sprited. There are kind of a lot of icons on any given WP admin page though, plus the current icon font system is essentially a one-request sprite, so probably best to be at least that performant.

melchoyce commented 9 years ago

Also how are we letting plugin developers attaching their own icons to an example a menu item in the dashboard?

This is actually already possible (but apparently is a little janky?): http://mannieschumpert.com/blog/using-wordpress-3-8-icons-custom-post-types-admin-menu/

Right now plugin authors can add their own svgs, set of pngs, or an icon from the Dashicons font.