<div class="metallicss">ほげほげ</div>
.metallicss {
	--convexity: 50%;
	border-radius: 64px;
	background: #c0c0c0;
	padding: 1em;
	--seed: 12;
	font-size: 3em;
	--metal: gold;
	width: 50%;
	text-align: center;
}
const base = [
		tag("rect", {
			props: {
				fill: "url(#gradient)",
				height: 1024,
				width: 1024,
				x: 0,
				y: 0
			}
		}),
		tag("rect", {
			props: {
				filter: "url(#texture)",
				height: 1024,
				style: "mix-blend-mode: luminosity; opacity: 0.5",
				width: 1024,
				x: 0,
				y: 0
			}
		}),
		tag("rect", {
			props: {
				filter: "url(#texture)",
				height: 1024,
				style: "mix-blend-mode: screen; opacity: 0.25",
				width: 1024,
				x: 0,
				y: 0
			}
		})
	],
	defs = tag("defs", {
		inner: [
			tag("linearGradient", {
				inner: [
					tag("stop", { props: { offset: "35%", ["stop-color"]: "#b0b0b0" } }),
					tag("stop", { props: { offset: "40%", ["stop-color"]: "#efefef" } }),
					tag("stop", { props: { offset: "45%", ["stop-color"]: "#909090" } }),
					tag("stop", { props: { offset: "49%", ["stop-color"]: "#707070" } }),
					tag("stop", { props: { offset: "51%", ["stop-color"]: "#303030" } }),
					tag("stop", { props: { offset: "60%", ["stop-color"]: "#909090" } }),
					tag("stop", { props: { offset: "70%", ["stop-color"]: "#505050" } }),
					tag("stop", { props: { offset: "100%", ["stop-color"]: "#505050" } })
				],
				props: { id: "gradient", x1: 0, x2: 0, y1: 0, y2: 1 }
			})
		]
	}),
	serializer = new XMLSerializer(),
	xmlns = "http://www.w3.org/2000/svg";
let blocked = document.body.className.indexOf("block-metallicss") !== -1;

function tag(name, { inner, props }) {
	const elem = document.createElementNS("http://www.w3.org/2000/svg", name);

	props && Object.entries(props).forEach((prop) => elem.setAttribute(...prop));
	inner?.forEach((innerElem) => elem.append(innerElem));

	return elem;
}

function sheen({ offset, radii: { x: rx, y: ry }, stroke, vertical, x, y }) {
	const margin = offset / (vertical ? x : y) / 2,
		size = offset / 3 / (vertical ? x : y),
		diff = 1024 - margin * 2 + size * 2;

	return tag("rect", {
		props: {
			"stroke-width": size,
			fill: "none",
			height: vertical ? 1024 + size : diff,
			rx,
			ry,
			stroke,
			width: vertical ? diff : 1024 + size,
			x: vertical ? margin - size : -size / 2,
			y: vertical ? -size / 2 : margin - size
		}
	});
}

