Creative Typography with SVG



Creative Typography with SVG

0 1


talk_svg-typography

Slide deck for talk, Creative Typography with SVG, built with reveal.js and reveal-liveCoding

On Github brenna / talk_svg-typography

Creative Typography with SVG

Brenna O'Brien / @brnnbrn

front-end engineer /  

#SVGType

These 8 Weird SVG Tricks Will Totally blow your mind

You might also learn a lot about SVG

SVG101

 =

  <svg viewBox="0 0 100 100">
    <path fill="#BE1637" stroke="#fff"
      d="M96.333,18.385c-2.396-6.01-7.205-11.064-13.857-14.194
      C76.595,1.423,70.26,1.09,64.501,2.782
      C58.743,4.472,53.566,9.081,50,14.408
      c-3.565-5.327-8.743-9.936-14.5-11.626
      C29.743,1.09,23.406,1.423,17.526,4.191
      c-6.652,3.128-11.46,8.184-13.858,14.194
      c-2.396,6.01-2.407,12.987,0.614,19.927
      C10.743,53.154,49.795,87.993,50,88.588
      c0.205-0.595,39.258-35.434,45.718-50.276
      C98.74,31.371,98.729,24.395,96.333,18.385z" />
  </svg>
  

V.R.E.A.M

viewBox Rules Everything Around Me

resolution independent

easy to manipulate with CSS & JS

  .heart:hover {
    fill: #fff;;
  }
      

great for icons and logos

Let's talk about <text> baby

<text> is accessible

<text>101

CSS Dev Conf
  <svg viewBox="0 0 600 100">
    <text y="1em" fill="tomato" font-size="80">CSS Dev Conf</text>
  </svg>
  

<text>101

  • watch out for y=0 default

  • no automatic line breaks

* just like the svg we're used to but instead of a path or a shape, we're rendering text * fill and stroke as you would expect * inherits font-family and sizing but turns px into SVG units * positioning with x & y, as you would expect, but watch out for y
1

typo- graphic lock-up

lack of line breaking can be to your advantage when you want to control lettering precisely
http://codepen.io/brenna/full/raOBaw/

Let's talk about...

  • <tspan>

  • textLength

  • lengthAdjust

<tspan>

  • similar to HTML <span>

  • absolute positioning with x & y

  • relative positioning with dx & dy

typographic lock-up

What islove
  <svg viewBox="0 0 200 50">
    <text font-size="20">
      <tspan textLength="80" x="0" y="1em"
        lengthAdjust="spacing">What is</tspan>
      <tspan textLength="80" x="0" dy="1em"
        lengthAdjust="spacingAndGlyphs">love</tspan>
    </text>
  </svg>
  

typographic lock-up

What islove
  <svg viewBox="0 0 200 50">
    <text font-size="20">
      <tspan textLength="80" x="0" y="1em"
        font-size="20" >What is</tspan>
      <tspan textLength="80" x="0" dy="0.9em"
        font-size="30" font-weight="bold" >love</tspan>
    </text>
  </svg>
  

CSS can set most attributes

What islove
  .love {
    fill: #FF6666;
  }
     
  <svg viewBox="0 0 200 50">
    <text font-size="20">
      <tspan textLength="80" x="0" y="1em"
        font-size="20" >What is</tspan>
      <tspan class="love" textLength="80" x="0" dy="0.9em"
        font-size="30" font-weight="bold" >love</tspan>
    </text>
  </svg>
    

RESPONSIVE TEXT!

responsive SVG

viewBox + flexible container

Fitter, Happier, Text
2

curved text

Let's talk about...

  • <textPath>

  • alignment-baseline

  • <defs>

<textPath>

set text along an arbitrary path

curved text with <textPath>

Are You Afraid
  <svg viewBox="0 50 500 150">
    <path id="arc" stroke="red" d="M82.372,165.969 c44.126-35.084,60.236-50.782,150.325-50.782s131.802,28.198,158.194,62.77" />
    <text fill="#5D509D" width="500">
      <textPath alignment-baseline="middle" xlink:href="#arc" font-size="44"  dy="100">
        Are You Afraid
      </textPath>
    </text>
  </svg>
  

<defs>

  • where you define re-usable SVG components

  • a trusty steed as we combine SVG techniques

curved text with <textPath>

