Advertisement · 728 × 90
#
Hashtag

#tinySVGtip

Advertisement · 728 × 90
filter#outline
    feGaussianBlur(stdDeviation='3')
    feComponentTransfer: feFuncA(type='table' tableValues='-3 4 -3')

filter#outline feGaussianBlur(stdDeviation='3') feComponentTransfer: feFuncA(type='table' tableValues='-3 4 -3')

Filled reindeer illustration.

Filled reindeer illustration.

Outline reindeer illustration.

Outline reindeer illustration.

#tinySVGtip
Want to turn your filled¹ reindeer² 🦌 into an outline one? You can do so with this super simple #SVG #filter!

¹needs a transparent background input
²or anything else on a transparent background, really

8 1 1 0

#tinySVGtip You want to do it with #SVG? Here's an SVG solution too!

It uses a single `circle` element inside an `svg` and less than 10 #CSS declarations, including those in keyframes! ✨

2 0 0 0
Two particles forming a gooey assembly and the SVG filter behind.

```
<svg width='0' height='0'>
  <!-- default filter area is just 110% of element, enlarge-->
  <filter id='goo' x='-50%' y='-50%' width='200%' height='200%'>
    <!-- push all pixels with alpha < .5 to be fully transparent-->
    <!-- and all others to be fully opaque-->
    <feComponentTransfer>
      <feFuncA type='discrete' tableValues='0 1'></feFuncA>
    </feComponentTransfer>
    <!-- use the tiniest px blur possible to get rid of edge jaggedness-->
    <feGaussianBlur stdDeviation='3'></feGaussianBlur>
    <!-- get rid of edge blurriness -->
    <!-- by reducing the number of semitransparent pixels-->
    <!-- alphas in the [0, 1] interval get mapped to the [-2, 3] one-->
    <!-- then values get clamped to [0, 1] anyway-->
    <feComponentTransfer>
      <feFuncA type='table' tableValues='-2 3'></feFuncA>
    </feComponentTransfer>
  </filter>
</svg>
```

Two particles forming a gooey assembly and the SVG filter behind. ``` <svg width='0' height='0'> <!-- default filter area is just 110% of element, enlarge--> <filter id='goo' x='-50%' y='-50%' width='200%' height='200%'> <!-- push all pixels with alpha < .5 to be fully transparent--> <!-- and all others to be fully opaque--> <feComponentTransfer> <feFuncA type='discrete' tableValues='0 1'></feFuncA> </feComponentTransfer> <!-- use the tiniest px blur possible to get rid of edge jaggedness--> <feGaussianBlur stdDeviation='3'></feGaussianBlur> <!-- get rid of edge blurriness --> <!-- by reducing the number of semitransparent pixels--> <!-- alphas in the [0, 1] interval get mapped to the [-2, 3] one--> <!-- then values get clamped to [0, 1] anyway--> <feComponentTransfer> <feFuncA type='table' tableValues='-2 3'></feFuncA> </feComponentTransfer> </filter> </svg> ```

#tinySVGtip Better gooey effect with no matrix filter!

