# SVG

* [A Compendium of SVG Information | CSS-Tricks](https://css-tricks.com/mega-list-svg-information/)
* [SVG – Sara Soueidan – Freelance Front-end Web Developer](https://sarasoueidan.com/tags/svg/index.html)
* [Pocket Guide to Writing SVG](http://svgpocketguide.com/book/)
* [Styling And Animating SVGs With CSS – Smashing Magazine](https://www.smashingmagazine.com/2014/11/styling-and-animating-svgs-with-css/)
* [An SVG Primer for Today's Browsers](https://www.w3.org/Graphics/SVG/IG/resources/svgprimer.html)
* [A Practical Guide to SVGs on the web](https://svgontheweb.com/)
* [How Designers Should Think About SVG – Design + Sketch – Medium](https://medium.com/sketch-app-sources/how-designers-should-think-about-svg-b2b92efc4d77)
* [A simple pie chart in SVG. Learning the trigonometry trio — sin… | by David Gilbertson | HackerNoon.com | Medium](https://web.archive.org/web/20210517191254/https://medium.com/hackernoon/a-simple-pie-chart-in-svg-dbdd653b6936)
* [The SVG `path` Syntax: An Illustrated Guide | CSS-Tricks](https://css-tricks.com/svg-path-syntax-illustrated-guide/)
* [Tools to Visualize and Edit SVG Paths (Kinda!) | CSS-Tricks](https://css-tricks.com/tools-visualize-edit-svg-paths-kinda/)
* [Tips for Creating and Exporting Better SVGs for the Web](https://sarasoueidan.com/blog/svg-tips-for-designers/)

Tools:

* [SVG manipulate paths](https://codepen.io/netsi1964/pen/pJzWoz)
* [xvg](https://xvg.now.sh/) - Chrome extension. See [XVG - debug SVG paths in the browse](https://github.com/winkerVSbecks/xvg)
* [SVG Path Builder](https://codepen.io/anthonydugois/pen/mewdyZ)
* [cubic Bézier curve with SVG](http://codepen.io/thebabydino/pen/EKLNvZ)
* [Svgbob Editor - Convert your ascii diagram scribbles into happy little SVG](https://ivanceras.github.io/svgbob-editor/)
* [SVG Path Editor](https://svg-path.com/)

Good to know:

* Presentation attributes will overwrite inherited styles specified on a parent element
* Links inside an SVG embedded as an `<object>` will open inside the boundaries of that `<object>`
* Certain CSS characters like brackets will cause an XML error when used inside an SVG file

### Accessibility

Only `img`, `iframe` and `object` can provide alternative content. `img` only provide text alternative (via the `alt` attribute)

* [Making SVG accessible](http://ljwatson.github.io/decks/2017/lws/index.html)
* [demosthenes.info – Making SVG Accessible](http://demosthenes.info/blog/1026/Making-SVG-Accessible)
* [Using ARIA to enhance SVG accessibility | TPG – The Accessibility Experts](https://developer.paciellogroup.com/blog/2013/12/using-aria-enhance-svg-accessibility/)
* <http://www.sitepoint.com/tips-accessible-svg/>
* <https://github.com/SVG-access-W3CG>
* [Making composed-tree.svg more accessible](http://svg-access-w3cg.github.io/use-case-examples/composed-tree-notes.html)
* [Accessible SVGs | CSS-Tricks](https://css-tricks.com/accessible-svgs/)
* [Managing focus in SVG - ally.js](https://allyjs.io/tutorials/focusing-in-svg.html)
* [Heating ice](http://svg-access-w3cg.github.io/use-case-examples/beaker.html) - See [SVG Heating ice - accessibility notes](http://svg-access-w3cg.github.io/use-case-examples/beaker-notes.html) and ['Chaals' Nevile sur Twitter : "Using SVG animation and aria-live to make an accessible interactive STEM demo: https://t.co/UxEaZE4lgQ with notes at https://t.co/pFi3XzRSiL"](https://mobile.twitter.com/chaals/status/838474855037067265)
* [highchart screenreaders chart - offline version](http://svg-access-w3cg.github.io/use-case-examples/hc-chart/notes.html)
* [7 solutions for creating more accessible SVGs » Simply Accessible](http://simplyaccessible.com/article/7-solutions-svgs/)

### Restrictions

| SVG Embed Technique                                       | External resources (styles, images) | Scripts | Interactivity (links, etc.) | CSS Animations                                                                                      | [CSS Inheritance](https://developer.mozilla.org/en-US/docs/Web/CSS/inheritance) |
| --------------------------------------------------------- | ----------------------------------- | ------- | --------------------------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| `<svg> … </svg>` (inlined)                                | Yes                                 | Yes     | Yes                         | Yes                                                                                                 | Yes                                                                             |
| `<svg><use xlink:href="#id"></svg>`                       | Yes                                 | Yes     | Yes                         | Yes                                                                                                 | Yes                                                                             |
| `<svg><use xlink:href="image.svg#id"></svg>`              | Yes                                 | Yes     | Yes                         | Yes? ([look like it's not the case](https://bugs.chromium.org/p/chromium/issues/detail?id=1345231)) | Yes                                                                             |
| `<object type="image/svg+xml" data="image.svg"></object>` | Yes                                 | Yes     | Yes                         | Yes, only inlined                                                                                   | No                                                                              |
| `<embed type="image/svg+xml" src="image.svg">`            | Yes                                 | Yes     | Yes                         | Yes, only inlined                                                                                   | No                                                                              |
| `<iframe src="image.svg"></iframe>`                       | Yes                                 | Yes     | Yes                         | Yes, only inlined                                                                                   | No                                                                              |
| `<img src="img.svg" alt="">`                              | No[^1]                              | No      | No                          | Yes, only inlined?                                                                                  | No                                                                              |
| `element::before{content: url(img.svg);}`                 | No[^1]                              | No      | No                          | Yes, only inlined?                                                                                  | No                                                                              |
| `background-image: url(image.svg);`                       | No[^1]                              | No      | No                          | Yes, only inlined?                                                                                  | No                                                                              |

**TODO test CSS Animations for "SVG as an Image" aka "SVG img src", SMIL animations (apprears to works at least with Safari)**

~~When used as an image: iframe doesn't work (no data URI, no srcdoc)~~ (don't know what I wanted to say there)

> Basically when using a foreign object tag \[in fact elements inside SVG as an Image] all its content must be origin free

* [SVG as an Image - SVG | MDN](https://developer.mozilla.org/en-US/docs/Web/SVG/SVG_as_an_Image#Restrictions)
* [SVG `use` with External Reference, Take 2 | CSS-Tricks](https://css-tricks.com/svg-use-with-external-reference-take-2/)
* `LayoutTests/http/tests/security/svg-imge-with-url-data-image.html` and `LayoutTests/http/tests/security/resources/image-with-url-data-image.svg`
* [141261 – SVG animation is slow only when the SVG is the background of the \<body>](https://bugs.webkit.org/show_bug.cgi?id=141261)

Related bugs:

* [100269 – SVG Images don't load referenced resources, including data URIs](https://bugs.webkit.org/show_bug.cgi?id=100269)
* [99677 – When using SVG as an image, we should load datauri images when these images are not in the image cache.](https://bugs.webkit.org/show_bug.cgi?id=99677)
* [170560 - \[SVG\] embeded images does not preloading (\<img> tag) - chromium - Monorail](https://bugs.chromium.org/p/chromium/issues/detail?id=170560)
* [552707 - Chrome fails to display createObjectURL encoded image pattern in a svg data uri - chromium - Monorail](https://bugs.chromium.org/p/chromium/issues/detail?id=552707)
* [176591 - SVG inside of a Blob cannot access its own defs element. - chromium - Monorail](https://bugs.chromium.org/p/chromium/issues/detail?id=176591)
* [Issues - chromium - An open-source project to help move the web forward. - Monorail](https://bugs.chromium.org/p/chromium/issues/list?q=component:Blink%3ESVG)

### Fragment identifier and SVG stack

```html
<img src="sprite.svg#instagram-icon" alt="Instagram icon">
```

```svg
<svg>
	<view id="instagram-icon" viewBox="64 0 32 32" />
</svg>
```

* [An Overview of SVG Sprite Creation Techniques ◆ 24 ways](https://24ways.org/2014/an-overview-of-svg-sprite-creation-techniques/)
* <https://bugs.webkit.org/show\\_bug.cgi?id=91790>
* <https://code.google.com/p/chromium/issues/detail?id=128055>
* [How to Use SVG Image Sprites](https://www.sitepoint.com/use-svg-image-sprites/)
* <http://dev.w3.org/csswg/css-images/#image-notation>
* <http://caniuse.com/#feat=svg-fragment>
* [How SVG Fragment Identifiers Work | CSS-Tricks](https://css-tricks.com/svg-fragment-identifiers-work/)

### SVG symbols

Aka icon

* The `viewBox` can be defined on the symbol, so you don't need to use it in the markup (easier and less error prone).
* `title` and `desc` tags can be added within the `<symbol>` and they kinda "come along for the ride" when the symbol gets used, making accessibility easier to do right.
* Symbols don't display as you define them, so no need for a `<defs>` block.
* This is probably what `<symbol>` was invented for anyway

```svg
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
  <symbol id="symbol-1" viewBox="214.7 0 182.6 792">
  	<title>symbol's-title</title>
    <desc>symbol's-desc</desc>
    <!-- <path>s and whatever other shapes in here -->
  </symbol>
  <symbol id="symbol-2" viewBox="0 26 100 48">
  	<title>symbol's-title</title>
    <desc>symbol's-desc</desc>
    <!-- <path>s and whatever other shapes in here -->
  </symbol>
</svg>

<svg class="icon">
  <use xlink:href="#symbol-1" />
</svg>
```

* [Comment travailler avec des icônes en SVG](https://la-cascade.io/comment-travailler-avec-des-icones-en-svg/)
* [SVG `symbol` a Good Choice for Icons | CSS-Tricks](https://css-tricks.com/svg-symbol-good-choice-icons/)

### Path

* [SVG Path](/calepin/formats-encoding-and-protocols/svg/svg.md)

#### Relative ↔︎ Absolute path

* [Utility: Convert SVG path to all-relative or all-absolute commands | Lea Verou](http://lea.verou.me/2019/05/utility-convert-svg-path-to-all-relative-or-all-absolute-commands/)
* <https://stackoverflow.com/questions/14179333/convert-svg-path-to-relative-commands/14179367#14179367>
* <https://stackoverflow.com/questions/9677885/convert-svg-path-to-absolute-commands/9677915#9677915>
* <https://github.com/DmitryBaranovskiy/raphael/blob/bef7f6b0e259030138193d42f2c74b754c292f3e/dev/raphael.core.js#L1646>

#### Path Data API

`SVGPathSeg`, `getPathData()` and `setPathData()`

* [jarek-foksa/path-data-polyfill.js: Polyfill for SVG 2 getPathData() and setPathData() methods.](https://github.com/jarek-foksa/path-data-polyfill.js)
* [progers/pathseg: SVGPathSeg polyfill](https://github.com/progers/pathseg/)

#### Primitives to path

See `MorphSVGPlugin.convertToPath` (require to be Club GreenSock membership)

Polyline to path: `<polygon points="x1,y1 x2,y2 x3,y3"/>` as `<path d="Mx1,y1 x2,y2 x3,y3Z"/>`

```html
<!--
http://codepen.io/niorad/pen/xmfza
Convert SVG-Shapes into paths so they can be animated.
The script converts all non-path-elements to paths so the stroke-dashoffset-trick works.
Note: this doesn't implement all syntaxes allowed by SVG specs
-->

<script>
	//inspired by http://product.voxmedia.com/post/68085482982/polygon-feature-design-svg-animations-for-fun-and

	//If you want to add SVG to the DOM, jQuery won't do
	//http://www.benknowscode.com/2012/09/using-svg-elements-with-jquery_6812.html

	function SVG(tag) {
	    return document.createElementNS('http://www.w3.org/2000/svg', tag);
	}

	function replaceRectsWithPaths(parentElement) {
	    var rects = $(parentElement).find('rect');

	    $.each(rects, function() {
	        var rectX = $(this).attr('x');
	        var rectY = $(this).attr('y');

	        var rectX2 = parseFloat(rectX) + parseFloat($(this).attr('width'));
	        var rectY2 = parseFloat(rectY) + parseFloat($(this).attr('height'));

	        var convertedPath = 'M' + rectX + ',' + rectY + ' ' + rectX2 + ',' + rectY + ' ' + rectX2 + ',' + rectY2 + ' ' + rectX + ',' + rectY2 + ' ' + rectX + ',' + rectY;

	        $(SVG('path'))
	        .attr('d', convertedPath)
	        .attr('fill', $(this).attr('fill'))
	        .attr('stroke', $(this).attr('stroke'))
	        .attr('stroke-width', $(this).attr('stroke-width'))
	        .insertAfter(this);
	    });

	    $(rects).remove();
	}

	function replaceLinesWithPaths(parentElement) {
	    var lines = $(parentElement).find('line');

	    $.each(lines, function() {
	        var lineX1 = $(this).attr('x1');
	        var lineY1 = $(this).attr('y1');

	        var lineX2 = $(this).attr('x2');
	        var lineY2 = $(this).attr('y2');

	        var convertedPath = 'M' + lineX1 + ',' + lineY1 + ' ' + lineX2 + ',' + lineY2;

	        $(SVG('path'))
	        .attr('d', convertedPath)
	        .attr('fill', $(this).attr('fill'))
	        .attr('stroke', $(this).attr('stroke'))
	        .attr('stroke-width', $(this).attr('stroke-width'))
	        .insertAfter(this);
	    });

	    $(lines).remove();
	}

	function replaceCirclesWithPaths(parentElement) {
	    var circles = $(parentElement).find('circle');

	    $.each(circles, function() {
	        var cX = $(this).attr('cx');
	        var cY = $(this).attr('cy');
	        var r = $(this).attr('r');
	        var r2 = parseFloat(r * 2);

	        var convertedPath = 'M' + cX + ', ' + cY + ' m' + (-r) + ', 0 ' + 'a ' + r + ', ' + r + ' 0 1,0 ' + r2 + ',0 ' + 'a ' + r + ', ' + r + ' 0 1,0 ' + (-r2) + ',0 ';

	        $(SVG('path'))
	        .attr('d', convertedPath)
	        .attr('fill', $(this).attr('fill'))
	        .attr('stroke', $(this).attr('stroke'))
	        .attr('stroke-width', $(this).attr('stroke-width'))
	        .insertAfter(this);
	    });

	    $(circles).remove();
	}

	function replaceEllipsesWithPaths(parentElement) {
	    var ellipses = $(parentElement).find('ellipse');

	    $.each(ellipses, function() {
	        var cX = $(this).attr('cx');
	        var cY = $(this).attr('cy');
	        var rX = $(this).attr('rx');
	        var rY = $(this).attr('ry');

	        var convertedPath = 'M' + cX + ', ' + cY + ' m' + (-rX) + ', 0 ' + 'a ' + rX + ', ' + rY + ' 0 1,0 ' + rX*2 + ',0 ' + 'a ' + rX + ', ' + rY + ' 0 1,0 ' + (-rX*2) + ',0 ';

	        $(SVG('path'))
	        .attr('d', convertedPath)
	        .attr('fill', $(this).attr('fill'))
	        .attr('stroke', $(this).attr('stroke'))
	        .attr('stroke-width', $(this).attr('stroke-width'))
	        .insertAfter(this);
	    });

	    $(ellipses).remove();
	}

	function replacePolygonsWithPaths(parentElement) {
	    var polygons = $(parentElement).find('polygon');

		// https://www.w3.org/TR/SVG/shapes.html#PointsBNF
	    $.each(polygons, function() {
	        var points = $(this).attr('points');
	        var polyPoints = points.split(/[ ,]+/);
	        var endPoint = polyPoints[0] + ', ' + polyPoints[1];

	        $(SVG('path'))
	        .attr('d', 'M' + points + ' ' + endPoint)
	        .attr('fill', $(this).attr('fill'))
	        .attr('stroke', $(this).attr('stroke'))
	        .attr('stroke-width', $(this).attr('stroke-width'))
	        .insertAfter(this);
	    });

	    $(polygons).remove();
	}

	function replacePolylinesWithPaths(parentElement) {
	    var polylines = $(parentElement).find('polyline');

	    $.each(polylines, function() {
	        var points = $(this).attr('points');

	        $(SVG('path'))
	        .attr('d', 'M' + points)
	        .attr('fill', $(this).attr('fill'))
	        .attr('stroke', $(this).attr('stroke'))
	        .attr('stroke-width', $(this).attr('stroke-width'))
	        .insertAfter(this);
	    });

	    $(polylines).remove();
	}

	function hideSVGPaths(parentElement) {
	    var paths = $(parentElement).find('path');

	    //for each PATH..
	    $.each( paths, function() {
	        //get the total length
	        var totalLength = this.getTotalLength();

	        //set PATHs to invisible
	        $(this).css({
	            'stroke-dashoffset': totalLength,
	            'stroke-dasharray': totalLength + ' ' + totalLength
	        });
	    });
	}

	function drawSVGPaths(_parentElement, _timeMin, _timeMax, _timeDelay) {
	    var paths = $(_parentElement).find('path');

	    //for each PATH..
	    $.each( paths, function(i) {
	        //get the total length
	        var totalLength = this.getTotalLength();

	        //set PATHs to invisible
	        $(this).css({
	            'stroke-dashoffset': totalLength,
	            'stroke-dasharray': totalLength + ' ' + totalLength
	        });

	        //animate
	        $(this).delay(_timeDelay*i).animate({
	            'stroke-dashoffset': 0
	        }, {
	            duration: Math.floor(Math.random() * _timeMax) + _timeMin
	            ,easing: 'easeInOutQuad'
	        });
	    });
	}

	function replaceWithPaths(parentElement) {
	    replaceRectsWithPaths(parentElement);
	    replaceLinesWithPaths(parentElement);
	    replaceEllipsesWithPaths(parentElement);
	    replaceCirclesWithPaths(parentElement);
	    replacePolygonsWithPaths(parentElement);
	    replacePolylinesWithPaths(parentElement);
	}

	function startSVGAnimation(parentElement) {
	    drawSVGPaths(parentElement, 1000, 2000, 50);
	}

	replaceWithPaths($('svg'));
	startSVGAnimation($('svg'));
</script>

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="800px" height="800px" viewBox="0 0 800 800" enable-background="new 0 0 800 800" xml:space="preserve">
<circle fill="#FFFFFF" stroke="#000000" stroke-width="4" stroke-miterlimit="10" cx="115.5" cy="119.5" r="55.5"/>
<ellipse fill="#FFFFFF" stroke="#000000" stroke-width="2" stroke-miterlimit="10" cx="284" cy="123" rx="69" ry="23"/>
<rect x="403" y="71" fill="#FFFFFF" stroke="#000000" stroke-width="2" stroke-miterlimit="10" width="98" height="97"/>
<path fill="#FFFFFF" stroke="#000000" stroke-width="2" stroke-miterlimit="10" d="M672,158c0,5.523-4.477,10-10,10h-82
    c-5.523,0-10-4.477-10-10V81c0-5.523,4.477-10,10-10h82c5.523,0,10,4.477,10,10V158z"/>
<polyline fill="#FFFFFF" stroke="#000000" stroke-width="2" stroke-miterlimit="10" points="66,292 115.5,239 171,321 194,251
    236,280 268,251 318,291 343,239 368,275 "/>
<path fill="#FFFFFF" stroke="#000000" stroke-width="2" stroke-miterlimit="10" d="M452,293c0,0,0-61,72-44c0,0-47,117,81,57
    s5-110,10-67s-51,77.979-50,33.989"/>
</svg>
```

### Transform

* [Transforms on SVG Elements | CSS-Tricks](https://css-tricks.com/transforms-on-svg-elements/)

#### `transform-origin` in SVG not the same as HTML

Default values:

* HTML: `center, center`
* SVG: `0, 0`

#### Transform on Firefox

`transform-origin: 50% 50%` is not supported in Firefox. Use `translate(-halfWpx -halfHpx) ... translate(halfWpx halfHpx)` or `transform-origin: 200px 200px` instead

### Animation

SMIL animation in SVG are powerfull, but hard to control. Prefer use CSS animation/transition but it is not supported in IE -11+. A pure JS fallback is the solution.

* <http://jakearchibald.com/2013/animated-line-drawing-svg/>

Animation as a huge impact on performance, especially on mobile. Rasterization is the problem. May be use canvas instead.

> \[SVG is] perfect for mobile… as long as it doesn’t move. There is no way to animate it smoothly on Android - rasterization won’t give you a chance.

* <https://github.com/kdzwinel/progress-bar-animation>
* <https://github.com/kdzwinel/progress-bar-animation/issues/1>

#### SMIL

Can't make multiple transform in the same time. Don't have an equivalent of `transform-orign` (it's the fault of SVG transform)

```svg
<!-- Animate element's translate -->
<animateTransform attributeName="transform" attributeType="XML" type="translate" from="589 122" to="580 -57" dur="250ms" fill="freeze" calcMode="spline" keySplines="0.43 0 0 1"/>
<!-- Animate opacity -->
<animate class="target" attributeName="opacity" attributeType="XML" from="1" to="0" dur="250ms" fill="freeze" calcMode="spline" keySplines="0.43 0 0 1"/>
```

Control it with JS: Add `begin="indefinite"` to `animate*` element, and `element.beginElement()` or `element.endElement()` (and few others methods) to control it.

* <http://leunen.me/fakesmile/index.html>
* <http://css-tricks.com/guide-svg-animations-smil/>
* <http://tutorials.jenkov.com/svg/svg-animation.html>
* <http://oak.is/thinking/animated-svgs>
* <http://apike.ca/prog\\_svg\\_smil.html>
* <https://developer.mozilla.org/en-US/docs/Web/SVG/SVG\\_animation\\_with\\_SMIL>

#### CSS

* <https://stackoverflow.com/questions/24302615/css3-animation-is-not-working>

#### JS

* [TweenMax](https://github.com/greensock/GreenSock-JS)
* <http://codepen.io/GreenSock/full/gpDrC/>
* <http://www.w3.org/TR/SVG/animate.html#DOMAnimationExample>

Now (05/11/2014) there no lib that can animate SVG transform attribute.

Interpolation:

* <http://www.w3.org/TR/css3-transforms/#interpolation-of-transform-functions>
* <http://www.w3.org/TR/css3-transforms/#transform-function-lists>
* <https://wiki.csswg.org/topics/transform-interpolation>
* `transform-origin: 200px 300px; transform: rotate(45deg);` is equivalent to: `transform: translate(200px 300px) rotate(45deg) translate(-200px -300px)`. Apply it to `scale`, `rotate`, \`\` (exist in SVG only for rotate: `transform="rotate(45 200 300)"` ). <http://www.w3.org/TR/css3-transforms/#transformation-matrix-computation>
* <https://stackoverflow.com/questions/19154631/how-to-get-coordinates-of-an-svg-element> <https://github.com/mbostock/d3/blob/48ad44fdeef32b518c6271bb99a9aed376c1a1d6/src/math/transform.js>
* <http://greensock.com/forums/tags/forums/svg/>
* <http://greensock.com/forums/topic/10666-svg-animations-in-ie/>
* <http://greensock.com/forums/topic/10684-apply-transforms-with-transform-attr-instead-of-inline-style-on-svg/>
* <http://greensock.com/forums/topic/10725-animating-svgs-fill-opacity/>
* <http://greensock.com/forums/topic/7376-general-purpose-svg-plug-in/>
* <https://github.com/akbr/GSAPSvgPlugin/blob/master/SvgPlugin.js>
* <https://gist.github.com/raldred/7769278>
* <http://www.benknowscode.com/2012/09/diving-into-matrices-with-css3\\_4970.html>
* <http://www.w3.org/TR/SVG/coords.html#TransformMatrixDefined>
* <https://github.com/jcoglan/sylvester>

#### Stroke animation

Works only on path elements. See code below to do that.

* `stroke-dashoffset`
* can be used for pie chart (camembert) animation. Use large `stroke-width` of a `<circle>`. On IE use a value minus <1px (50px → 49.9px)
* [SVG-Stroke Animation](http://codepen.io/niorad/pen/xmfza)
* [Animated line drawing in SVG - JakeArchibald.com](https://jakearchibald.com/2013/animated-line-drawing-svg/)
* [css - Animate Path in Internet Explorer - Stack Overflow](https://stackoverflow.com/questions/24918529/animate-path-in-internet-explorer)
* [Three Illustrator tricks for better SVG stroke animations | Val Head - Web & UI animation expert](http://valhead.com/2017/03/03/three-illustrator-tricks-for-better-svg-stroke-animations/)

### Stroke

* [Paths: Stroking and Offsetting | Tavmjong Bah's Blog](http://tavmjong.free.fr/blog/?p=1257)

### Pattern

* [An Overview of SVG Patterns : Adobe Dreamweaver Team Blog](http://blogs.adobe.com/dreamweaver/2015/09/svg-patterns.html)

### Unit

* stroke-width
* stroke-dasharray
* ...

unit less (5) = viewBox percentage (5%) = viewport

### DOM

Don't forget the SVG namespace:

```js
var image = document.createElementNS("http://www.w3.org/2000/svg", "image");
image.setAttributeNS("http://www.w3.org/2000/svg", "style", "opacity: 0.5");
// Use the default NS
image.setAttributeNS(null, "style", "opacity: 0.5");
image.setAttribute("style", "opacity: 0.5");
image.setAttributeNS('http://www.w3.org/1999/xlink', "href", "");
```

### Filter

* [My Article on SVG Filters at Smashingmag | eleqtriq](http://w3.eleqtriq.com/2015/05/the-svg-filter-and-why-its-awesome/)
* [SVG Filter Effects—3 Simple Filter Primitives - Vanseo Design](http://vanseodesign.com/web-design/simple-filter-primitives/)
* [SVG Filters](https://yoksel.github.io/svg-filters/#/)
* [SVG Filters 101 | Codrops](https://tympanus.net/codrops/2019/01/15/svg-filters-101/)
* [SVG Gradient Map Filter](https://yoksel.github.io/svg-gradient-map/#/)

#### Filter cropped, filter size

By default filter are `<filter x="-10%" y="-10%" width="120%" height="120%">`. If you want a bigger drop shadow, blur, etc. use `<filter x="-30%" y="-30%" width="160%" height="160%">`.

* [SVG Filters | tutorials.jenkov.com](http://tutorials.jenkov.com/svg/filters.html)
* [SVG Basics Tutorials - feOffset Filter Effect](http://www.svgbasics.com/filters3.html)

### Filter

* [Clipping in CSS and SVG — The clip-path Property and \<clipPath> Element](https://www.sarasoueidan.com/blog/css-svg-clipping/)

### Use clip-path over alpha channel filter as mask

...when it's possible for better performances

### Mask

Mask SVG qui disparaissent quand certain elements en contiennent ne sont plus affiché (`visibility: hidden;`, `display: none;`, removed)

### `<use>` with external source

Not work properly on IE9-11+?

* [Ajaxing for your SVG Sprite | CSS-Tricks](http://css-tricks.com/ajaxing-svg-sprite/)
* [SVG `use` with External Source | CSS-Tricks](http://css-tricks.com/svg-use-external-source/)

### Optimizations

Don't remove `xmlns="http://www.w3.org/2000/svg"` if you not inline the SVG document in an HTML document.

* element used once (`<use xlink:href="#ID" />`), replace replace it directly
* remove useless `id="ID"` attribute (if not reference by `xlink:ref="#ID"`, `clip-path="url(#ID)"`, etc.)
* same attributes (like `fill`, `stroke`, `stroke-***`, `style`, etc.) create a `<g></g>` wrapper with this attributes (will inherit attributes)
* remove useless namespace (like: `xmlns:xlink`) if not used
* remove whitespaces before and after value of `d=""`, `points=""`
* change color like #FFFFFF to it's named equivalent black...
* simplify transform matrix `matrix(1 0 0 1 $e $f)` to `translate($e $f)`, `translate(...) rotate(...) scale(...)...` to `matrix(...)`
* remove subtle transforms ex: `matrix(1 0 0 1 -1.220703e-04 -6.103516e-05)`
* remove on root `<svg></svg>` attributes like `id`, `x`, `y`, `width`, `height`, `enabled-background`, `xml:space`...
* precompress (gzip) and use appropriate headers <http://kaioa.com/node/45>
* reduce precision
* `<?xml version="1.0"?>` can be omitted
* `xmlns:xlink="http://www.w3.org/1999/xlink"` can be removed if not used
* `version="1.1"` on `svg` node can be omitted
* `<linearGradient>` inside `<defs>` not necessary
* `width` and `height` when `viewBox` is defined on `svg` node are not required
* `stop-opacity` on `stop` nodes are optional
* `stop-color="#ffffff"` and `stop-opacity="0"` can be merged to `stop-color="rgba(255,255,255,0)"`
* attribute quotes could be simple ones: `attribute='value'` instead of `attribute="value"`
* Remove all uncessary whites spaces like new lines, tabs

Some tools already exist:

* <https://github.com/svg/svgo>
* <https://code.google.com/p/svgmin/>
* <https://petercollingridge.appspot.com/svg-editor>
* <http://creativedroplets.com/export-svg-for-the-web-with-illustrator-cc/>
* [Common Pitfalls when Serving SVGs and How to Solve Them - José M. Pérez](https://jmperezperez.com/spotify-svg/)
* [Optimising SVGs for Web Use — Part 1 – Larsenwork – Medium](https://medium.com/larsenwork-andreas-larsen/optimising-svgs-for-web-use-part-1-67e8f2d4035)
* [Optimising SVGs for Web Use — Part 2 – Larsenwork – Medium](https://medium.com/larsenwork-andreas-larsen/optimising-svgs-for-web-use-part-2-6711cc15df46)
* [Optimising SVGs for Web Use — Part 2½ – Larsenwork – Medium](https://medium.com/larsenwork-andreas-larsen/optimising-svgs-for-web-use-part-2-1-598815d74f9c)

### Performances

Use HTML+CSS hardware acceleration (split SVG and wrap in HTML elements differents parts), Canvas (2D or WebGL) or just an still image (PNG) instead of SVG:

* [Goodbye, Layout Invalidation: Animating SVGs with CSS Transforms | Charlie Marsh](http://www.crmarsh.com/svg-performance/)
* [Maker here. I meant it as a way of saying good-bye to SVG as for the past years ... | Hacker News](https://news.ycombinator.com/item?id=12434230)
* [Performance of canvas versus SVG | Boris Smus](http://smus.com/canvas-vs-svg-performance/)
* Some well compressed PNG are smaller than the SVG version (often small icons) and the rendering time is the best by far
* [High Performance SVGs | CSS-Tricks](https://css-tricks.com/high-performance-svgs/)
* [shape-rendering - SVG | MDN](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering)
* [Improving SVG Runtime Performance by Taylor Hunt on CodePen](https://codepen.io/tigt/post/improving-svg-rendering-performance)

Inlined or as separate document vs CSS background image (data URI or separate document) impact rendering time and memory usage:

* [Bug 108999 – SVG background-image memory usage is absurd](https://bugs.webkit.org/show_bug.cgi?id=108999)
* [196524 - an svg background image eats up browser memory - chromium - Monorail](https://code.google.com/p/chromium/issues/detail?id=196524)
* [Bug 106159 – Remove the bitmap SVG image cache](https://bugs.webkit.org/show_bug.cgi?id=106159)
* [Case Study: Tricky SVG Background Images | Targetprocess - Visual management software](https://www.targetprocess.com/blog/2013/03/case-study-tricky-svg-background-images/)
* [Parashuram's blog: Icons - Font, Inline SVG or Background SVGs ?](http://blog.nparashuram.com/2015/05/icons-font-inline-svg-or-background-svgs.html), <https://docs.google.com/spreadsheets/d/1j8YnjlnBR1rFxZ89JYwrNRV2cXVaoCm-9BexErRj2Hs/edit#gid=1538311979> and <https://github.com/web-perf/svg-perf-test>

#### CSS animations applied on definition elements

CSS animations applied on elements used by `use` can be realy bad and not recommended.

### Case sensitivity

Since SVG is XML, node's name are case sensitive. Be carefull when create element in XML stream or via DOM (`createElement()`).

* <http://ejohn.org/blog/nodename-case-sensitivity/>

### Gradient

<https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Gradients>

> Linear gradients can be defined as horizontal, vertical or angular gradients:
>
> * Horizontal gradients are created when y1 and y2 are equal and x1 and x2 differ
> * Vertical gradients are created when x1 and x2 are equal and y1 and y2 differ
> * Angular gradients are created when x1 and x2 differ and y1 and y2 differ

```svg
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1 1' preserveAspectRatio='none'>
	<linearGradient id='g' x1='0%' y1='0%' x2='100%' y2='0%'>
		<stop offset='0%' stop-color='rgba(255,255,255,0.5)'/>
		<stop offset='100%' stop-color='rgba(255,255,255,0.8)'/>
	</linearGradient>
	<rect fill='url(#g)' width='100' height='100'/>
</svg>
```

* [How To Apply SVG Linear Gradients To A Fill Or Stroke - Vanseo Design](http://vanseodesign.com/web-design/svg-linear-gradients/)

#### Gardient — Left to right

```svg
<linearGradient id="g">
```

#### Gardient — Top to bottom

```svg
<linearGradient id="g" x1="0%" y1="0%" x2="100%" y2="0%">
```

### Coordinates, position and viewport

If `viewBox` is not defined nor `width` and `height`, SVG dimentions will not scale Use `viewBox` instead of `width`, `height`, `x` and `y`.

Responsive

* [How to Scale SVG | CSS-Tricks](https://css-tricks.com/scale-svg/)
* [Mimic Relative Positioning Inside an SVG with Nested SVGs](https://sarasoueidan.com/blog/mimic-relative-positioning-in-svg/)
* [How to Translate from DOM to SVG Coordinates and Back Again](https://www.sitepoint.com/how-to-translate-from-dom-to-svg-coordinates-and-back-again/)
* [Understanding SVG Coordinate Systems and Transformations (Part 1) — The viewport, \<code>viewBox, and `preserveAspectRatio`](https://sarasoueidan.com/blog/svg-coordinate-systems/)
* [Interactive Data Visualization: Animating the viewBox | CSS-Tricks](https://css-tricks.com/interactive-data-visualization-animating-viewbox/)
* [SVG & media queries - JakeArchibald.com](https://jakearchibald.com/2016/svg-media-queries/)
* [CSSconf EU 2014 | Sara Soueidan: Styling and Animating Scalable Vector Graphics with CSS - YouTube](https://www.youtube.com/watch?v=lf7L8X6ZBu8#t=1083)
* [Responsive SVGs with Constant Font Size](https://web.archive.org/web/20220706073255/https://florian.ec/blog/responsive-svg-constant-font-size/)

#### Adaptive image

* <http://w3.eleqtriq.com/2014/02/everything-is-relative-the-art-of-the-adaptive-image/>
* [Four sliced scaling for SVG | eleqtriq](http://w3.eleqtriq.com/2014/02/the-4-slice-scaling-technique-for-svg/)
* 9 slice in SVG: [The Holy Grail of Image Scaling | eleqtriq](http://w3.eleqtriq.com/2014/03/the-holy-grail-of-image-scaling/)
* <http://css-tricks.com/scale-svg/>

#### Scale bug on IE

* <http://www.seowarp.com/blog/2011/06/svg-scaling-problems-in-ie9-and-other-browsers/>
* <http://benfrain.com/svg-backgrounds-dont-zoom-correctly-in-internet-explorer-10/>

#### `preserveAspectRatio`

`preserveAspectRatio="xMidYMid meet"` (default, CSS equivalent `background: center / contain`) has no effect if `viewBox` is not set

Scaling:

keyword | CSS equivalent `meet` | `background-size: contain` `slice` | `background-size: cover` `none` | `background-size: 100% 100%` (stretching or squishing to fit the height and width)

For alignment (in conjuction with `meet` or `slice`), use 2 keywords concatenated (like `xMinYMin`):

keyword | CSS equivalent `xMin` | `background-position-x: left` `xMid` | `background-position-x: center` `xMax` | `background-position-x: right` `YMin` | `background-position-y: top` `YMid` | `background-position-y: center` `YMax` | `background-position-y: bottom`

* [Why and how `preserveAspectRatio`? by Taylor Hunt on CodePen](http://codepen.io/tigt/post/why-and-how-preserveaspectratio) - equivalent to `background-position` and `background-size`

### Align text

```
<text text-anchor="middle" dy=".3em">Center aligned text</text>
```

* [Easily center text vertically, with SVG! | Lea Verou](http://lea.verou.me/2013/03/easily-center-text-vertically-with-svg/)

### Fallback

```svg
<svg>
	<switch>
		<use xlink:href="#icon-twitter"></use>
		<foreignObject>
			<div class="fallback icon-twitter-fallback"></div>
		</foreignObject>
	</switch>
</svg>
<style>
	.icon-twitter-fallback{
		background-image: url("icon-twitter.png");
	}
</style>
```

> the logic is embedded inside the `<svg>` and use the `<foreignObject>` element to insert the non-SVG fallback. Using `<switch>`, SVG-capable browsers will render the first markup they understand (the SVG) and ignore the rest (the contents of the `<foreignObject>`). IE will do the opposite: it ignore the SVG it does not understand and renders the contents of the `<foreignObject>` because it is plain HTML.

* [SVG Fallbacks | CSS-Tricks](https://css-tricks.com/svg-fallbacks/)
* [A Complete Guide to SVG Fallbacks | CSS-Tricks](https://css-tricks.com/a-complete-guide-to-svg-fallbacks/)
* Chapter 28: Using SVGs As An Icon Font Replacement (Or, How To Create SVG Sprites And Use Them As An Icon System) (page 335) - Mastering SVG For Responsive Web Design by Sara Soueidan
* [Smashing Book 5 Real-Life Responsive Web Design - Part 1 - Smashing Magazine | Typography | Web Page](https://fr.scribd.com/document/279207475/Smashing-Book-5-Real-Life-Responsive-Web-Design-Part-1-Smashing-Magazine)
* [Inline SVG Fallback](http://www.kaizou.org/2009/03/inline-svg-fallback/)

### HTML Entities

```js
// create a doctype that includes definitions for all HTML entities - http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references
const HTML_ENTITIES = {
	"quot": 34,
	"amp": 38,
	"apos": 39,
	"lt": 60,
	"gt": 62,
	"nbsp": 160,
	"iexcl": 161,
	"cent": 162,
	"pound": 163,
	"curren": 164,
	"yen": 165,
	"brvbar": 166,
	"sect": 167,
	"uml": 168,
	"copy": 169,
	"ordf": 170,
	"laquo": 171,
	"not": 172,
	"shy": 173,
	"reg": 174,
	"macr": 175,
	"deg": 176,
	"plusmn": 177,
	"sup2": 178,
	"sup3": 179,
	"acute": 180,
	"micro": 181,
	"para": 182,
	"middot": 183,
	"cedil": 184,
	"sup1": 185,
	"ordm": 186,
	"raquo": 187,
	"frac14": 188,
	"frac12": 189,
	"frac34": 190,
	"iquest": 191,
	"Agrave": 192,
	"Aacute": 193,
	"Acirc": 194,
	"Atilde": 195,
	"Auml": 196,
	"Aring": 197,
	"AElig": 198,
	"Ccedil": 199,
	"Egrave": 200,
	"Eacute": 201,
	"Ecirc": 202,
	"Euml": 203,
	"Igrave": 204,
	"Iacute": 205,
	"Icirc": 206,
	"Iuml": 207,
	"ETH": 208,
	"Ntilde": 209,
	"Ograve": 210,
	"Oacute": 211,
	"Ocirc": 212,
	"Otilde": 213,
	"Ouml": 214,
	"times": 215,
	"Oslash": 216,
	"Ugrave": 217,
	"Uacute": 218,
	"Ucirc": 219,
	"Uuml": 220,
	"Yacute": 221,
	"THORN": 222,
	"szlig": 223,
	"agrave": 224,
	"aacute": 225,
	"acirc": 226,
	"atilde": 227,
	"auml": 228,
	"aring": 229,
	"aelig": 230,
	"ccedil": 231,
	"egrave": 232,
	"eacute": 233,
	"ecirc": 234,
	"euml": 235,
	"igrave": 236,
	"iacute": 237,
	"icirc": 238,
	"iuml": 239,
	"eth": 240,
	"ntilde": 241,
	"ograve": 242,
	"oacute": 243,
	"ocirc": 244,
	"otilde": 245,
	"ouml": 246,
	"divide": 247,
	"oslash": 248,
	"ugrave": 249,
	"uacute": 250,
	"ucirc": 251,
	"uuml": 252,
	"yacute": 253,
	"thorn": 254,
	"yuml": 255,
	"OElig": 338,
	"oelig": 339,
	"Scaron": 352,
	"scaron": 353,
	"Yuml": 376,
	"fnof": 402,
	"circ": 710,
	"tilde": 732,
	"Alpha": 913,
	"Beta": 914,
	"Gamma": 915,
	"Delta": 916,
	"Epsilon": 917,
	"Zeta": 918,
	"Eta": 919,
	"Theta": 920,
	"Iota": 921,
	"Kappa": 922,
	"Lambda": 923,
	"Mu": 924,
	"Nu": 925,
	"Xi": 926,
	"Omicron": 927,
	"Pi": 928,
	"Rho": 929,
	"Sigma": 931,
	"Tau": 932,
	"Upsilon": 933,
	"Phi": 934,
	"Chi": 935,
	"Psi": 936,
	"Omega": 937,
	"alpha": 945,
	"beta": 946,
	"gamma": 947,
	"delta": 948,
	"epsilon": 949,
	"zeta": 950,
	"eta": 951,
	"theta": 952,
	"iota": 953,
	"kappa": 954,
	"lambda": 955,
	"mu": 956,
	"nu": 957,
	"xi": 958,
	"omicron": 959,
	"pi": 960,
	"rho": 961,
	"sigmaf": 962,
	"sigma": 963,
	"tau": 964,
	"upsilon": 965,
	"phi": 966,
	"chi": 967,
	"psi": 968,
	"omega": 969,
	"thetasym": 977,
	"upsih": 978,
	"piv": 982,
	"ensp": 8194,
	"emsp": 8195,
	"thinsp": 8201,
	"zwnj": 8204,
	"zwj": 8205,
	"lrm": 8206,
	"rlm": 8207,
	"ndash": 8211,
	"mdash": 8212,
	"lsquo": 8216,
	"rsquo": 8217,
	"sbquo": 8218,
	"ldquo": 8220,
	"rdquo": 8221,
	"bdquo": 8222,
	"dagger": 8224,
	"Dagger": 8225,
	"bull": 8226,
	"hellip": 8230,
	"permil": 8240,
	"prime": 8242,
	"Prime": 8243,
	"lsaquo": 8249,
	"rsaquo": 8250,
	"oline": 8254,
	"frasl": 8260,
	"euro": 8364,
	"image": 8465,
	"weierp": 8472,
	"real": 8476,
	"trade": 8482,
	"alefsym": 8501,
	"larr": 8592,
	"uarr": 8593,
	"rarr": 8594,
	"darr": 8595,
	"harr": 8596,
	"crarr": 8629,
	"lArr": 8656,
	"uArr": 8657,
	"rArr": 8658,
	"dArr": 8659,
	"hArr": 8660,
	"forall": 8704,
	"part": 8706,
	"exist": 8707,
	"empty": 8709,
	"nabla": 8711,
	"isin": 8712,
	"notin": 8713,
	"ni": 8715,
	"prod": 8719,
	"sum": 8721,
	"minus": 8722,
	"lowast": 8727,
	"radic": 8730,
	"prop": 8733,
	"infin": 8734,
	"ang": 8736,
	"and": 8743,
	"or": 8744,
	"cap": 8745,
	"cup": 8746,
	"int": 8747,
	"there4": 8756,
	"sim": 8764,
	"cong": 8773,
	"asymp": 8776,
	"ne": 8800,
	"equiv": 8801,
	"le": 8804,
	"ge": 8805,
	"sub": 8834,
	"sup": 8835,
	"nsub": 8836,
	"sube": 8838,
	"supe": 8839,
	"oplus": 8853,
	"otimes": 8855,
	"perp": 8869,
	"sdot": 8901,
	"lceil": 8968,
	"rceil": 8969,
	"lfloor": 8970,
	"rfloor": 8971,
	"lang": 9001,
	"rang": 9002,
	"loz": 9674,
	"spades": 9824,
	"clubs": 9827,
	"hearts": 9829,
	"diams": 9830,
};

const SVG_DOCTYPE = `<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
	${Object.entries(HTML_ENTITIES).map(([name, value]) => `<!ENTITY ${name} "&#${value};">`).join("\n\t")}
]>`;
```

* [Character entity references in HTML 4](https://www.w3.org/TR/html4/sgml/entities.html)

### Data attributes

```xml
<whatever xmlns:data="https://html.spec.whatwg.org/#attr-data-*"><!-- Ths XML namespace value can be anything -->
    <url data:post-type="quote">
        <loc>https://example.com/3</loc>
        <lastmod>1998-08-19</lastmod>
    </url>
</whatever>
```

* [Arbitrary `data` attributes in XML by Taylor Hunt on CodePen](https://codepen.io/tigt/post/arbitrary-data-attributes-in-xml)

### Graphics Canvas

Aka WebGL

* [WebGL in SVG via foreignObject](https://gist.github.com/spite/6675ac4622a39cc7a75449215603fe4d?short_path=65bbefd)

### Text to Path

* [mikolalysenko/vectorize-text: Turns a text string into a 2D poly line](https://github.com/mikolalysenko/vectorize-text/tree/master) - Render with a browser canvas or Cairo ([canvas](https://www.npmjs.com/package/canvas)), then detect edges
* [bubkoo/text2svg: 🍄 Convert text to svg path.](https://github.com/bubkoo/text2svg/tree/master) - Use [opentype.js](https://github.com/opentypejs/opentype.js)
* [text-to-svg/src/index.js at master · shrhdk/text-to-svg](https://github.com/shrhdk/text-to-svg/blob/master/src/index.js) - Use [opentype.js](https://github.com/opentypejs/opentype.js)
* [ksss/text2svg: Generate SVG data from text and font file](https://github.com/ksss/text2svg/tree/master) - Use [FreeType](https://freetype.org/), written in Ruby. See [`svg_path_data`](https://github.com/ksss/freetype/blob/8e48fb665fbfe7055741e8ea8a33fa80862f9f83/lib/freetype/api.rb#L208-L236) and [`FT_Outline_Decompose`](https://freetype.org/freetype2/docs/reference/ft2-outline_processing.html#ft_outline_decompose)
* `inkscape file_text.svg --export-text-to-path --export-plain-svg file_shapes.svg`
* [kartsims/easysvg: Generate SVG definitions and XML using PHP](https://github.com/kartsims/easysvg/tree/master) - Render text path with SVG font, written in PHP
* [php - How to convert text to SVG paths? - Stack Overflow](https://stackoverflow.com/questions/7742148/how-to-convert-text-to-svg-paths/9558337#9558337) - Render text path with SVG font, written in PHP
* [danmarshall/google-font-to-svg-path: Create an SVG path from a Google font](https://github.com/danmarshall/google-font-to-svg-path/tree/master) - Use [maker.js](https://github.com/Microsoft/maker.js) (which use [opentype.js](https://github.com/opentypejs/opentype.js)), written in JS

See also:

* [HarfBuzz](https://harfbuzz.github.io/) - "HarfBuzz is a text shaping library"
* [Pango](https://pango.gnome.org/) - "Pango is a library for laying out and rendering of text, with an emphasis on internationalization"

### SVG Font

* [SVG Font Converter](https://xmlgraphics.apache.org/batik/tools/font-converter.html) - Batik `ttf2svg`
* [Text to SVG Paths](https://web.archive.org/web/20210917224826/https://catherineh.github.io/programming/2018/02/01/text-to-svg-paths) with freetype and Python
* FontForge scripting:
  * native scripting: `fontforge -lang ff -c 'Open($1); Generate($2)' font.otf font.svg`
  * pyton: `fontforge -c 'open(argv[1]).generate(argv[2])' font.otf font.svg`
  * [Scripting FontForge](https://fontforge.org/docs/scripting/scripting.html#invoking-scripts)

[^1]: no other URI that data URI can be used inside image SVG (Blob works only with Firefox, not Chrome, not Safari)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://mmems.gitbook.io/calepin/development/svg.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