Are You Afraid of theDark?
  <svg class="are-you-afraid" viewBox="0 0 475 300">
    <defs>
     <path id="arc" d="M82.372,165.969 c44.126-35.084,60.236-50.782,150.325-50.782s131.802,28.198,158.194,62.77"></path>
    </defs>
    <text fill="#5D509D" width="500">
      <textPath xlink:href="#arc" font-size="44"  dy="100">
        Are You Afraid
      </textPath>
      <tspan dy="10" x="50%" text-anchor="middle" font-size="44">of the</tspan>
      <tspan dy="1em" x="50%" text-anchor="middle" font-size="75">Dark?</tspan>
    </text>
  </svg>
  
3

text filled with gradients

smell ya later

-webkit-background-clip: text;

Let's talk about ...

  • <linearGradient>

  • <radialGradient>

  • gradientUnits

<linearGradient>

  <linearGradient id="fire" x1="0" y1="0" x2="100%" y2="100%">
    <stop stop-color="hotpink" offset="0%"/>
    <stop stop-color="goldenrod" offset="100%"/>
  </linearGradient>
  

<radialGradient>

  <radialGradient id="ring-of-fire" cx="50%" cy="50%" r="40"
    gradientUnits="userSpaceOnUse">
    <stop stop-color="hotpink" offset="0%"/>
    <stop stop-color="goldenrod" offset="100%"/>
  </radialGradient>
  

gradientUnits

  • userSpaceOnUse = absolute

  • objectBoundingBox = object relative

see also:clipPathUnits, maskUnits, patternUnits

Clipping in CSS and SVG: The clipPathUnits attribute

gradient filled text

Wow!
  <svg viewBox="0 0 300 60">
    <defs>
      <linearGradient id="fire">
        <stop stop-color="hotpink" offset="0%"/>
        <stop stop-color="goldenrod" offset="100%"/>
      </linearGradient>
    </defs>
    <text dy="1em" fill="url(#fire)" font-size="50">Wow!</text>
  </svg>
  
http://codepen.io/brenna/full/mybQVx/

only other way i've seen this done with live text is with -webkit-background-clip: text; and that's only webkit!

4

text filled with images

Let's talk about...

  • <image>

  • <pattern>

  • <clipPath>

<image> vs <img>

  
  <svg viewBox="0 0 200 100" width="600px">
    <!-- default value is 'meet', not 'slice' -->
    <image preserveAspectRatio="xMidYMid slice"
      xlink:href="img/moon.jpg" width="200" height="100" />
  </svg>
  

<pattern>

  • turns any SVG element into a fill

  • most fun with <image>

image fills with <pattern>

moon
  <svg viewBox="0 0 200 60">
    <defs>
      <pattern id="moon" width="200" height="60"
        patternUnits="userSpaceOnUse">
        <image href="img/moon.jpg" width="200" height="60" preserveAspectRatio="xMidYMid slice"></image>
      </pattern>
    </defs>
    <text fill="url(#moon)" y="1em">moon</text>
  </svg>
  

Image fill hot tips

  • <image> needs a width and height

  • preserveAspectRatio to fill viewBox

  • patternUnits="userSpaceOnUse" to size image viewBox

A Look At preserveAspectRatio in SVG

<clipPath>

restricts the visible area of another SVG element

image fills with <clipPath>

mars
  <svg viewBox="0 0 200 60">
    <defs>
      <clipPath id="mars-text">
        <text y="1em">mars</text>
      
    </clipPath></defs>
    <image clip-path="url(#mars-text)" xlink:href="img/mars2.jpeg"
    width="200" height="60" preserveAspectRatio="xMidYMax slice"/>
  </svg>
  

Why not text filled with gifs?

http://codepen.io/brenna/full/vEBQra/
5

knockout text

http://codepen.io/brenna/full/XmeRqb/

Let's talk about...

  • <mask>

  • <rect>

  • text-anchor

<mask>

  • like <clipPath> but with more control

  • black fill = opaque maskwhite fill = transparent mask

knockout text with <mask>

Buy 2 hams $20
    <svg viewBox="0 0 200 25">
      <rect fill="#fff" x="0" y="0" width="200" height="50"></rect>
      <text y="20" fill="#000" text-anchor="middle" x="50%" font-size="20">
         Buy 2 hams $20
      </text>
    </svg>
  

knockout text with <mask>

