Color fonts are a real thing. However...
... Support for OpenType SVG fonts in browsers is in active development, with all the caveats that apply to such functionality - see the caniuse site for current details.
This demo does not use color font technology, nor does it attempt to replicate color font functionality. Instead it demonstrates the application of color design and animation to any text on the web page, typically in HTML header elements, through the use of Scrawl-canvas snippet modules.
Scrawl-canvas font snippets
The snippets in this demo allow developers to apply color, distortion and animation effects to HTML header text blocks. Each header element can personalize the snippet effect applied to it using both CSS classes and HTML data- attributes (which take priority), meaning each snippet can create a range of different effects.
Heads up! This technique uses Scrawl-canvas snippet modules, which are experimental. Depending on the header size, and the complexity of the pattern design and animation effect, the technique may lead to heavy computation which can result in excessive power use and slower screen refresh rates.
Note that this demo includes many header examples. The more headers that the snippets get applied to, the longer the initial computation takes, which can lead to a delay to the effects appearing on the page - resulting in an unfortunate FOUT (flash of unstyled text).
Use snippets sparingly!
DOM text and canvas text: These snippets work by matching the font characteristics of the DOM headers and recreating the text in a <canvas> element added inside the header element (progressive enhancement). For accessibility and user experience purposes the DOM text is not removed: users should be able to copy/paste the header text as normal. Users who disable Javascript in their devices should still be able to see the normal, CSS styled header text.
Canvas text functionality is severely limited, compared to DOM text. These snippets attempt to:
- Match the header text font family - including cloud-based web fonts
- Match the positioning, line-height and line breaks of the header text in the canvas (as far as possible)
- Match the font size of the header text, and adapt to CSS media query responsive sizing on a real-time basis (work in progress)
- Respect <b>, <strong>, <i>, <em> and <u> markup within the header text
- Respect some of the CSS styling applied to the header text, such as: text-align, letter-spacing
Accessibility controls and checks include:
- For animated font effects, the snippets will attempt to add a navigable play|pause control button in the top-right corner of the header element
- For users who have set the prefers-reduced-motion: reduced feature on their devices, animated font effects will only play after the user clicks the Play|Pause control
- For users who have set the prefers-color-scheme: dark feature on their devices, the font effect will display using dark-mode colors (if they have been set)
- For users who have set the new prefers-contrast: more feature on their devices, the font effect will not display
Details on how to apply these Scrawl-canvas snippets to DOM elements can be found at the end of this page.
risograph-text-gradient-snippet
This effect is inspired by Risograph printing which uses a limited color palette, stippling colors to create a gradient effect.
The snippet can be customised using the following data- attributes applied using CSS variables, or directly to the HTML header element:
- data-top-color - any CSS color string
- data-bottom-color - any CSS color string
- data-outline-color - any CSS color string
- data-outline-width - (unit % of font size) outline width as a percentage of the font size
- data-random-radius - (0 - 1) the amount of mixing of the top and bottom colors
- data-random-level - (0 - 1) the density of the color mixing
... And for prefers-color-scheme: dark users:
- data-dark-top-color - any CSS color string
- data-dark-bottom-color - any CSS color string
- data-dark-outline-color - any CSS color string
This snippet reacts to the user preference prefers-contrast: more with the following data- attributes:
- data-contrast-color - any CSS color string
- data-dark-contrast-color - any CSS color string
Risograph effect - default values
CSS:
.demo-header {
font-size: 2em;
line-height: 1.15;
border: 0;
margin: 0;
-webkit-hyphens: none;
-ms-hyphens: none;
hyphens: none;
min-height: 1em;
caret-color: rgba(0 0 0 / 1);
background-color: rgba(0 0 0 / 0);
}
@media (min-width: 30em) {
.demo-header {
font-size: 3em;
}
}
@media (min-width: 40em) {
.demo-header {
font-size: 4em;
}
}
@media (min-width: 50em) {
.demo-header {
font-size: 5em;
}
}
@media (prefers-color-scheme: dark) {
.demo-header {
caret-color: rgba(255 255 255 / 1);
}
}
.header-font-sans {
font-family: 'Open Sans', 'Fira Sans', 'Lucida Sans', 'Lucida Sans Unicode', 'Trebuchet MS', 'Liberation Sans', 'Nimbus Sans L', sans-serif;
/*
These font-specific data values can only ever be best-fit approximations
- Especially when used for multiple fonts, like here
*/
--data-y-offset: 0.11;
--data-lineheight-adjuster: 0.875;
--data-underline-position: 0.75;
--data-underline-width: 0.09;
/*
no space after the colon (unless you don't want underlined spaces)
*/
--data-no-underline-glyphs:gjpqy
}
HTML:
<h4
id="header-test-1"
class="demo-header
header-font-sans
risograph-header"
contenteditable="plaintext-only"
>Lorem ipsum dolor <i>sit amet</i>, consectetur <u>adipiscing elit</u> magna aliqua</h4>
Lorem ipsum dolor sit amet, consectetur adipiscing elit magna aliqua
Risograph effect - variant 1
CSS:
.header-font-serif {
font-family: 'Lucida Bright', 'Lucida Fax', Palatino, 'Palatino Linotype', Palladio, 'URW Palladio', serif;
--data-y-offset: 0.1;
--data-lineheight-adjuster: 0.84;
--data-underline-position: 0.67;
--data-underline-width: 0.09;
--data-no-underline-glyphs:gjpqy;
}
.risograph-v1 {
--data-random-radius: 0.15;
--data-outline-width: 0.08;
--data-top-color: red;
--data-bottom-color: black;
--data-outline-color: gold;
--data-dark-top-color: red;
--data-dark-bottom-color: white;
--data-dark-outline-color: gold;
}
.no-bold {
font-weight: normal;
}
HTML:
<h4
id="header-test-2"
class="demo-header
header-font-serif
no-bold
risograph-header
risograph-v1"
contenteditable="plaintext-only"
>Lorem ipsum dolor <i>sit amet</i>, <b>consectetur</b> <u>adipiscing elit</u> magna aliqua</h4>
Lorem ipsum dolor sit amet, consectetur adipiscing elit magna aliqua
Risograph effect - default values with local amendments
CSS:
.header-font-mono {
font-family: 'Fira Mono', 'DejaVu Sans Mono', Menlo, Consolas, 'Liberation Mono', Monaco, 'Lucida Console', monospace;
--data-y-offset: 0.15;
--data-lineheight-adjuster: 0.85;
--data-underline-position: 0.72;
--data-underline-width: 0.08;
--data-no-underline-glyphs:gjpqy;
}
HTML:
<h4
id="header-test-3"
class="demo-header
header-font-mono
no-bold
risograph-header"
contenteditable="plaintext-only"
data-outline-width="0.1"
data-outline-color="darkslateblue"
data-dark-outline-color="lightslateblue"
data-contrast-color="darkred"
data-dark-contrast-color="pink"
>
Lorem ipsum dolor <i>sit amet</i>, <b>consectetur</b> <u>adipiscing elit</u> magna aliqua
</h4>
Lorem ipsum dolor sit amet, consectetur adipiscing elit magna aliqua
worley-text-gradient-snippet
Worley noise is a form of procedural texture which can be generated and used to simulate textures which look (a bit) like stone, water or biological cells.
The snippet can be customised using the following data- attributes applied using CSS variables, or directly to the HTML header element:
- data-base-color - any CSS color string
- data-highlight-color - any CSS color string
- data-noise-sum-function - permitted values include: 'none', 'sine-x', 'sine-y', 'sine', 'modular', 'random'
- data-noise-scale - (+number) a form of zoom level
- data-noise-output - permitted values include: 'X', 'YminusX', 'ZminusX' etc
- data-shadow-color - any CSS color string, for the text shadow
- data-shadow-offset-x - (unit % of font size) percentage of the font size to offset the text shadow horizontally
- data-shadow-offset-y - (unit % of font size) percentage of the font size to offset the text shadow vertically
- data-shadow-blur - (unit % of font size) percentage of the font size to blur the shadow
... And for prefers-color-scheme: dark users:
- data-dark-base-color - any CSS color string
- data-dark-highlight-color - any CSS color string
- data-dark-shadow-color - any CSS color string, for the text shadow
This snippet reacts to the user preference prefers-contrast: more with the following data- attributes:
- data-contrast-color - any CSS color string
- data-dark-contrast-color - any CSS color string
Scrawl-canvas supports several types of noise generation, including Worley noise - see Demo canvas-060.
Worley effect - default
CSS:
.header-font-cursive {
font-family: 'Brush Script MT', 'Brush Script Std', 'Lucida Calligraphy', 'Lucida Handwriting', 'Apple Chancery', cursive;
--data-y-offset: 0.15;
--data-lineheight-adjuster: 0.83;
--data-underline-position: 0.65;
--data-underline-width: 0.08;
--data-no-underline-glyphs:gjpqy
}
HTML:
<h4
id="header-test-4"
class="demo-header
header-font-cursive
no-bold
worley-header"
contenteditable="plaintext-only"
>
Lorem ipsum <b>dolor sit amet</b>, consectetur <u>adipiscing elit</u> magna aliqua
</h4>
Lorem ipsum dolor sit amet, consectetur adipiscing elit magna aliqua
Worley effect - variant 1
CSS:
.justify-center-test {
text-align: center;
}
.worley-v1 {
--data-highlight-color: red;
--data-shadow-color: slategray;
--data-dark-highlight-color: red;
--data-dark-shadow-color: lightslategray;
--data-shadow-offset-x: 0.05;
--data-shadow-offset-y: 0.05;
--data-shadow-blur: 0.03;
--data-noise-scale: 40;
--data-noise-sum-function: none;
}
HTML:
<h4
id="header-test-5"
class="demo-header
header-font-sans
justify-center-test
worley-header
worley-v1"
contenteditable="plaintext-only"
>
Lorem ipsum dolor <i>sit amet</i>, consectetur <u>adipiscing elit</u> magna aliqua
</h4>
Scrawl-canvas Phrase entity text can be justified within the Phrase's width; these text snippets will pick up and apply the header block text-align property.
Lorem ipsum dolor sit amet, consectetur adipiscing elit magna aliqua
Worley effect - variant 2
CSS:
.header-font-bungee {
font-family: Bungee;
--data-y-offset: 0.09;
--data-lineheight-adjuster: 0.86;
--data-underline-position: 0.79;
--data-underline-width: 0.08;
}
.justify-right-test {
text-align: right;
}
.worley-v2 {
--data-base-color: white;
--data-dark-base-color: white;
--data-highlight-color: #0760f7;
--data-dark-highlight-color: #74c0f2;
--data-noise-sum-function: none;
--data-noise-output: YminusX;
--data-noise-scale: 45;
--data-contrast-color: darkred;
--data-dark-contrast-color: pink;
}
HTML:
<h4
id="header-test-6"
class="demo-header
header-font-bungee
justify-right-test
worley-header
worley-v2"
contenteditable="plaintext-only"
>
Lorem ipsum dolor <i>sit amet</i>, consectetur <u>adipiscing elit</u> magna aliqua
</h4>
Lorem ipsum dolor sit amet, consectetur adipiscing elit magna aliqua
animated-highlight-gradient-text-snippet
A simple gradient effect using two colors, spaced along the gradient to make a series of bars. The gradient animates downwards in a repeating pattern.
The snippet can be customised using the following data- attributes applied using CSS variables, or directly to the HTML header element:
- data-main-color - any CSS color string
- data-highlight-color - any CSS color string
- data-gradient-easing - (string) easing function, for example: 'linear', 'easeOutIn3', etc
- data-gradient-skew-x - (-2 - 2) skew the gradient pattern horizontally
- data-gradient-skew-y - (-2 - 2) skew the gradient pattern vertically
- data-gradient-stretch-x - (0 - 4) stretch the gradient pattern horizontally
- data-gradient-stretch-y - (0 - 4) stretch the gradient pattern vertically
... And for prefers-color-scheme: dark users:
- data-dark-main-color - any CSS color string
- data-dark-highlight-color - any CSS color string
This snippet reacts to the user preference prefers-contrast: more with the following data- attributes:
- data-contrast-color - any CSS color string
- data-dark-contrast-color - any CSS color string
Animated highlight gradient effect - default (animated)
CSS:
.letter-space-px-test {
letter-spacing: 4px;
}
HTML:
<h4
id="header-test-7"
class="demo-header
header-font-sans
letter-space-px-test
highlight-gradient-header"
contenteditable="plaintext-only"
data-is-animated="true"
>
Lorem ipsum dolor <i>sit amet</i>, consectetur <u>adipiscing elit</u> magna aliqua
</h4>
Scrawl-canvas Phrase entitys include letter spacing functionality; these text snippets will use any CSS letter-spacing property value applied to the header element.
Lorem ipsum dolor sit amet, consectetur adipiscing elit magna aliqua
Animated highlight gradient effect - default with amendments
CSS:
.letter-space-em-test {
letter-spacing: 0.2em;
}
HTML:
<h4
id="header-test-8"
class="demo-header
header-font-serif
letter-space-em-test
highlight-gradient-header"
contenteditable="plaintext-only"
data-main-color="black"
data-dark-main-color="#faf1d4"
data-highlight-color="orange"
data-dark-highlight-color="#e6a315"
data-gradient-easing="easeInOut"
data-is-animated="true"
>
Lorem ipsum dolor <i>sit amet</i>, consectetur <u>adipiscing elit</u> magna aliqua
</h4>
Scrawl-canvas gradients support non-linear easings.
Lorem ipsum dolor sit amet, consectetur adipiscing elit magna aliqua
Animated highlight gradient effect - variant 1
CSS:
.highlight-gradient-v1 {
--data-main-color: lch(29.2345% 44.2 27);
--data-dark-main-color: #5eadd1;
--data-highlight-color: lab(52.2345% 40.1645 59.9971);
--data-dark-highlight-color: #c5d6fc;
--data-gradient-skew-x: -1;
/* no space after the colon! */
--data-gradient-easing:easeOutIn;
--data-is-animated: true;
}
HTML:
<h4
id="header-test-9"
class="demo-header
header-font-bungee
highlight-gradient-header
highlight-gradient-v1"
data-contrast-color="darkred"
data-dark-contrast-color="pink"
contenteditable="plaintext-only"
>
Lorem ipsum dolor <i>sit amet</i>, consectetur <u>adipiscing elit</u> magna aliqua
</h4>
Scrawl-canvas supports the use of LAB and LCH color strings.
Lorem ipsum dolor sit amet, consectetur adipiscing elit magna aliqua
bubbles-text-snippet
An animation effect that shows bubbles appearing, rising and expanding inside the text.
The snippet can be customised using the following data- attributes applied using CSS variables, or directly to the HTML header element:
- data-text-color - any CSS color string
- data-outline-color - any CSS color string
- data-outline-width - (unit % of font size) percentage of the font size for text outline width
- data-bubble-color - any CSS color string
- data-bubble-outline-color - any CSS color string
- data-bubble-density - the number of bubbles to generate
... And for prefers-color-scheme: dark users:
- data-dark-text-color - any CSS color string
- data-dark-outline-color - any CSS color string
- data-dark-bubble-color - any CSS color string
- data-dark-bubble-outline-color - any CSS color string
This snippet reacts to the user preference prefers-contrast: more with the following data- attributes:
- data-contrast-color - any CSS color string
- data-dark-contrast-color - any CSS color string
Bubbles text effect - default values
CSS:
.header-font-carter-one {
font-family: 'Carter One';
--data-y-offset: 0.17;
--data-lineheight-adjuster: 0.73;
--data-underline-position: 0.57;
--data-underline-width: 0.08;
--data-no-underline-glyphs:gjpqy;
}
HTML:
<h4
id="header-test-10"
class="demo-header
header-font-carter-one
no-bold
bubbles-text-header"
contenteditable="plaintext-only"
data-is-animated="true"
>
Lorem ipsum <b>dolor</b> <i>sit amet</i>, consectetur <u>adipiscing elit</u> magna aliqua
</h4>
Lorem ipsum dolor sit amet, consectetur adipiscing elit magna aliqua
Bubbles text effect - variant 1
CSS:
.bubbles-text-v1 {
--data-text-color: white;
--data-outline-color: black;
--data-bubble-color: green;
--data-bubble-outline-color: gold;
--data-dark-text-color: black;
--data-dark-outline-color: white;
--data-dark-bubble-color: lightgreen;
--data-dark-bubble-outline-color: gold;
--data-bubble-density: 100;
--data-contrast-color: darkred;
--data-dark-contrast-color: pink;
--data-is-animated: true;
}
HTML:
<h4
id="header-test-11"
class="demo-header
header-font-carter-one
no-bold
bubbles-text-header
bubbles-text-v1"
contenteditable="plaintext-only"
>
Lorem ipsum <b>dolor</b> <i>sit amet</i>, consectetur <u>adipiscing elit</u> magna aliqua
</h4>
Lorem ipsum dolor sit amet, consectetur adipiscing elit magna aliqua
swirling-stripes-text-snippet
A striped 2-color gradient effect. Animation occurs when the user hovers their browser cursor over the header, which leads to a swirl filter being applied to the text.
The snippet can be customised using the following data- attributes applied using CSS variables, or directly to the HTML header element:
- data-main-color - any CSS color string
- data-stripe-color - any CSS color string
- data-stripe-ratio - (0 - 1) the ratio of stripe to main color; higher values show wider stripes
- data-swirl-angle - (degrees) higher values lead to a tighter swirl; use negative values to reverse the swirl direction
- data-gradient-skew-x - (-2 - 2) skew the gradient pattern horizontally
- data-gradient-skew-y - (-2 - 2) skew the gradient pattern vertically
- data-gradient-stretch-x - (0 - 4) stretch the gradient pattern horizontally
- data-gradient-stretch-y - (0 - 4) stretch the gradient pattern vertically
... And for prefers-color-scheme: dark users:
- data-dark-main-color - any CSS color string
- data-dark-stripe-color - any CSS color string
This snippet makes no attempt to react to the prefers-contrast user preference.
Swirling stripes effect - default (animated)
HTML:
<h4
id="header-test-12"
class="demo-header
header-font-sans
swirling-stripes-header"
contenteditable="plaintext-only"
data-is-animated="true"
>
Lorem ipsum dolor <i>sit amet</i>, consectetur <u>adipiscing elit</u> magna aliqua
</h4>
Lorem ipsum dolor sit amet, consectetur adipiscing elit magna aliqua
Applying a Scrawl-canvas snippet to HTML header elements
These header text colorizer and animation effects have been designed so they can be applied to any font (left-to-right, alphabetic) - including cloud-based fonts - at any given font size. However, every font is its own thing and the metadata included in a font can be, at times, less than helpful. The practical outcome of font-uniqueness is that we have to finesse canvas font placement so that it can match up with the HTML-rendered text as closely as possible. We can do this using a set of data- attributes applied using CSS variables, or directly to the HTML header element:
HTML elements
- id="this-header-unique-name" - if applying a snippet to an HTML element, that element needs to be given a unique id value
- class="arbitrary-name" - we can use any CSS selector value to apply a snippet to HTML elements matching that selector
- contenteditable="plaintext-only" - useful during development to make sure canvas and HTML text match up as closely as possible
HTML and/or CSS font-related data- attributes/variables
- data-y-offset="0.11" - (unit % of font size) move the canvas text up/down until it covers the HTML text
- data-lineheight-adjuster="0.89" - (0 - 1) tweak the canvas text line height, for when the HTML text breaks into multiple lines
- data-underline-position="0.75" - (unit % of font size) tweak the positioning of canvas font underlines
- data-underline-width="0.09" - (unit % of font size) tweak the canvas underline width
- data-no-underline-glyphs="gjpqy" - (string) skip underlining these letters
- data-is-animated="true" - when set, the snippet will attempt to add accessibility control buttons to the header element to switch the animation off, and back on again. If the user has set their device/browser to prefers-reduced-motion then the animation should automatically halt after 5 seconds
Using snippets: We apply Scrawl-canvas snippets to HTML elements using Javascript:
JS:
import * as scrawl from 'path/to/scrawl-canvas/library';
import myFontEffect from './path/to/required-SC-header-snippet.js';
const headers = document.querySelectorAll('.arbitrary-name');
headers.forEach(el => myFontEffect(el, scrawl));
Testing the responsiveness of the snippets: all the examples have been set up with media queries to change font size in line with browser's viewport width.