export const unblock = () => {
		blocked = false;
	},
	metallicss = (elem) => {
		const { offsetWidth: width, offsetHeight: height } = elem,
			{ backgroundColor: background, borderRadius } = getComputedStyle(elem),
			depthValue = getComputedStyle(elem).getPropertyValue("--convexity"),
			seed = getComputedStyle(elem).getPropertyValue("--seed") || 23,
			metal = getComputedStyle(elem).getPropertyValue("--metal").replace(/ /g, ""),
			rawDepth =
				depthValue === "0%" || depthValue === " 0%"
					? 0
					: (depthValue && parseInt(depthValue)) || 20,
			lustre = `filter: ${
				{
					copper: "brightness(0.85) sepia(0.5) saturate(2) hue-rotate(-33.75deg)",
					gold: "brightness(0.95) sepia(1) saturate(1.5)",
					iron: "",
					silver: "brightness(1.125)"
				}[metal || "iron"]
			}`,
			depth = rawDepth * ((height > width ? width : height) / 640),
			absDepth = Math.abs(depth),
			x = width / (64 * (absDepth / 10 + 1)),
			y = height / (64 * (absDepth / 10 + 1)),
			radius = parseInt(borderRadius),
			radii = {
				x: height / 2 < radius ? 512 * (y / x) : radius * (1024 / width),
				y: width / 2 < radius ? 512 * (x / y) : radius * (1024 / height)
			},
			inverse = depth < 0,
			fill = background === "rgba(0, 0, 0, 0)" ? "gray" : background;

		elem.style.backgroundImage = `url('data:image/svg+xml;utf8,${encodeURIComponent(
			serializer.serializeToString(
				tag("svg", {
					inner: [
						tag("filter", {
							inner: [
								tag("feImage", {
									props: {
										preserveAspectRatio: "none",
										height: 1024,
										width: 1024,
										href: `data:image/svg+xml;utf8,${encodeURIComponent(
											serializer.serializeToString(
												tag("svg", {
													props: { height: 2048, width: 2048, xmlns },
													inner: [
														tag("rect", {
															props: {
																fill: "white",
																height: 2048,
																width: 2048
															}
														}),
														tag("g", {
															inner: Array.from({ length: 24 })
																.map((_, index) =>
																	sheen({
																		offset: Math.pow(
																			3,
																			index % 2 === 0 ? index / 4 : (index - 1) / 4
																		),
																		radii,
																		stroke: Math.ceil(index / 2) % 2 === 0 ? "red" : "white",
																		vertical: index % 2 === 0,
																		x,
																		y
																	})
																)
																.reverse(),
															props: { transform: "translate(512,512)" }
														})
													]
												})
											)
										)}`,
										result: "image"
									}
								}),
								tag("feGaussianBlur", {
									props: {
										["color-interpolation-filters"]: "sRGB",
										in: "image",
										result: "blur",
										stdDeviation: `${4 * (y / x)},${6 * (x / y)}`
									}
								}),
								tag("feDisplacementMap", {
									props: {
										["color-interpolation-filters"]: "sRGB",
										in: "SourceGraphic",
										in2: "blur",
										result: "displacement",
										scale: 50 + Math.abs(rawDepth) > 100 ? 100 : 50 + Math.abs(rawDepth),
										xChannelSelector: "R",
										yChannelSelector: "G"
									}
								})
							],
							props: {
								filterUnits: "userSpaceOnUse",
								height: 2048,
								id: "noise",
								width: 2048,
								x: 0,
								y: 0
							}
						}),
						tag("filter", {
							inner: [
								tag("feTurbulence", {
									props: {
										["color-interpolation-filters"]: "sRGB",
										baseFrequency: 0.005,
										result: "turbulence",
										seed,
										type: "fractalNoise"
									}
								}),
								tag("feDisplacementMap", {
									props: {
										["color-interpolation-filters"]: "sRGB",
										in2: "turbulence"
									}
								})
							],
							props: {
								filterUnits: "userSpaceOnUse",
								height: 1024,
								id: "texture",
								width: 1024,
								x: 0,
								y: 0
							}
						}),
						defs,
						tag("g", { inner: base, props: { filter: "url(#noise)" } }),
						inverse &&
							tag("rect", {
								props: {
									fill: "#20222480",
									height: 1024,
									opacity: `${rawDepth > -25 ? 25 : rawDepth * -1}%`,
									width: 1024,
									x: 0,
									y: 0
								}
							}),
						tag("rect", {
							props: {
								fill,
								height: 1024,
								opacity: 0.5,
								style: "mix-blend-mode: overlay",
								width: 1024,
								x: 0,
								y: 0
							}
						})
					],
					props: {
						preserveAspectRatio: "none",
						style: `transform: scale(1, ${inverse ? "-" : ""}1); ${lustre}`,
						viewBox: "256 256 512 512",
						xmlns
					}
				})
			)
		)}')`;
		elem.style.backgroundSize = "100% 100%";
		elem.style.border = "none";
		elem.style.boxShadow = `inset #ffffff80 0px ${
			inverse ? "-" : ""
		}4px 8px, inset ${
			{
				copper: "#402020",
				gold: "#604000",
				iron: "#202020",
				silver: "#404040"
			}[metal || "iron"]
		}${inverse ? "" : "c0"} 0px ${inverse ? "" : "-"}8px 16px ${
			inverse ? "" : ", #00000030 1px 2px 2px, #00000020 2px 4px 4px"
		}`;
		elem.style.color = `#${
			inverse
				? `${
						{
							copper: "100000",
							gold: "302000",
							iron: "000000",
							silver: "101010"
						}[metal || "iron"]
				  }c0`
				: "ffffffe0"
		}`;
		elem.style.textRendering = "geometricPrecision";
		elem.style.textShadow = inverse
			? "white .5px .5px 1px"
			: "black -.5px -.5px 1px";
		elem.style.transform = "translateZ(0)";
		elem.style.transition = "none";
	},
	traverse = () =>
		!blocked &&
		Array.from(document.querySelectorAll(".metallicss"))
			.filter(
				(elem) =>
					window.getComputedStyle(elem).getPropertyValue("display") != "none"
			)
			.forEach(metallicss);

if (document.readyState !== "loading") traverse();
else document.addEventListener("DOMContentLoaded", traverse);

export default metallicss;

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.