Glowing SVG Paths

by Scott Kaye

HTML

<div class="box">
    <svg viewBox="0 0 100 100">
		<defs>
			<linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="0%">
				<stop offset="0%"   stop-color="#f00"/>
				<stop offset="100%" stop-color="#0f0"/>
			</linearGradient>
			<filter id="glow" x="-50%" y="-50%" width="200%" height="200%"> 
				<feGaussianBlur in="SourceGraphic" stdDeviation="15" result="blur"/>
				<feMerge>
					<feMergeNode in="blur"/>
					<feMergeNode in="SourceGraphic"/>
				</feMerge>   
			</filter>
		</defs>
		
		<rect class="glow-path" filter="url(#glow)" stroke="url(#grad)" />
		<circle r="25" cx="50" cy="50" filter="url(#glow)" class="glow-path" stroke="url(#grad)" />
	</svg>
</div>

SCSS

$thickness: 2px;
$speed: 2s;

.box {
	position: relative;
	width: 200px;
	height: 200px;
	background: linear-gradient(#373737, #333);
	box-shadow: 0 0 15px #000, inset 0 0 5px 1px rgba(#f00, 1);
	margin: 20px 0;
	animation: pulse2 ($speed / 4) ease infinite, change $speed linear infinite;
}

svg {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	overflow: visible;

	> .glow-path {
		x: $thickness / 2;
		y: $thickness / 2;
		width: calc(100% - #{$thickness});
		height: calc(100% - #{$thickness});
		stroke-width: $thickness;
		fill: transparent;
		animation: loading $speed linear infinite, pulse ($speed / 4) ease infinite;
		stroke-dasharray: 200%;
	}
}

@keyframes loading {
	to { stroke-dashoffset: -400%; }
}

$wham: 3;
@keyframes pulse {
	0% { stroke-width: $thickness * $wham; }
	40% { stroke-width: $thickness; }
	90% { stroke-width: $thickness; }
	100% { stroke-width: $thickness * ($wham / 2); }
}

@keyframes pulse2 {
	0% { box-shadow: 0 0 15px #000, inset 0 0 10px 2px rgba(#f00, 1); }
	40% { box-shadow: 0 0 15px #000, inset 0 0 5px 1px rgba(#f00, 1); }
	90% { box-shadow: 0 0 15px #000, inset 0 0 5px 1px rgba(#f00, 1); }
	100% { box-shadow: 0 0 15px #000, inset 0 0 10px 1px rgba(#f00, 1); }
}

$sat: 3;
@keyframes change {
	0% { filter: hue-rotate(220deg) saturate($sat); }
	24% { filter: hue-rotate(220deg) saturate($sat); }
	25% { filter: hue-rotate(90deg) saturate($sat); }
	49% { filter: hue-rotate(90deg) saturate($sat); }
	50% { filter: hue-rotate(290deg) saturate($sat); }
	74% { filter: hue-rotate(290deg) saturate($sat); }
	75% { filter: hue-rotate(360deg) saturate($sat); }
	99% { filter: hue-rotate(360deg) saturate($sat); }
}

body {
	background: #111;
	margin: 0;
	min-height: 100%;
	display: flex;
	justify-content: center;
	align-items: center;
	flex-direction: column;
}

html {
	height: 100%;
}