Buy 2 hams $20
  <svg viewBox="0 0 200 25">
    <rect fill="#000" fill-opacity=".75" mask="url(#ham-text)"
    x="0" y="0" width="200" height="50" />
    <mask id="ham-text">
      <rect fill="#fff" x="0" y="0" width="200" height="50"></rect>
      <text y="20" fill="#000" text-anchor="middle" x="50%" font-size="20">
         Buy 2 hams $20
      </text>
    </mask>
  </svg>
  
* go over TEXT-ANCHOR HERE~~~ * mask should be in a defs but saving space
6

self typing text

Let's talk about...

<animate>

<animate>

animate (almost) any attribute, from within the SVG

Animatable SVG Attributes

<animate>

  <svg viewBox="0 0 800 100">
    <line stroke="goldenrod" stroke-width="10"
      x1="0" y1="50" x2="0" y2="50">
      <animate attributeName="x2"
      from="0" to="800"
      dur="2s" repeatCount="indefinite"/>
    </line>
  </svg>
  

self-typing text with <textPath> and <animate>

  <svg viewBox="0 0 800 100">
    <defs>
      <path id="animatedLine">
        <animate attributeName="d" from="m0,50 h0" to="m0,50 h800" dur="2s" repeatCount="indefinite"/>
      </path>
    </defs>
    <text dy="25" font-size="80">
      <textPath xlink:href="#animatedLine">
        hack the planet</textPath>
    </text>
  </svg>
  

self-typing text with <textPath> and <animate>

  <svg viewBox="0 0 400 100">
    <defs>
      <path id="animatedLine">
        <animate attributeName="d" from="m0,50 h0" to="m0,50 h400" dur="1s" repeatCount="indefinite"/>
      </path>
    </defs>
    <text dy="25" font-size="80" fill="#fff" x="50%" text-anchor="middle">
      <textPath xlink:href="#animatedLine">
        loading...</textPath>
    </text>
  </svg>
  

Q: Why not just <animate> with CSS & JS?

A:

7

ani- morphing text

<animate> can morph glyphs!

http://codepen.io/NinjaCoffee/full/JoJZrB/

converting text to paths

morphing text paths

say yes
  <svg viewBox="0 0 100 100">
    <path fill="#BE1637" d="M10.822,5.429  h28.927  l28.802,57.851  l0-57.45    h20.748  l0,85.189    l-28.927,0  l-29.78-58.217  l0.489,58.217  l-20.86,0z">
      <animate class="yes" attributeName="d" dur="1s"
        begin="indefinite" fill="freeze"
        to="M7.27,5.416 h26.127  l16.5,34.2 l16.5-34.2  h26.1 l-31.1,53.1  l0,32.107 l-11.35,0 l-11.35,0 l0-31.9z"/>
      <animate attributeName="fill" dur="1s"
        begin="indefinite" fill="freeze"
        to="goldenrod"/>
    </path>
  </svg>
  

morphin' hot tips

  • paths must have the exact same number and typeof anchor points *

    * or use GreenSock MorphSVG Plugin

  • fill="freeze" to hold end state

  • duration="indefinite" and .beginElement()to trigger with JS

How SVG Shape Morphing Works

paths can be made accessible

<title>, <desc> and ARIA

Tips for Creating Accessible SVG

8

self drawing text

Let's talk about...

  • stroke-dasharray

  • stroke-dashoffset

self-drawing <text>

  <svg viewBox="0 0 200 80" stroke-width="1">
    <text stroke-dasharray="700 700" stroke-dashoffset="700"
      fill="none" stroke="#fff" dy="1em" font-size="70">
      cool
      <animate dur="2s" repeatCount="indefinite"
        attributeName="stroke-dashoffset"
        values="700;0" />
    <text>
    </svg>
   

self-drawing <path>

longstroke-dasharray

+

animatedstroke-dashoffset

How SVG Line Animation Works

