Lea Verou: The web design cheat code: Using SVG to bridge CSS’ gaps

(audience applauding) – So, hello everyone. Thank you for being here. Before I start a few words about me. So, hi, I’m Lea. Here’s a fun fact you
may not know about me. I’m originally from Greece, even though I live in Boston now. And specifically, I grew
up in the island of Lesbos. Which technically makes
be geographically Lesbian. Probably the first you’ll ever meet. (audience laughs) I like Open Source you might
come commute some of my work. There’s some of my projects. You can find more on my GitHub. I’m an invited expert in
the CSS Working Group, so if you have any questions about like how CSS standards work, even if it’s not related to the talk, feel free to come and ask me, that’s fine. There’s me over there. I’ve written a book. If you have it with you I can sign it. It’s translated in a few languages and my day job is doing research at MIT. Specifically, my research is about making web programming more accessible. I work on this language called Mavo which is released as
an Open Source project. You can use it if you want. You can experiment with
it, give us feedback, maybe even contribute. It’s about making entire web applications by just writing HTML and CSS. So without further adieu, what I wanted to talk to you about today is basically the
intersection of SVG and CSS. I think everyone
understands the value of SVG when it comes to logos,
interactive visualizations and things like that, but
there’s a number of small ways that SVG can enhance what CSS can do. SVG is so much more powerful. Sometimes in slightly more worse syntax, but it’s a lot more powerful. It can do so many things
that CSS can’t dream of yet. So, that’s what this talk is about. But before I start, I wanna
get something out of the way and that’s coordinates. Because there’s many people, even people that hand code SVG for awhile, tend to be confused about how coordinate systems work in SVG. So, here I have an SVG that’s
just dropped into my HTML. Assume that this is
inside my body element. And I’ve given it a
width and height of 200. So, as you might predict,
it’s width and height is 300 by 200 pixels. And I also have a rectangle
that’s 100% by 100% which occupies the entire SVG. Nothing unpredictable there. Let me add a viewBox. So a viewBox defines
your coordinate system. And notice, that now
I’ve defined a viewBox that’s basically half of my width and half of my height and suddenly, so the rectangle that was
sized based on percentages didn’t change, it still
occupies my entire SVG. My aspect ratio didn’t change because it’s the same in my viewBox, but the direct angle I
have basically doubled. Because now the unit
list numbers are based on the coordinate system I just defined, which is defined by the viewBox. I can even do crazy things,
like this for example. And then if I want this to
be half it’s point five. Like it, these numbers, these unit list numbers are
all relative to the viewBox. Okay, let’s go back to a
more normal viewBox here. So, notice that now,
I’ve specified a viewBox that’s 100 by 100 which is different than, it defines a different aspect ratio than what my width and height specify. So what happens then? Both the rectangle
that’s sized 100% by 100% and my rectangle that’s
sized with unit list numbers they both occupy the space that I’ve defined with the viewBox and then the rest of the space is just filled by the SVG element. You can see the yellow background I’ve defined behind it here. And it’s just useless space. If I don’t specify one
of these dimensions, the other one is calculated
based on the aspect ratio. Similarly, if I remove the
height it will be calculated based on the aspect
ratio, so it will be 300. And if I remove both of them, then the SVG stretches to
occupy the entire element. And also, there’s very weird behavior if I don’t specify any of them. And that behavior is different
based on how you use the SVG. In this case, because
it’s embedded in my HTML it becomes 300 by 150. But if I was using it in an SVG image, it will actually stretch
to occupy the entire area that it needs to depending
on how I’m using it my CSS. We’ll actually take advantage
of this later in the talk. So, to recap. The viewBox defines the coordinate system. It also defines the aspect ratio. There’s a property that
allows you to override this. We’re not gonna use it, so I’m not gonna stress it very much. And a viewBox with no width and height makes the SVG
scale to fill the entire area. That’s what I want you to remember because it will be useful
throughout this talk. And now, let’s go on to
some more practical things. So, I’ve often needed to use characters, like Glyphs from a font as images whether they were like
special Unicode symbols, emojis, just plain characters. And usually what I did,
I had to go to Photoshop or Illustrator, insert my character, style it in the way I wanted and then export it to PNG or something and then use it in my CSS. Until eventually, I realized that I could embed SVGs in my CSS. And I’m sure most of you
have seen things like this. This is actually an SVG circle. It paints this red circle
that you see over there. But it’s kind of awful,
you can’t really tell that it’s a circle just by
looking at the code, can you? It’s just meaningless characters. And this is how most of us
get introduced to data URIs. And sometimes we never learn
that you know data URIs can be more readable than this. Sometimes, we learn that
you know we can wrap them in multiple lines by escaping
the end of each line. Just like, and this applies to every URL, but okay, so now we don’t
have horizontal scrolling but it still doesn’t make any sense. However, little known fact,
when the file you’re embedding is a plain text resource, not just SVG, any plain text format; CSV,
TSV, TXT files, anything. Anything that’s plain text, you can actually just
dump it in your data URI and you only need to escape
very, very few characters that have special meaning in URLs. The only one I’ve come
across in everyday practice is the hash character we’ll
see a case of escaping it soon. But most characters don’t actually need to be escaped these days. We might have seen this
with like all the characters URL encoded with like
percent signs everywhere and that’s still not very readable. But we don’t actually
need to escape all that. Old AI needed it. Today we don’t have to
care about old AI anymore. We don’t really need it. So, what have we done here? That’s just a regular SVG file. I can modify it right in my CSS. I can move the circles here. I can move it up, whatever. I can make the background smaller because it’s just a background and it works exactly the same
way as any other background. But now you might be thinking, okay Lea, so you’ve done all this
just to show us a background that’s a series of dots? I can do that with radial-gradients. Well, yes, but this opens up
the entire power of SVG to us. Not just circles and rectangles. For example, what about a text element? And now you can’t see
anything for two reasons. Because by default the baseline is zero, so the entire character
is clipped at the top. So we can define the baseline
to be 1em to bring it down. And now you can start seeing
this tiny, tiny, tiny A. And I can make it bigger by
just specifying a font size. And there we are. Now we have a background that is our, that is comprised of the A character. You might be wondering, well, I’ve never needed
to have a background that is the A character,
like how is this useful? Well, the Unicode table is
way more rich than this. What about a background
that is a unicorn emoji? Why not? (audience laughs) And you might be thinking,
okay well whatever, I could just export the
PNG with the unicorn emoji. Yeah, but can you enter CSS in that PNG? We can actually have a style
element in the data URI that is inside our CSS and
then we can do whatever. Let’s define an animation in here. – [Audience Member] No way. (audience members laughing) – And let’s give it some rotation, okay. So we’ve defined a dance animation. Let’s go here and apply
it and let’s say infinite. And let’s make it alternate
so it doesn’t just jump to the beginning when it finishes. And that’s a bit of a slow dance. Lets make it faster. (audience laughs) There you go. (audience applauds)
(audience cheers) So, there’s a bunch of takeaways. As we already mentioned you
can have multilane data URIs by escaping each line with a slash. This is very important. Everything will break if you
don’t include that slash. You can embed SVG in
your CSS with data URIs and most characters don’t
need to be URL encoded. And you can use these data URIs to create images out of characters. And of course, you have access
to everything you can do in SVG, that’s just one example. And you can even create
animated backgrounds with CSS animations
inside the embedded SVG. What can we use this technique for? One very common example that came to mind was you know sometimes we
wanna style block quotes with this fancy quote character that is sort of a
background like huge code that’s like a background. And usually we do this
by carefully positioning pseudo-elements or
exporting the quote as PNG. Well, we can use this to do it and there’s actually a Unicode character for this fancy quote. We can style meters with it. And then, we usually
start with star rating which only give us a flexibility rating either integer number of stars or, at best, like half a star. In this way, we don’t just
have access to like half stars, but also any decimal number of stars. Could even be something
like, you know, this and it will still work. I was actually using it earlier in my talk when I showed my book. And you can see how that works. The code there is some ugliness there because we can’t yet
style meters properly. This is gonna be fixed eventually, but brace yourselves for now. It does require a webkit pseudo-element. And for Firefox it will require
a small Moz pseudo-element that I’m not showing in this slide for the purposes of saving space. But in reality, you would also
need another rule for Firefox and another rule for Edge,
thankfully it is going away. So you won’t need that one soon. And even worse, there’s
lot of repetition here. You have to repeat the data URI twice. One for the semitransparent version and one for the actual opaque version. Let me show you how that works by changing the star to something else. So let’s assume instead of rating in a scale of one to five stars, you were rating chocolate ice cream so you wanted to rate it on a scale of one to five chocolate ice creams. So you saw how the different
layers overlap, right? And you might be wondering why can’t I use CSS variables for this? And well done for
thinking of CSS variables. CSS variables are awesome,
but they can’t do this yet. This is the kind of thing
we would want to do, right? And after we’ve done this we would also wanna put
the emoji in the variable. And then we could change just
that variable with the emoji. And we would have a different background. Unfortunately, we can’t do this. And we can’t do this for two reasons. Firstly, we don’t have
any concatenation in CSS. You might be thinking, but Lea, I’ve concatenated strings
before in the content attribute. Yes, you have, but that’s very specific to the content attribute. It’s not, it’s defined in
the same property definition that specifies what’s the syntax
for the content attribute. In other places in CSS, putting
strings next to each other doesn’t concatenate them. Similarly, you can’t
actually use a VAR function in the URL function at all. Even if there’s no
concatenation happening. Even if your entire URL function just contains a variable reference, that will still not work. And it will not work because
there’s special parsing rules to handle unquoted URLs. URL was the first function we got in CSS starting in CSS One. And to put it mildly, things were not very
rigorously defined back then. So, basically there’s a bunch of ugliness and hackiness for browsers
to handle this function and that has, the ugly consequence that anything you put
inside the URL function is treated as a URL. If you put a var reference
inside a URL function, the browser will think
you’re actually trying to reference a URL that starts with like var open parenthesis
dash, dash, whatever and it will try to fetch that URL and, of course, it will fail. Thankfully, we are
aware of these problems. We recently resolved to
solve these problems. The way we plan to solve them is we’re gonna add a new function for that basically does the same thing as URL, but it only accepts quoted URLs so it doesn’t need all
the parsing wonkiness. And also, we’re gonna add a new function for string concatenation that
you can use everywhere in CSS. The names for these functions
are still under debate and don’t hold your breath
for both of these features. The timeframe is kind of long
to add new things to CSS, but at least, if that’s any consolation, a solution is coming. And it will be useful for way
more things than just that. In the meantime, one way
to reduce duplication when you use these kinds of
techniques is reprocessors. They’re still useful. In large projects I
actually like to define large series of functions
that generate inline SVGs. My book was written in HTML and CSS and actually the CSS was basically Sass. And there is so many functions
generating SVG in there. The base one would be like
an inline SVG function. This is a sort of simplified
version of what I usually have. And it just generates an SVG
data URI with all the stuff that you don’t want to
repeat again and again, like the xml name space
and the data:image, SVG+xml. It’s kind of tedious. And then you can define
all sorts of functions. One for rectangles. One for circles. One for paths. One for emojis. Why not? And then the code I showed
you earlier for the meter could be simplified like this. One thing we can use variables in, the CSS variables in today,
is for the entire URL. So here, I have a variable
holding the entire data URI and that means I can create
multiple layers of it without having to repeat this entire… This entire URI which
is kind of a long thing. And let’s give it slightly
different positions maybe. Kind of like that. Maybe like this. And imagine how long this code would be if I had to repeat this data URI. And, of course, now you
can also animate it. And yes, I’m aware that this
is not a talk about animations, but, come on, animations are awesome. So we can animate background position Y to the different background
sizes so that it appears smooth. Five, three, 10. So let’s try that. And then we go here to
apply our animation. Snowfall we called it, I think. Let’s say three seconds
and we want it infinite and we don’t want this sort of like weird ease timing function
so let’s make it linear. And there it is. We can actually make the, we could actually make it move
horizontally a little bit. ‘Cause now it doesn’t look very natural. That sort of looks more natural. And I mean we can make it
snow in the entire slide, why not? (audience laughs) And we can, since there is a
variable holding our snowflake, if we wanna change while
it’s actually snowing we can just change it one
place and it will just work. For example, instead of a snowfall, let’s say we wanna make it raining men. (audience laughs) So we choose a man in business
suit levitating emoji. Apparently that’s a thing. I have no idea what the Unicode consortium
was thinking, but. (audience laughs) It’s a thing. So now it’s raining men here. So, fourth takeaway. You can use CSS variables
for the entire URL. And here’s another one
of my favorite use cases. List bullets. And it’s one of my favorite use cases because it’s such a small thing. It’s not fancy. But, it’s so commonly needed. I’m sure every single one
of you has needed to use custom bullets at some point in lists and what we ended up
doing is list style none and then like weird
pseudo-element positioning and then it often breaks
with multi-line text. However, with this technique
you can actually use list style image and have a real bullets. Let’s have a circle for example. Which is probably the
simplest list bullet. I already have a viewBox of 100 by 100. So let’s make the center at 50 and let’s make horizontally
maybe a little bit higher and give it a radius of 10. No, that’s to small, 20 and then we can give it
whatever fill we want and we have colored bullets. Or, I don’t know, whatever color you want. That’s sort of like a faded red. But you might be wondering okay, well, round bullets are not that interesting. But, of course, you can
have anything in there. So why not have text. And specifically, emojis. Same thing that we showed earlier. And again, the font size. Notice that I can also use attributes, but they have zero specificity so any CSS will override the attributes. And you can have sad emojis if
it’s a list about sad things. (audience laughs) And you can even have like classes that override each individual item and give it a different bullet. Like I had a slide earlier
with like all sad emojis and then like the last
one was sort of happy. So the fifth takeaway
is that SVG data URIs can help you create bulletproof
custom list bullets. And why do I say bulletproof? Let’s add some multi-line text. And you can see that it just works fine. We don’t have to do any weird like margin, negative margins, text
indents, all this stuff that I’m sure you’re traumatized by it when you use pseudo-elements
for custom bullets. It just works. It just works, it’s a regular bullet. So take a moment to look at this border. There are three reasons why
you can’t have this border in CSS today, at least, without any SVG. So, in CSS we can have dashed borders, but we can’t have custom dash links and custom dash gap links. It’s just whatever the
browser wants to give us and if we’re happy with that, if we’re not happy with that, tough shit. (audience laughs) Also, we cannot have borders that are colored by a gradient in CSS. Even though we do have
gradients for backgrounds, we can’t apply them to borders. And, of course, we can’t
have animations like this that make our dashed borders move. So, let me show you how you
can, how you can use SVG to have any of these things in your HTML. We’re gonna start from
a very plain rectangle. It has a width and height of 100%. Notice that it has no viewBox. There’s a reason for that
and we’re gonna get to it. And for now, it just has a
stroke, like a thin black stroke and that’s it and no fill. There is, so for this first
example I’m gonna show you how you can have a custom dashed border that animates in the way we saw. Like you know this marching ants animation that you also see in graphics applications when you select a rectangular area and like you get this dashed
border that actually moves. So how are we gonna do that? SVG has this wonderful property
called stroke-dasharray which allows you to specify exactly what your dashed strokes will look like and it accepts any number of numbers. The first one is your dash length. The second one is your gap length. And if you don’t provide the gap length, you can notice that it’s
the dash length by default, it just repeats. Basically anything you specify
here will repeat infinitely. So, you an actually have like
another different dash length and you can have all sorts of weird morris code patterns here. Although I haven’t found many use cases for having more than two numbers there. And there is also a
stroke-dashoffset property which starts from zero. And it controls where
your dashed border starts. So notice that now if I’m incrementing this property manually,
by just like pressing my arrow key here, I actually
got the animation I wanted. So, all I really need is to automate this animation
with CSS animations. And since these have
normal CSS properties… And since these have
normal CSS properties, I can just animate them
with an add keyframes rule. What would my keyframes be? Obviously I would start from zero, but then what would my ending keyframe be? Notice that I want this
to repeat infinitely, so I need to select an ending keyframe that will make it look like it’s continuously doing the
same movement infinitely. And the number that
will give me this effect is any multiple of my dash
length plus my gap length. Let me show you how this works. So if I have zero here, I get this result. My dash is 10 and my gap is five, so together their 15. If I put minus 15 here, I get
exactly the same visual result because I’ve done one iteration. It has moved by one dash and one gap. Same with plus 15, any
multiple of 15 works. So I’m gonna take advantage of this and apply an animation. Select other style element
and the keyframe element, let’s call it ants ’cause
it’s like marching ants and let’s paste this in here. And now, let’s apply this ants animation and let’s make it infinite. And we’re almost there, except notice that you get the default
easing which is ease which doesn’t make it move smoothly. You can see where it’s
animation iteration ends and the next one begins because
the default timing function accelerates and then decelerates and accelerates and then decelerates. So we also need to specify a linear here and there we are. You might be wondering, okay we did this, but this is just an
SVG that’s in our HTML. I actually wanted to apply
this to my HTML elements. Well, I’ve got you covered there. So, we copied what we just wrote and here we have a div
with a class of unicorn. And I have a data URI ready for us here and let’s just paste
what we wrote in here, escape the ends of lines and there we go. And actually, I can make
it, I can give it any… I can give it any aspect
ratio and it still works. And why is that? That’s exactly why I did
not specify a viewBox. Because if you’re using
an image as a background, and you don’t specify a
viewBox or any dimensions, then the SVG will stretch to accommodate the entire background positioning area and any unit list numbers in
it will be treated as pixels. So you get the same stroke width regardless of the proportions
of your HTML element. Meaning regardless of your actual background positioning area. And the numbers we specified
are actually pixels. They’re actually treated as pixels. We would not get the same
result if we had a viewBox. This is one of the few cases where you don’t specify a viewBox. Usually it’s good practice to include a viewBox with everything. So, takeaways. No viewBox or dimensions
lets your SVG background occupy the entire element. Stroke-dasharray lets you
create custom dashed borders and stroke-dashoffset lets you
move them and is animatable. Stroke-dasharray is also animatable. There’s lots of cool effects
you can do with that. For another example, here
we have a thick stroke applied on a rectangle, again with no viewBox for the same reason. And we’re gonna apply a
gradient to that stroke. Brace yourselves a bit
because the syntax in SVG is not very nice for this,
but the result is worth it. So, SVG got gradients about 15 years before CSS got gradients. So, they’re a little more clumsy. We had like 15 years to
flesh them out for CSS. So, for SVG we define a
linear gradient element. We give it an ID, so we can reference it. And then, the color stops
at actual stop elements. And let’s say, and we specify the color with the stop-color property. And let’s give us the blue
we already have, zero AC. And now, how do we apply
this gradient as a fill, as a stroke, whatever? With the URL function believe it or not. So, we use the URL function with it’s ID. I’m not sure if that was
brilliant or horrible, you can decide for yourselves. Now, you might be wondering, well, Lea, you specified a gradient there and it has two stops but
I don’t see any gradient, it’s still just blue. So in CSS when you specify two colors they’re spaced automatically. So if you specify two colors, the first one goes to the beginning, the last one goes to the end. If you have more than two
they’re also equally spaced. However, in SVG you have to
manually specify the offset and now you have a gradient. Before we didn’t really get a gradient because they were both at zero,
which is the default offset. Now, we also want to apply… We want the gradient to be angled, we don’t want it to be left to right. We want it to have like a 45 degree angle. How do we do that in SVG? There is a gradientTransform attribute and it accepts an actual
transform function, like rotate. And the syntax is slightly
different than in CSS. In CSS transforms,
again, SVG got transforms from the very beginning
in like 1998 or so. So the transform syntax
is slightly different. Notice that it doesn’t have units for one. There were no angles back then, either in CSS or in SVG. So you can’t actually
add a deg unit after it. Which also means you
can’t use different units. You can’t have a turn unit or a radian or anything like that like in CSS. This is a caveat to
keep in mind in general when you’re writing transforms for SVG, especially because in some
places you get the CSS syntax and in some places you get the SVG syntax. Anytime you’re using an attribute in SVG, then it uses the SVG transform syntax. If you’re using a property, even if you’re applying the
property to SVG content, then you’re using the CSS syntax. But here we can’t use a property so we have to use an attribute. So, this is our gradient stroke. And let’s copy it and
paste it onto our data URI so we can apply it to HTML content. And escape the endings of lines and now, notice that this
was still not sufficient. There is something more we need to do. Remember when I mentioned that most characters
don’t need to be escaped? One common exception to
this is the hash character. We actually do need to escape this as %23 and here as well. And now, we got our stroke. There’s another caveat. It’s actually showing it’s
structure as a background. Like yes, we’re treating this
as a stroke but actually, ultimately it’s a background really. And we can see it going behind our text. But this is something we can
easily fix with a padding. And if we want to have
both space for our border and an actual padding we
can just say 20 pixels plus 1em, for example. You might be wondering
why is our stroke width 40 but our padding is 20? Did anybody notice this? Raise your hand. Cool, some of you noticed this. So actually in SVG when you draw strokes, half of the stroke is inside your shape and half of the stroke
is outside your shape. And there is no property to control this. There was one added in SVG Two, but because browsers were not
interested they took it out. If you do care about such a property, you should complain to the browsers because that’s what ultimately
controls adoption of things. So in SVG there is no way to avoid this. Strokes are always drawn
half in and half out. It’s not like Illustrator
where you can press a button and have your stroke on the outside and press a different button and have your stroke all on the inside. And it’s actually as
we’ll see in a later demo, as we’ll see, it’s actually quite
complicated when we really, really need to draw our
stroke on the inside. It can get very complicated. But in this case, it’s fine
if half of it is clipped. We still get a gradient border. It still works fine. So, SVG supports gradient strokes, though with an unwieldy syntax. You can apply those to HTML
elements via data URIs, as we’ve already seen. And you need to escape the hash as %23 because it’s a reserved character in URLs. You don’t actually need to escape every reserved character in URLs. The browser is smart enough to figure out, for example, if you’re using a colon it’s not actually a protocol
in the middle of the URL. So it’s very few. I think it’s also the question
mark that you need to escape and that’s pretty much it. So, another example of fancy strokes that we could fake with SVG. Quite often there are
websites that try to pretend they have this handwritten
style and things are sketched. You know, they wanna give this organic design kind of feel to them. And usually, we do this by
applying like handwritten fonts, but when it comes to borders
it can be quite a pain. You have to usually have like
separate files for the border and apply them either with border image or like have fixed dimensions. However, there is a
way to do this with SVG which is what this demo is about. It involves using filters. How many of you have used SVG filters? Very few, okay. So, filters in SVG are
defined by the filter element. Just like gradients we
give them a name, an ID and we reference them by the
ID and the filter property. And notice that now I don’t see anything because my filter is empty. So it makes my entire element disappear. Let’s add an feTurbulence filter. And it requires a base
frequency attribute, let’s say point two. So what does feTurbulence do? It uses a certain algorithm
to generate a random pattern. Which is not very useful by itself, but it will be very useful in combination with other filters. And so, it requires a base
frequency attribute as a minimum and you can also use a
numOctaves attribute to specify how many times this frequency
repeats, how many octaves. We’re gonna use three. Why are we gonna use three? Just for experimentation. And then, we’re gonna
use another filter here an feDisplacementMap and, god,
I hope I write it correctly. (she laughs) So, this filter accepts two inputs. But in general when
you’re chaining filters one after the other,
each filter takes as a, by default each filter takes the result of the previous filter as an input. Which is actually convenient in our case. So we’re gonna use SourceGraphic
as our first input. SourceGraphic just corresponds to whatever thing we
applied the filter on. Which is why we just
suddenly saw it again. And feDisplacementMap also
supports another input, a second input. But, we’re not gonna specify that because we actually wanna use the input of the previous filter
as the second input. And then, we can specify
a scale attribute. So what does feDisplacementMap does? What it does is kind
of a very weird thing. So it accepts a matrix as an image, but it does actually use the image. It doesn’t actually display
the image in any way. Instead it uses the second
input as a sort of matrix where the red channel specifies how much you’re gonna move horizontally, how much you’re gonna move
each pixel horizontally and the green channel specifies how much you’re gonna move each pixel vertically. It’s very, very weird. And the blue channel
is ignored completely. So basically what do we want to make it look like, a scribble. We want the pixels to
sort of slightly move in slightly semi-random ways. Which is why we have this
random texture via feTurbulence and then we’re using
this texture as an input to feDisplacementMap to make the pixels of our original image
sort of slightly move in semi-random ways. And then we have to specify
the scale attribute. Which by default is zero, which is why we don’t see any movement. Because by default the
offsets that we’ve specified are multiplied by the scale and by default it’s zero,
so there are no offsets. But if we increase it, then we’re starting to
see something there. Now, we have another problem. Remember when I told you earlier that half the stroke
is drawn on the inside and half the stroke is
drawn on the outside? Now, it’s actually
becoming a problem for us. And when it’s an SVG that’s
just directly embedded in our HTML, there are
simpler ways around it. We can just say overflow visible and there is our scribbled rectangle. I promised you it would look like that. However, overflow visible will not help us when we use this as a background image. Because the stuff that’s
outside the SVG area will just be clipped. So we have to find a
different way to do it. And there is where the ugliness starts. So, in Chrome we can say, we
can specify X and Y attributes to offset it a little bit. Come on, Lea, learn to type. And then we can make the width and height a little bit smaller, because Chrome allows
us to use calc in here. So we can say calc 100% minus
six and here also minus six and now we have our whole rectangle. And this will actually
work as a background. However, this will not work in Firefox. Firefox hasn’t caught up yet
and it doesn’t allow us to use, to use calc and fancy things
like that in width and height. Instead to support Firefox we have to do this horrible thing. Which I’m not gonna type for you because I wanna forget this exists. But if you need to support Firefox, if you really need this squiggly
effect to appear in Firefox you have to actually make the
rectangle yourself from lines. And why from lines? Why can’t you use a path or something? Because you can’t use percentages in paths and we actually really
need percentages here. So, we have lines sized in percentages with transforms to offset them. Yeah.
(audience laughs) But for the rest of it, I’m going to use the calc
technique because it’s shorter and because eventually
Firefox is gonna catch up. So, we have our squiggly rectangle. Let’s try to apply it to HTML now. Again, the same div
with a class of unicorn. Again, we paste it in here. We escape the lines. And we escape any hashes. Where are they? There we are. Yay, and we also give it a padding. (audience applauds) Thank you. So, let’s give it a padding. Maybe too much. Okay, so now what else
can we do with this? To recap before we move forwards. So you can use calculate
in geometry attributes, but not in Firefox yet. feTurbulence creates a
pseudo-random texture. feDisplacementMap shifts pixels around based on the pixel
values of another image. And together they can be used to create a scribble effect as we saw. How many of you have
heard of Squigglevision? Only one. Okay, so to be fair I hadn’t heard of the word Squigglevision
before I made this talk. I had to research what is
this effect actually called. That resulted in many
weird Google searches. I hope nobody gets ahold of my history. So, the effect I was looking
for was basically this that I’m sure you’ve all seen in cartoons. Where something is basically
supposed to be stationary but it has this effect
of like multiple frames that are drawn separately
being infinitely circling between all these frames. So how could we do this effect? Could we apply this effect in our divs? Like we’ve already done the
scribble for our borders, but what if we want the scribble to actually animate like this? Could we do that? Let’s try. So, here’s the rectangle we’ve already… Here’s the scribble we’ve already created. And there is another parameter
of the feTurbulence filter that I haven’t mentioned
and it’s called seed. Seed starts from zero, so seed’s the random number generator. But it could be anything. Like you can seed it
with any number you want. And notice that if I
manually increase the seed, then we do sort of get
Squigglevision don’t we? We just need to automate this. What I’m doing here by
incrementing the seed, I just need to automate
it with an animation. So my first attempt that
I’m not gonna show you was trying to use a keyframes animation and hoping that seed has
also become a property. But no, none of these filter attributes have been ported into properties. We’re currently in a sort
of transitional phase. The browsers are porting more and more of SVG attributes
as CSS properties so we can animate them
with CSS animations, but for these filter
parameters we’re not there yet. So we need to use a slightly
older way of animating SVG stuff, which is still
supported pretty much everywhere. It’s called SMIL. Again, this is a running theme. It’s kind of ugly, but powerful. So, the way SMIL works is
you nest an animate element inside the thing you want to animate and then you specify a
duration, let’s say one second. And an attribute name,
which in our case is seed. And values, which in our
case is let’s say one to 10. And then a repeat count
which should be indefinite. Is it, what did I do here? Hmm. Come on don’t fail me. Hmm. – [Woman] Is it the values
one through 10 before it? – [Lea] Yeah, yeah, yeah
it should be a colon. Hmm, and I guess nobody has seen SMIL before so can’t spot what
I did wrong here, right? I think it’s the duration, but oh, god. – [Man] Should it be infinite? – [Lea] No, no, no that’s
actually a point I wanted to make that it’s for some reason it’s indefinite and not infinite in SMIL. Oh, well. Should I, hmm? Well, I shouldn’t spend too
long trying to debug this. (man talking off mic) – [Lea] What? – [Man] You’ve have it
coded with from and to. From minus unto two. – [Lea] No, no, my values should work. Actually, you know what? Just close your eyes here for a bit. (audience laughs) (audience talking) – [Audience members] Ah, semicolon. – Semicolon. (she laughs) (audience laughs)
(audience applauds) Yeah, in retrospect maybe
I should have just said you know let’s pretend
this works and move on, but yeah I didn’t want to
’cause I love this effect and I wanted share it. So yeah, semicolon not colon. So, let’s apply this to our HTML element. Here’s what we’ve done previously. And I guess we don’t actually need to go and escape everything again,
we can just copy this. That’s the only change we made really. So let’s go here, insert a
new line, escape that line and paste this. So you can see that now we’ve got Squigglevision for the border. And it’s animating and
I hope you can see it from the back animating,
as well right, can you? Okay, good. So, yes. So you cannot animate filter
parameters with CSS animations, but you can use SMIL. Animating the seed of
an feTurbulence filter creates Squigglevision. Are we done yet? No.
(audience laughs) So, after I got this
working I was thinking, you know what, this doesn’t
look like proper Squigglevision. The borders animating,
but the text is not. So, how could I also make the text animate to like make it look like
proper Squigglevision? One way to do that would be
to actually move the border from the SVG to an HTML
border, to a CSS border and then apply an SVG
filter to the whole thing. You can apply SVG filters to HTML content so that should work, right? So what I tried was something like this. And then I removed the
rectangle from here. And instead I changed the
background with a filter and I added a hash here for scribble. And notice what happens, it’s not that it completely doesn’t work, it is actually applied. But it’s not animating. Do you see this? Let me, let me tweak it on and off. Now it’s not there. Now it is. Now it’s not there. Now it is. You can see that it’s
applied to everything but it’s not animating. For some reason, in Chrome
if I specify a filter via URL it doesn’t seem to support
animation in the filter. I’m not sure why but do not give up, because there is a workaround. So, if you actually include the SVG. If you actually embed the SVG in your HTML and let’s actually copy
it from where from here, that’s better. Where were we? Now, let’s go here and paste the SVG here. And hide it with display none. And actually will this work? Hmm, yes. So basically we pasted the SVG here. We don’t actually need
the rectangle anymore we just need the filter. It still has the same ID. And we don’t need a URL here anymore because it’s actually local now. And now, we got Squigglevision. And let’s specify some padding,
too, to make it look nicer. (audience applauds) Thank you. So I think now, we are pretty much done. To recap, if you use a data
URI in the filter property animation is disabled in the filter. It’s probably a browser bug. And including the filter
in your HTML can fix that. And you can actually hide the filter. You don’t need the SVG. You don’t need to display
the SVG in any way. It’s just a little bit
of ugliness in your HTML. You can pretend it’s not there. So, this is actually what I used in the cover of this presentation. If you look at the heading, where it says The Web Design Cheat Code, it actually has that applied to it. So I hope that was useful. Thank you very much. I also have stickers, come find me. (audience applauds)
(audience cheers) – I love how you said, don’t give up. As if any of us would have
got 1% as far as you did with that, that was absolutely incredible. I spent most of that in shock. (Lea laughs) Not really like, just uh, that’s amazing. The Interweb’s once again
given us some questions both from in the room and remote. So if you don’t mind, I mean
to ask you some of them. – [Lea] Sure. – The top one I’m going to
read it in what I imagine the voice is of the person who wrote it. (Lea laughs) But only because it sounds very indignant. And that’s, what about Internet Explorer? (everyone laughs) – Well, if you look at the market share of Internet Explorer, it’s actually extremely
small at this point. Even IE-11, even if you
combine all of the IEs up to IE-11 it’s like one or two percent. And if you design things properly
with graceful degradation, progressive enhancement, like ultimately these
are all visual effects. If they’re not there, website
will just look less pretty. It won’t break. Like you have to do something
very wrong to actually break a website because
Squigglevision is not animating. (audience laughs) Or because the border
doesn’t have a gradient. – [Seminar Host] Can we all
say Squigglevision more. That’s actually the best
word I’ve ever heard. Should we all say it together? Should we all say it together? On three. One, two, three. – [Everyone] Squigglevision. – Amazing. (she laughs) Sorry, I was gonna freak out there. Right, next ones. Will the slides be available
after the talk and– – [Lea] Look at the URL. – Easy, easy tiger, easy
unicorn I should say. And what software did
you use to make them? Everyone seems to be
very interested in that. – [Lea] Also, (she laughs)
also, on the last slide. – [Seminar Host] Oh,
if had read the screen, I would have known. – [Lea] It’s also something that I wrote, but it’s in a separate repo in GitHub. – Amazing, okay, let’s all go immediately use that. And we’ve got a slightly
combative one, I feel. Once CSS Houdini can be used will there even be a point for SVG? Oh, she’s sitting down for this one. It’s gonna be big. – I believe we’ll be
able to use Houdini specs pretty soon, because browsers are very, very interested in them. I still think there’s value in SVG. First off, not everybody
can write JavaScript. So even with Houdini
specs you’re stuck using other people’s effects unless you can write JavaScript yourself. And not every single colleague
of ours can write JavaScript. There are many designers
or Front-End Developers that just focus on HTML and CSS and they cannot write JavaScript easily. And actually, and it’s not
even like super trivial cases. Like writing Java Script to define a new sort of visual effect via Houdini is not something like someone can do that just knows like super
basic JavaScript, either. So, I think there’s still value for declarative languages like SVG. It’s a different paradigm and its, actually part of my day job
is studying these people that don’t write backend
code or JavaScript but they are professioned
with HTML and CSS. Like my entire research is about enabling them to do
more with HTML and CSS. And there’s a lot of these
people they are very capable, but like imperative programming
is not for everyone. It’s not something that
is easy for everyone. So, I think there’s always gonna be space for declarative languages like SVG just because you can’t always expect someone else to write the effect you want. You can just write it yourself in SVG and often, with much less code. – Thank you for that succinct answer. Thank you. We’ve got a couple more. We’ve got two more minutes,
so I think two more questions. Ah, no someone just put
another question on. There was two questions,
they ruined it for me. How heavy are these
animations on the processor and battery. – It depends on the animation the Squigglevision one is kind of heavy. The rest are okay. The rest are pretty performant. – I didn’t know if that
was a pause for water or dramatic pause or like
that, that’s why I was waiting. And is it possible to apply
anti-aliasing in SVG filters? – I’m not sure how. If you discover how,
please tell me as well, ’cause I also don’t
like the aliasing there. But when I looked into it,
I couldn’t figure it out. – Wow that’s, that’s really amazing. That’s all amazing. Can we have another round
of applause for Lea, there? (audience applauds) And also, get it Amy, get it. You’ve overly keen you are. That’s always been your problem, that is. Yeah, yeah, too keen. Lea, Frontend United somehow found out that you were pregnant. (everyone laughs) I don’t know how.
– I wonder how? – [Seminar Host] I don’t know how. So we would love to give
you a little present. So here you go.
– [Lea] Ooh. – And if you would care to
unfurl it for the crowd. – [Audience] Aww. – Oh, my god. This is the cutest thing ever. (audience applauds) Aww.


Add a Comment

Your email address will not be published. Required fields are marked *