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

You might think inset `box-shadow`, but it doesn't work! Really, there are tons of articles & questions on StackOveflow on this very topic.

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

#SVG #filter #inset #shadow #image #svgFilter #code #coding #frontend #webDev #webDevelopment

CSS Backgrounds and Borders Module Level 3

Almost all solutions I've seen involve wrapping the image in a wrapper, then either moving it behind its parent or placing an absolutely positioned pseudo on top, such that another element/ pseudo on top gets the shadow.

This means an extra element and often losing right click menu, save for the rare cases when the element on top of the img in z order gets `pointer-events: none`.

#css #shadow #boxShadow #inset #code #coding #frontend #web #dev #webDev #webDevelopment #shadows

While I've seen the rare #SVG solution among the SO answers, I found those filters to be too complicated. So here's a much simpler SVG version, step by step 👆

Live demo https://codepen.io/thebabydino/pen/gOBxmOZ also for this week's #CodePenChallenge

No wrapper, no losing right click menu on img if not setting `pointer-events: none` on element on top of img in z order.

#CodePen #css #filter #svgFilter #shadow #inset #code #coding #frontend #web #dev #webDevelopment #webDev

Inset shadow on image

A simple and elegant solution to an old problem. --- If the work I've been putting out since early 2012 has helped you in any way or you just like it...

Deconstructing:

All the fe-prefixed elements ("fe" stands for "filter effect") are called #filter primitives (see https://developer.mozilla.org/en-US/docs/Web/SVG/Element#filter_primitive_elements).

All those used here take 1 or 2 inputs. We don't specify them explicitly for those with a single input... because they're the defaults!

The default input is normally the result (output) of the previous #filter primitive. Save for the very first filter primitive, when the default input is the SourceGraphic.

#SVG #filterEffect #svgFilter #code #coding #web

SVG element reference - SVG: Scalable Vector Graphics | MDN

SVG drawings and images are created using a wide array of elements which are dedicated to the construction, drawing, and layout of vector images and diagrams. Here you'll find reference documentation for each of the SVG elements.

MDN Web Docs

Length values in a filter (dx, dy, stdDeviation) are either all in px or relative to box dimensions (if primitiveUnits='objectBoundingBox')

https://drafts.fxtf.org/filter-effects/#element-attrdef-filter-filterunits

This is something I find massively problematic - #SVG got left behind. https://mastodon.social/@anatudor/111596456117533541

While #CSS #filter functions like `drop-shadow()` allow us to specify the offsets and/ or standard deviation using font-relative units, SVG filters don't.

#svgFilter #code #coding #frontend #gotcha #web #dev #webDev #webDevelopment

`feComposite` & `feBlend` take 2 inputs: the 2 layers we're compositing/ blending. Compositing/ blending take 2 layers and combine them in a single one using a compositing operation/ blend mode.

`operator='out'` for `feComposite` is kinda like `mask-composite: subtract` - mask compositing is something I've detailed in this #cssTricks article https://css-tricks.com/mask-compositing-the-crash-course/#aa-subtract

#svgFilter #code #coding #frontend #gotcha #web #dev #webDev #webDevelopment #compositing #blending #alpha

Mask Compositing: The Crash Course | CSS-Tricks

At the start of 2018, as I was starting to go a bit deeper into CSS gradient masking in order to create interesting visuals one would think are impossible

CSS-Tricks

In our particular case, we subtract the bottom layer alpha (input given by `in2` attribute, which has the default value: result of the feGaussianBlur primitive) *out* of the top layer alpha (input given by `in` attribute, set to SourceAlpha, basically img alpha).

Since blurring has given us semitransparent pixels in the edge areas, this difference gives us an alpha of 0 everywhere (1-1) other than along the edges, where the bottom layer is semi-transparent. RGB channels are those of top layer!

Top layer has all 3 RGB channels 0 in this case ⇒ black inner shadow.

We paint it orangey using feColorMatrix as detailed here https://mastodon.social/@anatudor/112157559510002242

Finally, we put it on top of SourceGraphic (bottom layer in2 input). This is done with the default (normal) mode for feBlend.

#svg #filter #svgFilter #blending #compositing #blendMode #alpha #inset #shadow #css #code #coding #web #dev #webDev #frontend #webDevelopment

A really cool bonus with this #SVG #filter method is that it also works on non-rectangular shapes! 🥳🎉

See this #CodePen demo https://codepen.io/thebabydino/pen/abVgQJB/ - also an entry for this week's #CodePenChallenge

This can help with sliders such as these https://codepen.io/thebabydino/pen/PwaGLM

#filterEffect #mask #masking #cssMask #CSS #code #coding #web #dev #webDev #webDevelopment #frontend

Inset shadow on irregular progress

...

@anatudor

Always wondered why an inset box-shadow is rendered below the element. Is there a real life use case for that?