The Web Design
Cheat
Code

Using SVG to bridge CSS’ gaps •

By Lea Verou (@LeaVerou)

Fronteers 2010

Fronteers 2011

Fronteers 2012

Fronteers 2019

SVG Primer
viewBox

CSS variables to reduce duplication?


			meter {
				width: 15em; height: 3em;
				--star-opacity: .2;
				background: url('data:image/svg+xml,\
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">\
					<text font-size="100" y=".8em" opacity="' var(--star-opacity, 1) '">★') 0 / auto 100%;
			}

			meter::-webkit-meter-optimum-value { /* ::-moz-meter-bar for Gecko */
				--star-opacity: 1;
				background: inherit;
			}
		

😢 Nope 😢

Why can’t we use CSS variables in url()?

  • No concatenation in CSS
  • Special parsing rules to support unquoted URLs
  • New functions to solve these are coming!

Reduce duplication with preprocessors


			@function inline-svg($content, $attr:'') {
				@return url('data:image/svg+xml,\
				<svg xmlns="http://www.w3.org/2000/svg" #{$attr}>\
				#{$content}</svg>');
			}
		
		

@function svg-emoji($char, $attr:'') { @return inline-svg( '<text font-size="100" y=".8em" #{$attr}>#{$char}</text>', 'viewBox="0 0 100 100"'); }
		
			meter {
				width: 15em; height: 3em;
				background: svg-emoji('★', 'opacity=".2"') 0 / auto 100%;
			}

			meter::-webkit-meter-optimum-value { /* ::-moz-meter-bar for Gecko */
				background: svg-emoji('★') 0 / auto 100%;
			}
		

Idea suggested by Amelia Bellamy-Royds

sketchy borders

stroke-dasharray: 0% 400% to 400% 400%

baseFrequency, numOctaves, seed, scale, attributeName, dur, values, repeatCount

To support Firefox too:


			<g style="filter: url(#scribble); stroke: black; stroke-width: 4px">
				<line x2="100%" transform="translate(0 3)" />
				<line y2="100%" transform="translate(3)" />
				<line x1="100%" x2="100%" y2="100%" transform="translate(-3)" />
				<line y1="100%" x2="100%" y2="100%" transform="translate(0 -3)" />
			</g>
		

🤢🤮🤮

Squigglevision

SVG Filters on HTML Content

  • If you use a data URI in the filter property, animation is disabled
  • Including the filter in your HTML fixes that