Problem/Motivation
We need some guidelines for svg & svg icons for Drupal core.
The issue have come up during the work on the RSS icon #2427213: Replace feed.png with feed.svg
To sum it up we need Guidelines:
- How should a svg icons be created stroke's / vectors
- Which apps do we want it to support (sketch, illustrator ...)?
- must be editable colors with css (inline) ?
- Does it even matters & by having "guidelines" the design community will pretty much move on, as they want it to look pretty, not use time on svgo optimization etc.
Proposed resolution
Write a guideline... here is a start:
Goals of SVGs:
- Support high-resolution displays automatically -- because SVGs are vectors they can scale up to any pixel density without losing clarity.
- Replace as many static image assets in core as possible -- static image assets (jpgs and pngs) currently in Drupal core are not scalable, and do not support hi-res displays so we should attempt to replace as many of them as possible.
- Lay framework of best practices that contrib can adopt -- this could mean demonstrations of both inline svgs (ie inside twig templates) as well as external svg assets in core.
Best Practices
- Avoid bikeshedding on design
When converting from existing raster images to vector images, it is better to maintain the existing image size (dimensions) and colors from the originals, to minimize scope creep on the issue queues. There are many examples of endless design-by-committee tickets on the issue queues that languish for years, ultimately to be abandoned because a redesign opens up too many unanswerable questions.
- Minimize file size
Since these little icon files are assets that will be loaded (downloaded) millions of times across millions of websites, one of the most important tenants is to require the smallest file size possible for the SVGs in core. So just as "profiling" the server-side implications of changing each phptemplate into twig, so important is it also to ensure SVG files are optimized and even potentially minified. This means manual (or automatic) removal of all "crap" produced by vector design applications like Illustrator, Sketch, and Inkscape. Removal of these elements should not inhibit editability in these applications as the resulting SVG still conforms to the spec.
There are not so many graphics in Drupal core, so it is not problematic to have high standards here. Once created, the SVG file could be unmodified for years.
There are a number of ways to optimize SVGs including via the
svgocommand and/or optimized manually -- each of which might produces better results in different cases. The best method usually depends on the complexity of the SVG. For example, the points required for a rounded rectangle as a<path>end up being more code than using a<rect>with therxandryattributes to give the rounded corners. The strategy can be that a designer can create the SVG and someone else can optimize it with svgo or by hand. - Validate against SVG 1.1
All core assets should pass through the validator http://validator.w3.org successfully. Although, we can ignore the "DOCTYPE missing" error, it seems not necessary and to be removed in SVG 1.2 according to MDN documentation article (about namespaces)
- Indentation & coding standards
- SVG is markup, and therefore should use proper indentation (2 spaces). SVGO strips whitespace by default, so this is something we should maybe discuss further if to sacrifice readability vs weight
- Like CSS standards, use lowercase hex colors for fill and stroke.
- Path precision on small files should be rounded to 1 or 2 decimal places, when necessary. Prefer whole integers when possible. One common technique to reduce size is by bumping up the size of the viewBox by a factor of ten in order to completely remove the decimals.
- Use SMACSS class structures on SVG tags, particularly when there is more than one of the same tag in an SVG. This will facilitate easy style overrides from a theme's CSS.
- Like CSS standards, classes should be preferred to ID attributes. ID attributes should be stripped, unless they are used as Fragment Identifiers
- Default presentation attributes (fill/stroke/etc) should be moved off from SVG tags if it reduces the weight, and placed as Internal CSS (inside a
<style>tag). Note: this is a manual procedure, there are not many tools to automate this process. Try Illustrator CSS Properties: SVG Elements in the SVG save settings - Do not base64 encode inline SVGs -- there are serious performance implications in doing this.
- Ultimately, SVG files should be created with inline-embedding in mind even if currently only used via reference in CSS or IMG tags. Inline SVGs come with additional limitations that developers should be aware of:
- If the image/icon typically shows up near text and inside links, then the SVG can be considered decorative, and the
aria-hidden="true"andfocusable="false"attributes should be added to the root SVG element. - Ensure the
height,width, andviewBoxattributes are always present. SVGO sometimes strips out one or more of these attributes. - Avoid SVG features requiring IDs and fragment identifier refs (e.g., filters, masks, gradients). Using ID attributes inside inline SVGs presents potential "duplicate ID" warnings when embedding the same or similar SVGs multiple times in one HTML doc.
- If the image/icon typically shows up near text and inside links, then the SVG can be considered decorative, and the
- Inline SVG Vs external SVG
There is no single right answer to inline versus external SVG.
Inline SVG (i.e. SVG images embedded directly inside twig templates) is preferred over external SVG asset files added via
<img>tag, or referenced in CSS backgrounds, in cases where SVG needs to be manipulated (e.g. animated or color changed) via CSS or JavaScript, whereas external SVGs referenced in CSS backgrounds cannot.When SVG does not need manipulation, keeping them as external assets has the benefit of SVG files being cached by the browser.
We need to weigh the pros/cons and analyze the SVG Sprite option also (less HTTP requests, and cacheable).
Consider also that HTTP 2.0 is minimizing the benefit of "saving HTTP requests".
- Fallback methodologies
Although SVG is widely supported, there are some exceptions, like IE8. There is barely any consensus on the "best way" to support fallbacks. If using inline SVGs (as is the best practice), then by and large the best fallback method has to be the SVG
<switch>structure, because it is the only foolproof fallback method that has no dependencies on javascript. The switch tag requires the first element be a group tag<g>followed by a single<foreignObject>tag containing the fallback<img>inside.Other fallback methods available: Use
.no-svgand.svgclasses in css to provide background image fallbacks. Because this fallback method requires modernizr javascript be loaded on the page, this is an inferior solution that should only be considered as a last resort. - SVG Accessibility
SVG Accessibility is only really applicable to inline SVGs. Inline SVGs can be be given text alternatives by adding a
<title id="title">tag inside the SVG and referencing this using anaria-labelledby="title"attribute on the<svg>tag itself, i.e.:<svg aria-labelledby="title"> <title id="title">Alternative text goes here</title> <!-- Remaining SVG code follows. --> </svg>ARIA support is introduced officially into the SVG 2.0 specification, but it is still possible to use ARIA with SVG 1.1 content. Some examples in this article will raise a flag when you validate your HTML, but it’s a reasonable exception to make.
-- Léonie Watson Tips for Creating Accessible SVG (Sitepoint article)
If the image content is purely graphical, add the
role="img"attribute to the<svg>tag. If the SVG is interactive, make use of<text>tags for readable text and make the interactive elements focusable by wrapping them in<a xlink:href="http://example.com">tags. - SVG Localization
SVG can contain text. So if we use<title>and<desc>for accessible labels, these will need to be localizable.
Can we generate SVG using Twig? How do we cache these per locale?The current recommendation is that text in SVGs (particularly visible text) should be avoided. As stated on a blog post from Una Kravets:
Running the website through the web interface Google Translate Tool could possibly translate the SVG text if the character glyphs exist in the specified font, but may also break the SVG due to viewbox constraints. So even though the diagram text is highlightable, don't rely on SVG images to be the tools you need for text translation.
Tools & Resources
- Optimization:
https://jakearchibald.github.io/svgomg/
https://github.com/svg/svgo
https://github.com/svg/svgo-gui
https://github.com/davidderaedt/SVG-NOW - A Compendium of SVG Information
- SVG `symbol` a Good Choice for Icons
- Using ARIA to enhance SVG accessibility - very detailed information about the state of browser and screenreader support, as of December 2013
- Tips for Creating Accessible SVG
Comments
Comment #1
corbacho commentedThanks for opening the issue. I think is needed. SVG is a dual technology, it's markup and image at the same time. So I agree it's tricky to make "guidelines" for it, because it depends on the use case.
These things cross my mind now:
* Validate against SVG 1.1 ? http://validator.w3.org
* SVG shouldn't have any "trace" of crap, it should be as clean as possible. For performance reasons (less weight, the better) and for readability and cross-compatibility.
SVG is a markup language. The same way that we wouldn't accept the crap HTML+CSS that Dreamweaver outputs (even if it's valid) why we should accept the level of crap that Illustrator/Sketch outputs ?
* SVGO takes 1 second, and automate 90% of the process. Why not use it ? The default settings are good.
* Styling with Internal CSS (instead of inline CSS), is something really cool that can save bytes and cleaner output. This normally requires manual manipulation, it's something SVGO can't do for you.
http://www.w3.org/TR/SVG/styling.html#StylingWithCSS
I know that there is nowadays very few tools to help with some steps, and it's quite manual process.
But in the other hand, there is not so many graphics in Drupal core.. I don't think it's problematic to have high standards here. Once created, the SVG file could be unmodified for years.
Designers can post their designs in drupal.org, and somebody else optimize it. Not all steps needs to be done by the designer.
Comment #2
jwilson3Added a few things to start the guideline out. First and foremost a clear set of goals for SVG in core. And secondly what I consider to be the most important tenant: file size optimization.
Since these little icon files are assets that will be loaded (downloaded) millions of times across millions of websites, one of the most important tenants is to require the smallest file size possible for the SVGs in core. So just as "profiling" the server-side implications of changing each phptemplate into twig, so important is it also to ensure SVG files are optimized and even potentially minified.
Comment #3
jwilson3Added some of comment #1 to guidelines.
Comment #4
jwilson3Comment #5
jwilson3Comment #6
jwilson3Comment #7
jwilson3Comment #8
jwilson3Comment #9
jwilson3Comment #10
jwilson3Comment #11
jwilson3Comment #12
mortendk commentedd a m n ! :)
Comment #13
jwilson3Bringing over discussion started on #2427213, from mortendk:
So apparently svgo has trouble optimizing certain things, such as masks created in Sketch. It's very possible there are other things svgo cannot handle well.
Additionally, if you're using a mask, then you're essentially hiding data points from view. This is useless data that adds to SVG file size bloat, so in most cases, there is an alternative way to create the path/object you want, that may even (not always) result in a smaller and less complicated SVG file. In Illustrator one would expand the paths and or instead of a mask, overlay what would have been the mask layer on top -- select both layers and use the "Crop" button inside the "Pathfinder" pane, this would result in a simple single
<path>element.So, I believe that best practices would dictate that we should stick to the utter basic SVG elements for three reasons:
Comment #14
jwilson3Added point about accessibility.
Comment #15
jwilson3More changes on accessibility.
Comment #16
jwilson3A place for links to tools and resources.
Comment #17
mortendk commentedA quick thoght what do we know about optimization from popular apps, lets face it designers are a bunch of lazy f.... so lets help em out.
In sketch i found these 2 tricks for fixing exporting of svg
sketch 2.2:
in the terminal paste in:
remove svg crap
defaults write com.bohemiancoding.sketch3 exportCompactSVG -bool yesadd in svg crap
defaults write com.bohemiancoding.sketch3 exportCompactSVG -bool noComment #18
jwilson3In Illustrator:
* Always use: Object > Artboards > Fit to Artwork and ensure the artboard starts at point 0, 0.
* Object > Path > Simplify can provide VERY REAL optimizations for paths with a lot of little "dots" (vertices) near one another.
This also reminds me that we need a section in the guidelines about responsive SVGs.
Comment #19
corbacho commentedGreat job jwilson :)
Updating issue summary with some comments and also notice this:
SVG validator demands a DOCTYPE, but it seems not necessary and to be removed in SVG 1.2 according to MDN documentation article (about namespaces)
Comment #20
Crell commentedjwilson3: Are there any standard guidelines about responsive SVGs? It's an area that is rather confusing to me, and when I last went googling for leading practices I didn't find much.
Comment #21
jwilson3@Crell: I've found and read about a few guidelines for responsive SVGs, but have not tested any myself in cross browsers. Some of them depend on having a wrapper tag around the svg itself -- which frankly sucks.
The cleanest solution I know of is to set
width="100%" height="100%"on the<svg>tag. By default, this will scale up the vector graphic to it's container element -- whcih can have drastic effects for a small inline SVG "icon" plopped onto the page (like a feed icon). So then if you don't want the image to scale UP larger than the SVG's own viewbox size) you can set a max-width rule on the style attribute on the svg tag, to the x-width dimension of the viewbox property. Eg:The inline style is a bad example because if you're making a small icon responsive, you'll probably want to manipulate the max-width in an external css file, where you can use media queries, etc.
Comment #22
FAAREIA commentedHi, i have been using SVG in my latest proyects, including Drupal proyects. This is my experience:
Responsive SVG
preserveAspectRatioattribute in you svg. Check link 01 and link 02Inline SVG
Method #1 - Inline
Advantages
<title>and<desc>Disadvantages
Method #2 - IMG
<img src="img/logo.svg" alt="Company name">Advantages
<title>and<desc>Disadvantages
Method #3 - Inline SVG identifiers
<svg><use xlink:href="img/icons.svg#logo"/></svg>Advantages
<title>and<desc>Disadvantages
SVG Background
Method #1 - CSS background
Advantages
Disadvantages
Method #2 - Fragment identifier:
Advantages
<title>and<desc>Disadvantages
Crafting the SVG
This is the method i have been using. It works crossbrowser and on mobile. It won't work on browsers which do not support svg.
Explanation
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">.<symbol>tag<symbol>must have it's ownidandviewBoxattribute.preserveAspectRatioattribute if it is not default ("xMidYMid meet").<title>and<desc>tag for better accesibilityReferences
Comment #23
corbacho commentedReplying #2426967: Feed icon should be a CSS background image not a image file. where jwilson listed a list of pros to inline SVG.
With the forth-coming HTTP 2.0 the number of HTTP requests is not anymore an issue. So "saving" HTTP requests won't be a problem anymore (as I understood).
Inlining SVG in the templates is only good for advanced manipulation (via css or JS)... but it has a main disadvantage: It can't be cached by the browser
So it has to be a decision taken case-by-case. We can't generalize in the guideline with a single advice.
FAAREIA guidelines style, with pros/cons is quite good idea to have.
Comment #24
rikki_iki commentedI've been working on this for a project and made this codepen to work out the kinks in various scaling methods, most of which has already been mentioned above but might be useful to see in action... http://codepen.io/rikki-iki/pen/rVxaNj (consistent across all supported browsers). I did find that inline SVGs in IE required both a height and width set in CSS which can cause problems when the container is smaller than the viewBox or css dimensions (see example 4).
Regarding fallbacks, I haven't tested it yet but the idea of using
<picture>sounded really interesting http://sarasoueidan.com/blog/svg-picture/Comment #25
jwilson3Comment #26
jwilson3Another angle to discuss: SVG Animations -- namely "SIML" which currently has fairly poor browser support is being considered on #1974928: Update Drupal's default throbber icons. The thought is that for browsers that don't support the animation, a fallback to a simple color change would be sufficient. I'm certainly in favor of a solution like that, but if anyone objects to the visual regression of these older browsers losing the icon rotation, speak up.
Comment #27
andrewmacpherson commentedFleshed out the
aria-labelledbyexample, to make it clear that the value is an ID attribute, not the element name.Comment #28
andrewmacpherson commentedminor edit, add list markup to Problem section.
Comment #29
andrewmacpherson commentedAdded the links from #22 to the Resources section, using the actual titles of the articles.
Comment #30
andrewmacpherson commentedDo we want to make use of the want to target SVG's
<desc>element using thearia-describedbyattribute? (For details see the SVG accessibility articles linked in the issue resources section.)i.e.
We are already making widespread use of aria-describedby in D8 core, notably with Form API output from
\Drupal\Core\Form\FormBuilder::doBuildForm().Tagging accessibility so we can get more views on whether this is useful for our images.
Comment #31
andrewmacpherson commentedComment #32
andrewmacpherson commentedIf we do use
<title>and<desc>in our SVG, these will need to be localizable.This might mean we can't have static SVG assets. However, I'm assuming Twig can be used to generate arbitrary XML, not just HTML? So perhaps we could have files like
feed-icon.svg.twig.Comment #33
andrewmacpherson commentedAdding localization of
<title>and<desc>to main issue summary.Comment #34
andrewmacpherson commentedFrom the related issue, comment #50 in #2427213: Replace feed.png with feed.svg, Lewis says
Comment #35
mgiffordAdding
<title>and<desc>would be a great accessibility enhancement.Comment #36
andrewmacpherson commented@mgifford Some more discussion cropped up about this in #2427213: Replace feed.png with feed.svg. The title and desc elements would need to be translatable. Having them embedded inside the SVG would mean having to generate/cache separate SVG images for each translation. This is quite different from a PNG where we would put image file and fallback text in separate src/alt attributes. The feed icon issue eventually stuck with the span.visually-hidden fallback text, to avoid this issue.
Comment #37
jwilson3If the svg were embedded inside a twig template itself, then the translatable text would be a non-issue. I'm not opposed to trying this, but it also needs more discussion, for example there are people that are talking about adding a single SVG at the top of the dom (or could be after the footer) that is essentially an svg sprite of all the svg images used on the page and then referencing them using the #id svg sprite method. To do that in core would be a pretty significant undertaking, requiring some global thing keeping track of each svg, adding it to the sprite with an id, and adding in the placeholder svgs in its place. OOS for this issue, but certainly using a twig template that produces inline svg could be an idea we could entertain as a first step towards better a11y.
Comment #38
joelpittetComment #40
jwilson3Added a note to the issue summary from https://una.im/a11y-for-the-masses/ about watching out for text in SVGs.
It suggests that you should not put raw text strings into SVG because Google Translate and other providers cannot translate the text appropriately, and also brings up the great point that if we start allowing text in the svg for things like
<title>and<desc>then people will be tempted to put visible text in there as well, and transliterated visible text in SVG might completely break the svg drawing when you take viewport size restrictions into account (ie, foreign language text in more verbose languages might get cut off).I think it will be hard to get Localization right, and still maintain Accessibility.
Comment #41
andypostComment #43
idebr commentedAdded #2694535: Support rect property and nested render arrays in html_tag for dynamic SVGs as a related issue.
Comment #44
yoroy commentedI wonder how we can best balance pragmatism (so that we can move forward and make nice changes) and standardisation (making sure we're doing the right thing).
#2775725: Update the throbber icon is getting somewhat stalled on a decision about how to handle SVGs. Maybe people who are interested in this can have a look and chime on that specific case? Thanks!
Comment #57
mgiffordWith inline SVG we can manage multilingual content in Twig.
Lots to pull on from here https://cariefisher.com/a11y-svg-updated/
Comment #58
hudriPlease don't do this, especially not in core. I even propose to avoid CSS styles and encourage the use of presentation attributes, as they are very easy to overrule in CSS by contrib+custom modules and themes. To avoid repetition and weight, better use an intermediate group (e.g.
<g fill="currentcolor">) instead.Do not re-enter the dark age of CSS selector specifity battles
Comment #59
skaughtComment #60
jwilson3Re #58:
I tend to agree, but I feel like it is hard to make call one way or the other. It seems to me that this is highly dependent on how complex the SVG (or group of SVGs) is and how many attributes there are that would be shared/duplicated. Furthermore, there is a good argument that by using classes instead of inline attributes, the classnames become the api, giving core the freedom to change/tweak things like hex colors getting converted to rgb or CSS attributes eg
path.something {fill: var(--my-color, #00ff00); }without breaking the overrides in your custom theme. (Even just fixing the case of the hex value which might seems innocuous enough, would break your theme override since attribute selectors are case sensitive (path[fill="#00FF00"] != path[fill="#00ff00"]).To reframe my point in the context of your example on comment #58...
This:
Seems much less fickle than:
In the second example, if the SVG from core or contrib ever changes the fill attribute value, your theme override breaks. I could be wrong here but it seems unexpected that the fill attribute value is the API, and OTOH, much more obvious that a classname is an API, and has been purposefully added in the SVG to make theme overrides more stable.
Comment #61
jwilson3I've pulled over a few additional best practices from the current issue I was working on #3521857: Update Drupal's default file type icons to use SVG.