A presentation at pitercss_conf in in St Petersburg, Russia by Lisi Linhart
P E N
&
P A P E R
T O
P E N
&
P A P E R
T O
S V G
A N I M A T I O N S S V G
A N I M A T I O N S
lis ilin h ar t . in f o @ lis i_ lin h ar t in s t agr am . co m / lis i. lin e . ar t AN IL LU STR ATIO N A DVEN TU REAN IL LU STR ATIO N A DVEN TU RE
O U R
A D V E N T U R E O U R
A D V E N T U R E D R A W I N G D R A W I N G I S L A N D I S L A N D S V G
R O C K S V G
R O C K A N I M A T I O N A N I M A T I O N C L I F F S C L I F F S
D R A W I N G
I S L A N D D R A W I N G
I S L A N D
I N S P I R A T I O N I N S P I R A T I O N
A N A L Y S I S A N A L Y S I S
S K E T C H I N G S K E T C H I N G
S T R U C T U R E S T R U C T U R E
I N K I N G I N K I N G
C O D I N G C O D I N G
A R T I S T A R T I S T glue toge ther diff er ent ideas to one unison dr awing find simplicit y in their ideas find inspir ation in their surr ounding, mo vies , music cr af t dr awings mas ter simplicit y D E V E L O P E R D E V E L O P E R glue toge ther diff er ent components to one w orking s y s tem find s truc tur e in comple xit y analy se user needs , issues and compe titor s cr af t applications mas ter comple xit y
O N
T O
S V G
R O C K O N
T O
S V G
R O C K
D R A W I N G
S V G
� D R A W I N G
S V G
�
T H E
F I N I S H E D
D R A W I N G T H E
F I N I S H E D
D R A W I N G
T H E
M A G I C
O F T H E
M A G I C
O F A D O B E
I L L U S T R A T O R A D O B E
I L L U S T R A T O R
I M A G E
T R A C E I M A G E
T R A C E
I M A G E
T R A C E
O P T I O N S I M A G E
T R A C E
O P T I O N S
S P L I T
I N T O
L A Y E R S S P L I T
I N T O
L A Y E R S
E X P O R T
A S E X P O R T
A S
E X P O R T
O P T I O N S E X P O R T
O P T I O N S < s v g
" 1 . 1 "
" 0
< g
" f r a m e "
. . . < / g
< g
" a r r o w s "
. . . < / g
< g
6 "
. .
< g
5 "
. .
. . .
< / s v g
O P T I M I S E
W I T H
O P T I M I S E
W I T H
S V G O M G S V G O M G
S V G O
D I F F E R E N C E S V G O
D I F F E R E N C E 2 2 K B
1 2 . 6 K B 2 2 K B
1 2 . 6 K B
S C A L A B L E
S C A L A B L E
V E C T O R
V E C T O R
G R A P H I C S G R A P H I C S
U S E
S V G
F O R U S E
S V G
F O R scalable, r esponsiv e images small file siz es s t yling & animation via C SS debugging in the br o w ser accessibilit y via title at tribute
S V G
A C C E S I B I L I T Y S V G
A C C E S I B I L I T Y use inline S V G does it need alt te xt or is it decor ativ e ? pr o vide a title < s v g
" 0
0
1 0 0
1 0 0 "
" t r u e "
< p a t h
" M 3 . . . . "
< / p a t h
< / s v g
< s v g
" 0
0
1 0 0
1 0 0 "
< t i t l e
A
H i g h
B u i l d i n g < / t i t l e
< p a t h
" M 3 . . . . "
< / p a t h
< / s v g
S V G
A C C E S I B I L I T Y S V G
s v g < s v g
" b u i l d i n g T i t l e "
" 0
0
< t i t l e
" b u i l d i n g T i t l e "
A
B u i l d i n g < / t i t l e
< p a t h
" M 3 . . . . "
< / p a t h
< / s v g
< s v g
" b u i l d i n g T i t l e
b u i l d i n g D e s c "
< t i t l e
" b u i l d i n g T i t l e "
A
B u i l d i n g < / t i t l e
< d e s c
" b u i l d i n g D e s c "
A
d r a w i n g
o f
a
b l a c k
a n d
< p a t h
" M 3 . . . . "
< / p a t h
< / s v g
W H A T
T H E
C O D E
L O O K S
L I K E W H A T
T H E
C O D E
L O O K S
L I K E
< s v g
" h t t p : / / w w w . w 3 . o r g / 2 0 0 0 / s v g "
" 0
0
3 5 2 . 1
3 1 8 "
< g
" f r a m e "
. . . < / g
< g
" a r r o w s "
. . . < / g
< g
6 "
. . . < / g
< g
5 "
. . . < / g
< g
4 "
. . . < / g
< g
3 "
. . . < / g
< g
2 "
. . . < / g
< g
1 "
. . . < / g
< g
" t e x t "
. . . < / g
< g
" s l a s h "
. . . < / g
< / s v g
S V G
V I E W B O X S V G
V I E W B O X
< svg
"0 0 200 100"
... </ svg
svg { width : 200px ;} < svg
"0 0 200 100"
... </ svg
@ media (min-width: 768px ) {
svg { width : 400px ;}
}
S V G
V I E W B O X S V G
V I E W B O X
S V G
&
C S S
=
� S V G
&
C S S
=
�
S V G
&
C S S
T R A N S F O R M S
=
� � S V G
&
C S S
T R A N S F O R M S
=
� �
B R O W S E R
B R O W S E R
I N C O N S I S T E N C I E S ST OP ANIMA TION ST OP ANIMA TION Chrome IE & Opera Firefox Safari (zoomed) E D I T
O N H T M L C S S J S R e s u l t
S V G
&
C S S
T R A N S F O R M S S V G
&
C S S
T R A N S F O R M S In all br o w ser s , p x -based origins ar e measur ed diff er ently f or S V G elements IE and Oper a don't honor C SS tr ansf orms at all on S V G elements Z ooming in Saf ari br eak s the s ync be t w een %- based and p x -based origins css-trick s . com/ s v g-animation- on- css-tr ansf orms/
2
S I M P L E
O P T I O N S 2
S I M P L E
O P T I O N S Use an S V G animation libr ar y lik e GS AP Split into se v er al S V Gs to animate with C SS
S P L I T T I N G
S V G S S P L I T T I N G
S V G S < div
"drawing"
< svg
"drawing__svg"
"0 0 404.7 398.9"
< g
"building-6"
.. </ g
< g
"building-5"
.. </ g
< g
"building-4"
.. </ g
...
</ svg
</ div
const svgEl = document .querySelector( '.drawing__svg' );
const wrapper = svgEl.parentElement;
const svgEl = document .querySelector( '.drawing__svg' );
const wrapper = svgEl.parentElement;
while (svgEl.firstElementChild) {
const newSVG = svgEl.cloneNode();
const childNode = svgEl.firstElementChild;
newSVG.appendChild(childNode);
wrapper.appendChild(newSVG);
}
const svgEl = document .querySelector( '.drawing__svg' );
const wrapper = svgEl.parentElement;
while (svgEl.firstElementChild) {
const newSVG = svgEl.cloneNode();
const childNode = svgEl.firstElementChild;
newSVG.appendChild(childNode);
newSVG.classList.add(
drawing-- ${childNode.getAttribute( 'data-name' )}
);
wrapper.appendChild(newSVG);
}
S P L I T T E D
S V G S P L I T T E D
S V G < d i v
" d r a w i n g "
< s v g
" d r a w i n g _ _ s v g
f r a m e "
" 0
0
4 0 4 . 7
3 9 8 . 9 "
< s v g
" d r a w i n g _ _ s v g
a r r o w s "
" 0
0
4 0 4 . 7
3 9 8 . 9 "
< s v g
" d r a w i n g _ _ s v g
1 "
" 0
0
4 0 4 . 7
3 9
< s v g
" d r a w i n g _ _ s v g
2 "
" 0
0
4 0 4 . 7
3 9
< s v g
" d r a w i n g _ _ s v g
3 "
" 0
0
4 0 4 . 7
3 9
< s v g
" d r a w i n g _ _ s v g
4 "
" 0
0
4 0 4 . 7
3 9
. . .
< / d i v
U S I N G
C S S
V A R I A B L E S
F O R U S I N G
C S S
V A R I A B L E S
F O R A N I M A T I O N A N I M A T I O N
C S S
V A R I A B L E S
I N
C S S C S S
V A R I A B L E S
I N
C S S G L O B A L G L O B A L L O C A L L O C A L U S A G E U S A G E : r o o t
{
p r i m a r y :
t e a l ;
}
b u t t o n
{
p r i m a r y :
d e e p p i n k ;
}
b u t t o n
{
c o l o r :
p r i m a r y ) ;
/ /
d e e p p i n k
}
C S S
V A R I A B L E S
I N
J S C S S
V A R I A B L E S
I N
J S c o n s t
e l e m e n t
=
d o c u m e n t . q u e r y S e l e c t o r ( ' . f o o ' ) ;
e l e m e n t . s t y l e
c o l o r ' ,
' o r a n g e ' ) ;
e l e m e n t . s t y l e
c o l o r ' ) ;
/ /
=
' o r a n g e '
e l e m e n t . s t y l e
c o l o r ' ) ;
W H Y
U S E
V A R I A B L E S
F O R
A N I M A T I O N ? W H Y
U S E
V A R I A B L E S
F O R
A N I M A T I O N ? easily debuggable no e x cessiv e DOM manipulation DOM node independent locally adap table T r ansf orm: Individual P r oper ties
C S S
V A R I A B L E S
S U P P O R T C S S
V A R I A B L E S
S U P P O R T
O F F
T O
A N I M A T I O N
C L I F F S O F F
T O
A N I M A T I O N
C L I F F S
L E T ' S
A N I M A T E L E T ' S
A N I M A T E 1 . Add mousemo v e e v ent
A D D
M O U S E M O V E
E V E N T A D D
M O U S E M O V E
E V E N T c o n s t
{
c l i e n t W i d t h ,
c l i e n t H e i g h t
}
=
d o c u m e n t . d o c u m e n t E l e m e n t ;
d o c u m e n t . a d d E v e n t L i s t e n e r ( ' m o u s e m o v e ' ,
( e )
=
{
/ /
d o
s o m e t h i n g
w i t h
e . c l i e n t X
a n d
e . c l i e n t Y
c o n s t
x
=
e . c l i e n t X ;
c o n s t
y
=
e . c l i e n t Y ;
} ) ;
c o n s t
{
c l i e n t W i d t h ,
c l i e n t H e i g h t
}
=
d o c u m e n t . d o c u m e n t E l e m e n t ;
d o c u m e n t . a d d E v e n t L i s t e n e r ( ' m o u s e m o v e ' ,
( e )
=
{
c o n s t
x
=
e . c l i e n t X
/
c l i e n t W i d t h ;
c o n s t
y
=
e . c l i e n t Y
/
c l i e n t H e i g h t ;
} ) ;
x: 0 x: 1 y: 0 y: 1
c o n s t
{
c l i e n t W i d t h ,
c l i e n t H e i g h t
}
=
d o c u m e n t . d o c u m e n t E l e m e n t ;
d o c u m e n t . a d d E v e n t L i s t e n e r ( ' m o u s e m o v e ' ,
( e )
=
{
c o n s t
x
=
( e . c l i e n t X
/
c l i e n t W i d t h
0 . 5 )
2 ;
c o n s t
y
=
( e . c l i e n t Y
/
c l i e n t H e i g h t
0 . 5 )
2 ;
} ) ;
x: -1 x: 1 y: -1 y: 1
A D D
M O U S E M O V E
E V E N T
A D D
M O U S E M O V E
E V E N T
✔ ✔ c o n s t
{
c l i e n t W i d t h ,
c l i e n t H e i g h t
}
=
d o c u m e n t . d o c u m e n t E l e m e n t ;
c o n s t
w r a p p e r
=
d o c u m e n t . q u e r y S e l e c t o r ( ' . d r a w i n g ' ) ;
d o c u m e n t . a d d E v e n t L i s t e n e r ( ' m o u s e m o v e ' ,
( e )
=
{
c o n s t
x
=
( e . c l i e n t X
/
c l i e n t W i d t h
0 . 5 )
2 ;
c o n s t
y
=
( e . c l i e n t Y
/
c l i e n t H e i g h t
0 . 5 )
2 ;
/ /
s e t
t h e
C S S
V a r i a b l e s
x ' ,
x
) ;
/ /
1
t o
1
y ' ,
y
) ;
/ /
1
t o
1
} ) ;
L E T ' S
A D D
I T
T O G E T H E R L E T ' S
A D D
I T
T O G E T H E R 1 . Add mousemo v e e v ent ✔ 2 . Apply C SS T r ansf orms
A P P L Y
C S S
T R A N S F O R M S A P P L Y
C S S
T R A N S F O R M S S E T
I N
J S S E T
I N
J S S E T
I N
C S S
W I T H
C A L C ( ) S E T
I N
C S S
W I T H
C A L C ( ) wrapper.style.setProperty( '--x' , x ); // -1 to 1
wrapper.style.setProperty( '--y' , y ); // -1 to 1
.drawing--building-1 {
// transform: translate('x-Axis','y-Axis');
transform : translate( 20px , 20px );
}
.drawing--building-1 {
transform : translate (calc(var(--x) * 20px ), calc (var(--y) * 20px ));
}
C S S
T R A N S F O R M S
W I T H
S A S S
M A P S
=
� C S S
T R A N S F O R M S
W I T H
S A S S
M A P S
=
� $svgItems : (building- 1 : 18px , building- 2 : 14px , building- 3 : 10px ,
building- 4 : 8px , building- 5 : 4px , building- 6 : 2px ,
arrow-left: 6px , arrow-right: 6px );
@ each
$key , $value in $svgItems {
.drawing-- #{ $key } {
transform :
translate(calc(var(--x) * #{
$value }), calc(var(--y) * #{ $value }));
}
}
.drawing--building-1 {
transform : translate (calc(var(--x) * 18px ), calc (var(--y) * 18px ));
}
L E T ' S
A D D
I T
T O G E T H E R L E T ' S
A D D
I T
T O G E T H E R 1 . Add mousemo v e e v ent ✔ 2 . Apply C SS T r ansf orms ✔ 3 . Add r eques tAnimationF r ame
A D D
R E Q U E S T A N I M A T I O N F R A M E A D D
R E Q U E S T A N I M A T I O N F R A M E a f u n c t io n
t h at
t h e
b r o w s e r
can
o p t im iz e
it ,
s o
an im at io n s
w ill b e s m o o t h e r an imat io n s
in
in ac t i v e
t ab s
w ill s t o p ,
allo w in g t h e
C PU
t o
ch ill m o r e
b at t e r y -f r ie n d ly n o t
n e ce s s ar y
if
y o u ' r e
u s in g t h e
W e b
A n im at io n s
A p i u s e
can ce lA n imat io n F r am e ( )
t o
can ce l it
A D D
R E Q U E S T A N I M A T I O N F R A M E A D D
R E Q U E S T A N I M A T I O N F R A M E function
repeatOften ( ) {
// Animate something
// call requestAnimationFrame to keep animating
requestAnimationFrame(repeatOften);
}
requestAnimationFrame(repeatOften);
A D D
R E Q U E S T A N I M A T I O N F R A M E
A D D
R E Q U E S T A N I M A T I O N F R A M E
✔ ✔ let x;
document .addEventListener( 'mousemove' , (e) => {
x = (e.clientX / clientWidth - 0.5 ) * 2 ;
// call requestAnimationFrame with update function
requestAnimationFrame(update);
});
function
update ( ) {
// animate changes
wrapper.style.setProperty( '--x' , x );
wrapper.style.setProperty( '--y' , y );
}
L E T ' S
A D D
I T
T O G E T H E R L E T ' S
A D D
I T
T O G E T H E R 1 . Add mousemo v e e v ent ✔ 2 . Apply C SS T r ansf orms ✔ 3 . Add r eques tAnimationF r ame ✔ 4 . Add linear interpolation (lerp )
A D D I N G
L I N E A R
I N T E R P O L A T I O N A D D I N G
L I N E A R
I N T E R P O L A T I O N a w ay to mak e y our animation smoo ther ins tead o f jumping fr om A to B , LERP will go only a fr ac tion o f the w ay on e v er y fr ame combats linear or jagged mo v ement C odepen Ar ticle
A D D I N G
L I N E A R
I N T E R P O L A T I O N A D D I N G
L I N E A R
I N T E R P O L A T I O N function
lerp ( start, end ) {
const dx = end.x - start.x;
const dy = end.y - start.y;
return {
x : start.x + dx * 0.1 ,
y : start.y + dy * 0.1 ,
};
}
W I T H O U T
L E R P W I T H O U T
L E R P W I T H
L E R P W I T H
L E R P
L E T ' S
A D D
I T
T O G E T H E R L E T ' S
A D D
I T
T O G E T H E R 1 . Add mousemo v e e v ent ✔ 2 . Apply C SS T r ansf orms ✔ 3 . Add r eques tAnimationF r ame ✔ 4 . Add linear interpolation ✔ 5 . Add mor e C SS things!
A D D
A D D
M O R E
C S S
T H I N G S ! M O R E
C S S
T H I N G S ! C SS Ho v er Animations C SS S t yling lik e color s Click Lis tener s on Elements R x Obser v ables & Scheduler s to k eep animating once the mouse goes outside the windo w
l i � � . � � n e . � � �
K E E P
H A V I N G
F U N
W I T H
T H E
W E B K E E P
H A V I N G
F U N
W I T H
T H E
W E B A S
A
M E D I U M A S
A
M E D I U M
T H A N K
Y O U ! T H A N K
Y O U !
lis ilin h ar t . in f o @ lis i_ lin h ar t in s t agr am . co m / lis i. lin e . ar t
For decades drawing has allowed us to tell captivating stories with only a simple medium like pen and paper. But why stop at pen and paper, when we have an amazing medium like the web, that allows us to turn handdrawn sketches into beautiful interactive and animated SVG illustrations. This talk will explain how art and coding have many similarities and why creating a clear cut between developers and designers can be limiting. We will explore what SVG is and how we can utilise it to turn our illustrations into code. Finally we’ll sprinkle some animation techniques on top to create a delightful interactive illustration in the browser.
The following resources were mentioned during the presentation or are useful additional information.
Codepen Examples in the presentation
Detailed article on how to provide accessible svgs
Article on Cross Browser Issues with SVG
Article on how to create linear interpolation
My illustrations on Instagram
Here’s what was said about this presentation on social media.
A note for awesome @lisi_linhart's talk about animated drawing #piterCSS art + css + svg magic pic.twitter.com/9RFoRt003J
— Артём Пендюрин (@ErBlack) June 9, 2018
Sometimes SVG title is not enough and you might want to use id and aria-labelledby attribute to get a title that will be read out by a screen reader via @lisi_linhart at #pitercss pic.twitter.com/d6qunxf15C
— Anna Migas (@szynszyliszys) June 9, 2018
Now @lisi_linhart showing her process towards illustration. That’s inspiring and encouraging! #piterCSS pic.twitter.com/eAHNrw08m2
— Oliver Schöndorfer (@glyphe) June 9, 2018
Next up at #pitercss is @lisi_linhart. Can’t wait to see what sketch Lisi is going to present for St Petersburg (there was a mermaid for Warsaw!) pic.twitter.com/b0JTsEsagm
— Anna Migas (@szynszyliszys) June 9, 2018
Thank you @Una and @lisi_linhart for the great talks on the second @pitercss_conf day. I plan to start learning more about SVG animation, illustrations and how to interact with it in CSS :) #pitercss
— Nikita Prokopenko (@nik_prokopenko) June 9, 2018
@lisi_linhart is making her magic at @pitercss_conf #pitercss #pitercss_conf #sketchnotes pic.twitter.com/UpoWajLgwd
— Sergei Kriger (@_sergeikriger) June 9, 2018
“Keep having fun with the web as a medium for trying out new things!“ great take away! Thank you, @lisi_linhart 👏 #piterCSS pic.twitter.com/SZJ7MgIXZR
— Oliver Schöndorfer (@glyphe) June 9, 2018
#pitercss #pitercss_conf amazing talk about SVG animations by @lisi_linhart pic.twitter.com/30P5ZwFZC9
— Leonid (@lkalneus) June 9, 2018
Pen & paper 👉 SVG animations? Why not! 🌈 Everything is possible on the Web with art and coding acting together. Illustration adventure for developers 👩🔧 and designers 👨🎨 with @lisi_linhart from Salzburg 🇦🇹 at https://t.co/tFya4ji2HD pic.twitter.com/3KrhImoPr4
— pitercss_conf (@pitercss_conf) April 24, 2018
I really enjoyed @lisi_linhart’s SVG animation presentation at @fronttrends, she went through her process from start to finish drawing to animating with JavaScript interaction connected to CSS variables, using calc and sass maps, and finally, LERP pic.twitter.com/xy1tdxsuYi
— Sarah Drasner (@sarah_edo) May 25, 2018
@lisi_linhart - great use of css variables, amazing way to do animations performant! #fronttrends
— Kacper Kula (@kulak_at) May 25, 2018
@lisi_linhart describes drawing process in the terms of software development - great compassion :) #fronttrends
— Kacper Kula (@kulak_at) May 25, 2018
Art + code is something what we love! Lisi Linhart @lisi_linhart is already on the stage telling how she combines drawings, SVG and animations 👩🏻🎨💻 #svg #svganimations #fronttrends #ft2018 #web pic.twitter.com/GIskNouEO8
— Front-Trends 2018 (@fronttrends) May 25, 2018
This talk has been my fav @fronttrends. Such an a clear & actionable way for me to start transforming my doodles to school animations 😍✨💗 https://t.co/mIBWvLF2uQ
— Stephanie Nemeth (@stephaniecodes) May 25, 2018