Each particle can get its own CSS blur filter with a value that may be any unit (SVG doesn't support this).

The assembly containing them gets an SVG filter as below.

Heavily commented demo: codepen.io/thebabydino/...

28 7 1 2

#tinySVGtip Give box with a (semi)transparent background a gradient shadow!

Create position:absolute pseudo covering entire parent border-box. Move it behind parent.

Set desired gradient on it. Apply SVG filter that blurs & offsets it, then subtracts original out of it.

codepen.io/thebabydino/...

13 2 0 0
<!-- DON'T ❌😱 -->
<filter id='f'>
  	<!-- input in for the very first primitive is by default 
		 SourceGraphic, so there's no need to set it explicitly -->
  	<!-- no need to set result attribute either as 
		 it's only useful to reference the result of a primitive 
		 in another primitive that doesn't immediately follow it -->
	<feGaussianBlur in='SourceGraphic' stdDeviation='8' result='blur' />
  	<!-- feOffset does nothing here as both offsets are 0, 
		 so it can be removed -->
	<feOffset in='blur' dx='0' dy='0' result='offsetBlur' />
	<!-- feMerge when we only have two inputs is overkill, we get 
		 same result with a feBlend using SourceGraphic as top layer 
		 (in attribute) -->
	<feMerge>
		<feMergeNode in='offsetBlur' />
		<feMergeNode in='SourceGraphic' />
	</feMerge>
</filter>

<!-- DO ✅😻 - produces the exact same result -->
<filter id='f'>
	<feGaussianBlur stdDeviation='8'/>
	<feBlend in='SourceGraphic'/>
</filter>

<!-- DON'T ❌😱 --> <filter id='f'> <!-- input in for the very first primitive is by default SourceGraphic, so there's no need to set it explicitly --> <!-- no need to set result attribute either as it's only useful to reference the result of a primitive in another primitive that doesn't immediately follow it --> <feGaussianBlur in='SourceGraphic' stdDeviation='8' result='blur' /> <!-- feOffset does nothing here as both offsets are 0, so it can be removed --> <feOffset in='blur' dx='0' dy='0' result='offsetBlur' /> <!-- feMerge when we only have two inputs is overkill, we get same result with a feBlend using SourceGraphic as top layer (in attribute) --> <feMerge> <feMergeNode in='offsetBlur' /> <feMergeNode in='SourceGraphic' /> </feMerge> </filter> <!-- DO ✅😻 - produces the exact same result --> <filter id='f'> <feGaussianBlur stdDeviation='8'/> <feBlend in='SourceGraphic'/> </filter>

#tinySVGtip Simplifying an SVG filter

10 3 1 0
Screenshot of the filter and its result up to the point where the image is offset and blurred.

Screenshot of the filter and its result up to the point where the image is offset and blurred.

Screenshot of the filter and its result up to the point where the offset and blurred image version is subtracted out of the original image alpha (1 everywhere within the image rectangle), leaving us with a black inset shadow, just the shadow.

Screenshot of the filter and its result up to the point where the offset and blurred image version is subtracted out of the original image alpha (1 everywhere within the image rectangle), leaving us with a black inset shadow, just the shadow.

Screenshot of the filter and its result up to the point where the black inset shadow is painted orange using feColorMatrix.

Screenshot of the filter and its result up to the point where the black inset shadow is painted orange using feColorMatrix.

Final step: the orangey inset shadow is placed on top of the initial image.

Final step: the orangey inset shadow is placed on top of the initial image.

#tinySVGtip How do you create an inset shadow on an img element?

You might say inset box-shadow, but it doesn't work!

SVG filters to the rescue for an elegant solution!

✨ offset & blur image
✨ subtract it out of original image alpha ⇒ get black inner shadow
✨ paint it 🍊
✨ place it on top of img

10 1 1 1
Relevant CSS code:

```
.barcode {
	/* relevant styles */
	background: 
      	/* along x axis between semi-transparent black & transparent */
		linear-gradient(90deg, #0002, #0000),
		linear-gradient(90deg, #0003, #0000),
		linear-gradient(90deg, #0000, #0005),
		linear-gradient(90deg, #0000, #0007);
    /* each layer has a different size so that stacking these gradients 
    /* results in a random-looking semitransparent vertical lines pattern */
	background-size: 13px, 7px, 19px, 17px;
	filter: url(#f)
}
```

Relevant CSS code: ``` .barcode { /* relevant styles */ background: /* along x axis between semi-transparent black & transparent */ linear-gradient(90deg, #0002, #0000), linear-gradient(90deg, #0003, #0000), linear-gradient(90deg, #0000, #0005), linear-gradient(90deg, #0000, #0007); /* each layer has a different size so that stacking these gradients /* results in a random-looking semitransparent vertical lines pattern */ background-size: 13px, 7px, 19px, 17px; filter: url(#f) } ```

The markup.
```
<svg width='0' height='0'>
	<filter id='f'>
		<feComponentTransfer>
          	<!-- push all alpha values < .5 to 0 
				 and all others (>= .5) to 1 -->
			<feFuncA type='discrete' tableValues='0 1'/>
		</feComponentTransfer>
	</filter>
</svg>
<div class='barcode'></div>
```

The markup. ``` <svg width='0' height='0'> <filter id='f'> <feComponentTransfer> <!-- push all alpha values < .5 to 0 and all others (>= .5) to 1 --> <feFuncA type='discrete' tableValues='0 1'/> </feComponentTransfer> </filter> </svg> <div class='barcode'></div> ```

Result of stacking prime-number of pixels size linear gradients, before applying the SVG filter: random-looking semitransparent vertical slightly blurry lines pattern.

Result of stacking prime-number of pixels size linear gradients, before applying the SVG filter: random-looking semitransparent vertical slightly blurry lines pattern.

After applying the SVG filter: proper barcode look!

After applying the SVG filter: proper barcode look!

#tinySVGtip Create a barcode ▌│█║▌║▌║ with a CSS gradient pattern (only a handful of CSS declarations in total) + a super simple SVG filter!

Also an entry for this week's #CodePenChallenge codepen.io/thebabydino/...

3 1 1 0
Screenshot. Shows desaturation of all in an image but the petals of red roses.

Screenshot. Shows desaturation of all in an image but the petals of red roses.

#tinySVGtip Remember to *always* set

`color-interpolation-filters='sRGB'`

for your #SVG #filter!

Otherwise: wildly different results in Chrome/ Firefox vs. Safari out of primitives that manipulate channel values (`feComponentTransfer` for gooey effect, `feColorMatrix` for stuff like 👇)

1 0 1 0
1️⃣ Draw a line along the direction of the stripes, let's say along the main diagonal.

Defaults for x1, y1, x2, y2 are all 0 and we want the start point x1,y1 to be at 0,0 (top left corner) anyway, so we only set x2,y2 at 100%,100% (bottom right corner).

<line x2='100%' y2='100%' stroke='orange'/>

This draws an orange ine along the main diagonal, from the top left corner to the bottom right one.

2️⃣ Make this line dashed.

<line x2='100%' y2='100%' stroke='orange' stroke-dasharray='20%'/>

This makes the line dashed.

3️⃣ Make this line thicker.

<line x2='100%' y2='100%' stroke='orange' stroke-dasharray='20%' stroke-width='20%'/>

This makes the dashed line thicker.

4️⃣ No, not like that... really, much thicker!

<line x2='100%' y2='100%' stroke='orange' stroke-dasharray='20%' stroke-width='150%'/>

The dashed line is now so thick that the dash lines stretch perpendicularly onto it to the point they cover the entire SVG rectangle.

1️⃣ Draw a line along the direction of the stripes, let's say along the main diagonal. Defaults for x1, y1, x2, y2 are all 0 and we want the start point x1,y1 to be at 0,0 (top left corner) anyway, so we only set x2,y2 at 100%,100% (bottom right corner). <line x2='100%' y2='100%' stroke='orange'/> This draws an orange ine along the main diagonal, from the top left corner to the bottom right one. 2️⃣ Make this line dashed. <line x2='100%' y2='100%' stroke='orange' stroke-dasharray='20%'/> This makes the line dashed. 3️⃣ Make this line thicker. <line x2='100%' y2='100%' stroke='orange' stroke-dasharray='20%' stroke-width='20%'/> This makes the dashed line thicker. 4️⃣ No, not like that... really, much thicker! <line x2='100%' y2='100%' stroke='orange' stroke-dasharray='20%' stroke-width='150%'/> The dashed line is now so thick that the dash lines stretch perpendicularly onto it to the point they cover the entire SVG rectangle.

#tinySVGtip Been using this forever, but don't think I've ever shared it here.

Easily create stripes along any direction in SVG!
✨ draw a line along that direction
✨ make it dashed
✨ make it much thicker
✨ no, not like that... I really mean much thicker!

That's it! 🥳🎉

codepen.io/thebabydino/...

22 6 0 0