self-drawing <path>

  <svg viewBox="0 0 100 80" stroke-width="1">
    <path stroke-dasharray="200 200" stroke-dashoffset="200" fill="none" stroke="#fff"
      d="M26.325,31.255c0.623-2.608-1.089-8.703-1.089-11.383c0-2.863-0.255-5.876,0.028-8.725c1.533,3.676,4.99,6.807,7.303,9.998c1.781,2.457,3.374,4.643,4.075,7.623c2.356-0.13,4.568-1.057,7.044-0.652c1.929,0.315,4.543,1.057,6.155,2.174c0.737-1.115,1.155-2.605,1.626-3.831c1.263-3.285,2.666-6.38,4.499-9.385c0.839-1.375,1.635-2.99,2.583-4.26c0.104,5.004,1.526,9.846,1.548,14.827c0.004,0.896-0.126,1.903,0,2.79c0.134,0.947,0.079,0.708,0.49,1.458c0.772,1.411,2.459,2.691,3.478,3.954c1.379,1.711,2.333,3.192,2.921,5.313c0.97,3.497,1.53,8.9,0.375,12.37c-1.624,4.879-4.688,7.727-8.488,10.109C51.7,68.133,47.63,68.824,39.28,65.737c-6.503-2.404-12.196-6.026-15.273-12.438c-1.965-4.096-2.422-9.251-2.118-13.737C22.035,37.402,23.517,31.44,26.325,31.255">
      <animate dur="2s" repeatCount="indefinite"
        attributeName="stroke-dashoffset"
        values="200;0" />
    </path>
    </svg>
   

self-drawing text <path>

  <svg viewBox="0 0 514 154" fill="none" stroke="#fff" stroke-width="3">
    <path stroke-dashoffset="170" stroke-dasharray="170 170" d="M85.829,53.281C79.831,43.719,68.859,28.49,55,31.392c-14.211,2.976-24.931,16.44-22.009,31.469C36.657,81.72,51.87,88.245,65.286,98.974c9.447,7.554,20.266,14.968,16.728,27.692">
      <animate dur="2.5s" repeatCount="indefinite"
        attributeName="stroke-dashoffset"
        values="170;0;0;0;0;0"/>
    </path>
    <path stroke-dashoffset="170" stroke-dasharray="170 170" d="M86.29,51.759C85.829,40,101.451,31.417,108.667,31.392c18.838-0.064,25.381,14.722,25.721,26.399c0.577,19.855-26.349,34.853-39.721,45.542c-8.141,6.507-11.573,10.448-16.509,19.325">
      <animate dur="2.5s" repeatCount="indefinite"
        attributeName="stroke-dashoffset"
        values="170;170;0;0;0;0" />
    </path>
    <path stroke-dashoffset="720" stroke-dasharray="720 720" d="M134.822,121c13.331-22.482,78.647-107.117,110.639-96.537c26.659,9.257-54.654,55.542-65.318,60.832c78.647-30.417,29.326,59.507-9.331,42.316c-15.995-6.61,17.329-9.255,22.662-9.255c31.993,3.965,35.99,6.609,66.65-7.937c22.661-10.577,11.997-2.645,30.659,5.291c22.66,7.935,41.322-6.61,62.65-3.965c11.996,1.32,18.662,9.255,33.326,10.575c14.663,1.324,27.991-6.61,42.653-10.575c0,1.32,0,3.965,0,5.288c9.334-2.646,18.663-5.288,27.992-10.58c2.667,7.934,6.668,3.965,14.665,3.965">
      <animate dur="2.5s"repeatCount="indefinite"
      attributeName="stroke-dashoffset"
      values="720;720;720;360;0;0" />
    </path>
  </svg>
  

<text>

<tspan>

<textPath>

<defs>

<linearGradient>

<radialGradient>

<stop>

<image>

<pattern>

<clipPath>

<mask>

<rect>

<animate>

<line>

<path>

d

fill

stroke

x, y

dx, dy

textLength

lengthAdjust

font-size

font-weight

xlink:href

alignment-baseline

x1, x2

y1, y2

cx, cy, r

stop-color

offset

gradientUnits

clipPathUnits

maskUnits

patternUnits

preserveAspectRatio

text-anchor

fill-opacity

attributeName

to, from

values

begin, dur

repeatCount

stroke-dasharray

stroke-dashoffset

<a>

<altGlyph>

<altGlyphDef>

<altGlyphItem>

<animate>

<animateColor>

<animateMotion>

<animateTransform>

<circle>

<clipPath>

<color-profile>

<cursor>

<defs>

<desc>

<ellipse>

<feBlend>

<feColorMatrix>

<feComponentTransfer>

<feComposite>

<feConvolveMatrix>

<feDiffuseLighting>

<feDisplacementMap>

<feDistantLight>

<feFlood>

<feFuncA>

<feFuncB>

<feFuncG>

<feFuncR>

<feGaussianBlur>

<feImage>

<feMerge>

<feMergeNode>

<feMorphology>

<feOffset>

<fePointLight>

<feSpecularLighting>

<feSpotLight>

<feTile>

<feTurbulence>

<filter>

<font>

<font-face>

<font-face-format>

<font-face-name>

<font-face-src>

<font-face-uri>

<foreignObject>

<g>

<glyph>

<glyphRef>

<hkern>

<image>

<line>

<linearGradient>

<marker>

<mask>

<metadata>

<missing-glyph>

<mpath>

<path>

<pattern>

<polygon>

<polyline>

<radialGradient>

<rect>

<script>

<set>

<stop>

<style>

<svg>

<switch>

<symbol>

<text>

<textPath>

<title>

<tref>

<tspan>

<use>

<view>

<vkern>

MDN: SVG element reference

accent-height

accumulate

additive

alignment-baseline

allowReorder

alphabetic

amplitude

arabic-form

ascent

attributeName

attributeType

autoReverse

azimuth

baseFrequency

baseline-shift

baseProfile

bbox

begin

bias

by

calcMode

cap-height

class

clip

clipPathUnits

clip-path

clip-rule

color

color-interpolation

color-interpolation-filters

color-profile

color-rendering

contentScriptType

contentStyleType

cursor

cx

cy

d

decelerate

descent

diffuseConstant

direction

display

divisor

dominant-baseline

dur

dx

dy

edgeMode

elevation

enable-background

end

exponent

externalResourcesRequired

fill

fill-opacity

fill-rule

filter

filterRes

filterUnits

flood-color

flood-opacity

font-family

font-size

font-size-adjust

font-stretch

font-style

font-variant

font-weight

format

from

fx

fy

g1

g2

glyph-name

glyph-orientation-horizontal

glyph-orientation-vertical

glyphRef

gradientTransform

gradientUnits

hanging

height

horiz-adv-x

horiz-origin-x

id

ideographic

image-rendering

in

in2

intercept

k

k1

k2

k3

k4

kernelMatrix

kernelUnitLength

kerning

keyPoints

keySplines

keyTimes

lang

lengthAdjust

letter-spacing

lighting-color

limitingConeAngle

local

marker-end

marker-mid

marker-start

markerHeight

markerUnits

markerWidth

mask

maskContentUnits

maskUnits

mathematical

max

media

method

min

mode

name

numOctaves

offset

onabort

onactivate

onbegin

onclick

onend

onerror

onfocusin

onfocusout

onload

onmousedown

onmousemove

onmouseout

onmouseover

onmouseup

onrepeat

onresize

onscroll

onunload

onzoom

opacity

operator

order

orient

orientation

origin

overflow

overline-position

overline-thickness

panose-1

paint-order

path

pathLength

patternContentUnits

patternTransform

patternUnits

pointer-events

points

pointsAtX

pointsAtY

pointsAtZ

preserveAlpha

preserveAspectRatio

primitiveUnits

r

radius

refX

refY

rendering-intent

repeatCount

repeatDur

requiredExtensions

requiredFeatures

restart

result

rotate

rx

ry

scale

seed

shape-rendering

slope

spacing

specularConstant

specularExponent

speed

spreadMethod

startOffset

stdDeviation

stemh

stemv

stitchTiles

stop-color

stop-opacity

strikethrough-position

strikethrough-thickness

string

stroke

stroke-dasharray

stroke-dashoffset

stroke-linecap

stroke-linejoin

stroke-miterlimit

stroke-opacity

stroke-width

style

surfaceScale

systemLanguage

tableValues

target

targetX

targetY

text-anchor

text-decoration

text-rendering

textLength

to

transform

type

u1

u2

underline-position

underline-thickness

unicode

unicode-bidi

unicode-range

units-per-em

v-alphabetic

v-hanging

v-ideographic

v-mathematical

values

version

vert-adv-y

vert-origin-x

vert-origin-y

viewBox

viewTarget

visibility

width

widths

word-spacing

writing-mode

x

x-height

x1

x2

xChannelSelector

xlink:actuate

xlink:arcrole

xlink:href

xlink:role

xlink:show

xlink:title

xlink:type

xml:base

xml:lang

xml:space

y

y1

y2

yChannelSelector

z

zoomAndPan

MDN: SVG attribute reference

go on a code adventure

SVG on MDN

jenkov.com SVG Tutorials

You'll probably learn something useful

thank you!

 

#SVGType 5 wow!

(504) 229-6828