FunText

Version

Basics

FunText is a lightweight and versatile npm library designed for text animation.

About

The aim of this project is to offer straightforward and readily accessible animation choices for text-based elements. It empowers users to craft entirely custom animations while maintaining complete control over them. This is achieved through the incorporation of newly standardized Shadow DOM technology.

Instalation

Element Plus can run on browsers that support ES2018.

Package manager

Using a package manager is recomended to allow the use of bundlers.

# NPM
$ npm install funtext --save

# Yarn
$ yarn add funtext

# PNPM
$ pnpm install funtext

Import in Browser

Import Element Plus through browser HTML tags directly, and use global variable FunText.

// unpkg
<script src="//unpkg.com/funtext"></script>

// jsdelivr
<script src="https://cdn.jsdelivr.net/npm/funtext"></script>

Examples

Setup

To init a funtext instance we pass it a container and the list of animations.

Example:

<div id="funtext">This text is animated</div>
import { FunText, type InputAnimation } from "funtext";

// Retrives the container
const container = document.getElementById(
  "funtext"
);

// Defines the animations
const animations: InputAnimation[] = [
  {
    scope: "letter",
    property: "translate",
    duration: 1.5,
    steps: "0 10px",
    iteration: "infinite",
    direction: "alternate",
  },
];

// Defines options
const options: InputOptions = {
  defaults: {
    iteration: "infinite",
    direction: "alternate"
  }
}

if (container) {
  // Builds the funtext instance
  const funtext = new FunText(
    container,
    animations,
    options
  );

  // Replaces the content of the container with the funtext instance
  funtext.mount();
}

Result:

This text is animated

Scope

A scope is an animation property that determines how the text is divided into individual elements.

Build-in

There are two build-in scopes, word and letter.

Example:

<div id="word">Scoped into words</div>
<div id="letter">Scoped into letters</div>
const word_container = document.getElementById(
  "word"
);
const word_animations = [
  {
    scope: "word",
    property: "translate",
    duration: 2,
    steps: "0 10px",
    iteration: "infinite",
    direction: "alternate",
    offset: 0.5,
  },
  {
    scope: "letter",
    property: "color",
    duration: 9,
    steps: ["", "yellow", "orange", "red", "lime", "green", "blue", "purple"],
    iteration: "infinite",
  },
];
const funtext_word = new FunText(word_container, word_animations)
funtext_word.mount()

const letter_container = document.getElementById("letter");
const letter_animations: InputAnimation[] = [
  {
    scope: "letter",
    property: "translate",
    duration: 1.5,
    steps: "0 10px",
    iteration: "infinite",
    direction: "alternate",
  },
];
const funtext_letter = new FunText(letter_container, letter_animations)
funtext_word.mount()

Result:

Scoped into words
Scoped into letters

Custom

It is also possible to define a custom scope. A scope has two properties, split and priority. Split is either a string or a regex defining how the text is divided and the priority is a number that determines in what order the scope will be applied. Lower scopes get applied first (letter has priority 3 and word has priority 1).

Example:

const animations = [
  {
    scope: {
      split: "A",
      priority: 0,
    },
    property: "translate",
    duration: 1,
    steps: {
      0.1: "0 -5px",
      100: "0 5px",
    },
    iteration: "infinite",
    direction: "alternate",
    offset: 1,
  },
  {
    scope: {
      split: "B",
      priority: 4,
    },
    property: "color",
    duration: 1,
    steps: "red",
    iteration: "infinite",
    direction: "alternate",
    offset: 1,
  },
];

Result:

cccBcccAcccBccc

Steps

Steps determine the keyframes of the animation. Passing a string gives the final value, passign an array gives a list of values at equal intervals and passing an object gives a list of values at specefied intervals.

Example:

const string_animations = [
  {
    scope: "letter",
    property: "color",
    duration: 10,
    steps: "red",
    fill: "forwards",
  },
];

const array_animations = [
  {
    scope: "letter",
    property: "color",
    duration: 10,
    steps: ["blue", "green", "yellow", "red"],
    fill: "forwards",
  },
];

const object_animations = [
  {
    scope: "letter",
    property: "color",
    duration: 10,
    steps: {
      70: "blue",
      85: "green",
      95: "yellow",
      100: "red",
    },
    fill: "forwards",
  },
];

Result:

Steps are a string
Steps are an array
Steps are an object

Animations

Animations have all the standard properties regular css animations have like: duration, delay, iteration-count, direction, timing-function, fill-mode and play-state, a property that defines the property that will be animated, as well as some custom properties like offset and sync.

Offset

Offset defines the delay between animations in the same scope.

Example:

const offset_none = [
  {
    scope: "letter",
    property: "opacity",
    duration: 5,
    steps: "0",
    fill: "forwards",
    offset: 0,
  },
];

const offset_small = [
  {
    scope: "letter",
    property: "opacity",
    duration: 5,
    steps: "0",
    fill: "forwards",
    offset: 0.1, // Default
  },
];

const offset_large = [
  {
    scope: "letter",
    property: "opacity",
    duration: 5,
    steps: "0",
    fill: "forwards",
    offset: 0.5,
  },
];

const offset_custom = [
  {
    scope: "letter",
    property: "opacity",
    duration: 5,
    steps: "0",
    fill: "forwards",
    offset: (index, priority) => {
      return index * index * 0.05;
    },
  },
];

Result:

This has no offset
This has a small offset
This has a large offset
This has a custom offset

Sync

Sync moves the animation to fit a specefied time frame. It has to parameters: duration, which specefies a new duration where the animation will be placed, and location, which specefies where in that new location the animation will be placed.

Example:

const sync_none = [
  {
    scope: "letter",
    property: "background",
    duration: 6,
    steps: "red",
  },
];

const sync_start = [
  {
    scope: "letter",
    property: "background",
    duration: 3,
    steps: "red",
    sync: {
      duration: 6,
      location: 0,
    },
  },
];

const sync_middle = [
  {
    scope: "letter",
    property: "background",
    duration: 3,
    steps: "red",
    sync: {
      duration: 6,
      location: 50,
    },
  },
];

const sync_end = [
  {
    scope: "letter",
    property: "background",
    duration: 3,
    steps: "red",
    sync: {
      duration: 6,
      location: 100,
    },
  },
];

Result:

This animation has no sync
This animation is synced to the start
This animation is synced to the middle
This animation is synced to the end

Transform and filter

There are two animated properties that control multiple other properties. These are In the realm of CSS animations, transform and filter are pivotal properties, each capable of orchestrating a variety of sub-properties. Managing these intricate configurations manually can be challenging, prompting the implementation of custom animations tailored specifically for these compound properties."

Example:

const transform = [
  {
    scope: "letter",
    type: "transform",
    animations: [
      {
        property: "translateY",
        duration: 5,
        unit: "px",
        steps: "-5",
      },
      {
        property: "rotate",
        duration: 5,
        unit: "deg",
        steps: { 50: "180" },
      },
    ],
    fill: "forwards",
  },
];

const filter = [
  {
    scope: "letter",
    type: "filter",
    animations: [
      {
        property: "opacity",
        duration: 5,
        unit: "",
        steps: [1, 0],
      },
      {
        property: "blur",
        duration: 4,
        unit: "px",
        steps: 2,
      },
    ],
    fill: "forwards",
  },
];

Result:

Transform animations
Filter animations

Options

Options are an optional third parameter that provide additional customization, accessibility support and help shorten initialization.

Text

Uses given text for animation instead on the one in the container.

Example:

<div id="funtext">This text will be overwriten</div>
const container = document.getElementById("funtext");
const options = {
  text: "New text provided in options"
}
const funtext = new FunText(container, [], options);
fun_options_text.mount();

Result:

Defaults

Provides default values to animation properties.

Example:

const animations = [
    {
      scope: "letter",
      property: "color",
      duration: 3,
      steps: "rgb(81, 150, 173)",
    },
  ];
  
  const options = {
    defaults: {
      iteration: "infinite",
      direction: "alternate",
    },
  };

Result:

Using default iteration and direction

Tags

Tags determine the html tags used for specific element in the creating of the funtext dom structure. There are container (div), text (p) and break (br).

Example:

const options = {
  tags: {
    text: "span",
    container: "section"
  }
}

Css

Can be used for custom styling. Has the following parameters: global, for all classes, root, for the root element, container, for the container elements, text, for the text elements, break, for the newline elements and raw, for insering raw css. For dark mode, there is dark, which takes the above elements and redefines them under the media rule prefers-color-scheme: dark. For layouts with specific breakpoints, any number can be inserted and all above elements are redefined under the media rule max-width: "number"px.

Example:

<div id="funtext1">This has a bigger font</div>
<div id="funtext2">his is blue on light mode and red on dark mode</div>
<div id="funtext3">This has a underline on mobile and a dash on desktop</div>
const user_css = {
  css: {
    root: "font-size: 1.5rem;",
  },
};

const user_css_dark = {
  css: {
    container: "color: blue;",
    dark: {
      container: "color: red;",
    },
  },
};

const user_css_layout = {
  css: {
    text: "text-decoration: dashed;",
    768: {
      text: "text-decoration: underline;",
    },
  },
};

Result:

This has a bigger font
This is blue on light mode and red on dark mode
This has a underline on mobile and a dash on desktop

Attributes

Sets the attribute and value of the root element.

Example:

const options = {
  attributes: {
    id: "funtext",
    data: "some_data"
  }
}

Accessibility

Accessibility provides support for screen-readers and people with poor eyesight. This is done with aira, which adds a label for screen readers and hides the animated element, prefersContrast, which adds artificial contrast to elements and prefersReducedMotion, which prevents animated text from moving.

const options = {
  accessibility: {
    aria: true,  // Set to true by default
    prefersContrast: 0.25,  // Set to 0.15 by default
    prefersReducedMotion: true,  // Set to false by default
  }
}

Mode

Toggles the mode property of the shadow dom. If set to true allows outside javascript to access the funtext element.

Example:

const options = {
  mode: true,  // Set to false by default
}

Global

So far all settings have effected individual elements but we can also change ioptions globally to apply to all elements. These global options can overwriten by the elements local settings.

Example:

// alternative FunText.setOptions({ ... })
FunText.options = {
  ...
}

Controls

Controls allow for modification and manual control of the animated text.

Build

The mount function replaces container text with animates text and unmount does the opposite.

Example:

<div id="funtext">
  <p id="click_display">Clicks: 0</p>
  <br>
  <button id="click_button">Click</button>
</div>

<div>
  <button id="mount_button">Mount</button>
  <button id="unmount_button">Unmount</button>
</div>
const click_display = document.getElementById("click_display");
let clicks = 0;
const click_button = document.getElementById("click_button");
click_button.addEventListener("click", () => {
  clicks += 1;
  click_display.innerHTML = "Clicks: " + clicks;
});
            
const funtext_conatiner = document.getElementById("funtext");
const funtext_animations] = [
  {
    scope: "letter",
    property: "translate",
    steps: "0 4px",
    duration: 0.5,
    iteration: "infinite",
    direction: "alternate",
    offset: 0.2
  },
];
const funtext_options = {
  text: "Loading...",
};
const funtext = new FunText(
  fun_controls_build_container,
  fun_controls_build_animations,
  fun_controls_build_options
);
  

const mount_button = document.getElementById("mount_button");
mount_button.addEventListener("click", () => funtext.mount());

const unmount_button = document.getElementById("unmount_button");
unmount_button.addEventListener("click", () => funtext.unmount());

Result:

Clicks: 0


Setters

Parameters of the funtext object can be altered after construction. The container, animations and options can all be manually chnaged.

Example:

const container_start = document.getElementById("container_start");
const container_new = document.getElementById("container_new");

const animations_start = [
  {
    scope: "letter",
    property: "color",
    steps: ["lime", "green", "lime"],
    duration: 3,
    iteration: "infinite",
    sync: {
      duration: 6,
      location: 0,
    },
  },
];
const animations_new = [
  {
    scope: "word",
    property: "translate",
    steps: "10px 0",
    duration: 4,
    iteration: "infinite",
    direction: "alternate",
  },
];

const options_start = {
  css: {
    text: "font-size: 1.5rem;",
  },
};
const options_new = {
  css: {
    text: "font-size: 1.1rem;",
  },
};

const funtext = new FunText(
  container_start,
  animations_start,
  options_start
);
funtext.mount();

const container_button = document.getElementById("set_container");
container_button.addEventListener("click", () => {
  funtext.container = container_new;
});

const animations_button = document.getElementById("set_animations");
animations_button.addEventListener("click", () => {
  funtext.animations = animations_new;
});

const options_button = document.getElementById("set_options");
options_button.addEventListener("click", () => {
  funtext.options = options_new;
});

Result:

Starting container
New container

Playstate

The state of an individual animation can be changes manually. It can be paused, played or toggled. This can be applied to an indiviudal animation or all of them.

Example:

const container = document.getElementById("funtext");
const animations: InputAnimation[] = [
  {
    scope: "letter",
    property: "background",
    steps: ["yellow", "orange", "red", "lime", "green", "blue", "purple"],
    duration: 7,
    iteration: "infinite",
    direction: "alternate",
  },
  {
    scope: "letter",
    property: "color",
    steps: ["purple", "blue", "green", "lime", "red", "orange", "yellow"],
    duration: 7,
    iteration: "infinite",
    direction: "alternate",
  },
];

const funtext = new FunText(
  container,
  animations
);
funtext.mount()?.pauseAll();

const first_id: AnimationId = {
  property: "background",
  scope: "letter",
};

const status_any = document.getElementById("status_any");
const status_all = document.getElementById("status_all");
function updateStatus() {
  status_any.innerText = "Playing any: " + funtext.isPlayingAny();
  status_all.innerText = "Playing all: " + funtext.isPlayingAll();
}

const play_first = document.getElementById("play_first");
play_first.addEventListener("click", () => {
  funtext.play(first_id);
  updateStatus();
});

const pause_first = document.getElementById("pause_first");
pause_first.addEventListener("click", () => {
  funtext.pause(first_id);
  updateStatus();
});

const toggle_first = document.getElementById("toggle_first");
toggle_first.addEventListener("click", () => {
  funtext.toggle(first_id);
  updateStatus();
});

const play_all = document.getElementById("play_all");
play_all.addEventListener("click", () => {
  funtext.playAll();
  updateStatus();
});

const pause_all = document.getElementById("pause_all");
pause_all.addEventListener("click", () => {
  funtext.pauseAll();
  updateStatus();
});

const toggle_all = document.getElementById("toggle_all");
toggle_all.addEventListener("click", () => {
  funtext.toggleAll();
  updateStatus();
});

Result:

Status

Playing any: false

Playing all: false

Control the playstate with the panel below

Documentation

FunText constructor
Parameter
Type
Default
Description
container
HTMLElement
Required
Container element for the text animations
animations
InputAnimation[]
Required
Animations that are applid to the text
animations
InputAnimation[]
Object
Additional options

Animations

Default animation
Parameter
Type
Default
Description
type
"default"
"default"
Type of the animation
scope
string | RegExp
"letter"
Scope of the animation
property
string
Required
Animated property
steps
string | array | object
Required
Animation keyframes
duration
number
Required
Duration of the animation
delay
number
0
Delay of the animation
iteration
number | string
1
Number of iterations
direction
string
"normal"
Direction of the animation
timing
string
"linear"
Timing function of the animation
fill
string
"none"
Fill mode of the animation
state
string
"playing"
Play state of the animation
offset
number | Function
0
Offset between scoped elements
sync
InputAnimationSync
null
Sync of the animation
onStart
Function
null
Runs at the start of the animation
onEnd
Function
null
Runs at the end of the animation
onIterationStart
Function
null
Runs at the start of the iteration
onIterationEnd
Function
null
Runs at the end of the iteration
onCancel
Function
null
Runs if the animation is canceled
Animation Sync
Parameter
Type
Default
Description
duration
number
Required
Duration to which the animation is synced to
location
number | string
Required
Location to which the animation is synced to
Transform / Filter animations
Parameter
Type
Default
Description
type
"transform" | "filter"
Required
Type of the animation
animations
TransformAnimation[] | FilterAnimation[]
Required
Sub-animations relating to the transform / filter animation properties
scope
string | RegExp
Required
Scope of the animation
delay
number
0
Delay of the animation
iteration
number | string
1
Number of iterations
direction
string
"normal"
Direction of the animation
timing
string
"linear"
Timing function of the animation
fill
string
"none"
Fill mode of the animation
state
string
"playing"
Play state of the animation
offset
number | Function
0
Offset between scoped elements
sync
InputAnimationSync
null
Sync of the animation
onStart
Function
null
Runs at the start of the animation
onEnd
Function
null
Runs at the end of the animation
onIterationStart
Function
null
Runs at the start of the iteration
onIterationEnd
Function
null
Runs at the end of the iteration
onCancel
Function
null
Runs if the animation is canceled
Transform / Filter animation
Parameter
Type
Default
Description
property
string
Required
Animated property
steps
string | array | object
Required
Animation keyframes
unit
string
Required
Unit of the given steps
duration
number
Required
Duration of the animation
delay
number
0
Delay of the animation

Options

Animation options
Parameter
Type
Default
Description
text
string
null
Text to be animated
defaults
DefaultProperties
null
Default values for animations
tags
Tags
null
Html tags for the constructed elements
css
CssOptions
null
Style for the constructed elements
attributes
Object
null
Attributes for the root element
accessibility
Accessibility
null
Accessibility options
openNode
boolean
false
if true allows outside styles and javascript to access the constructed elements
Animated Properties
Parameter
Type
Default
Description
delay
number
0
Delay of the animation
iteration
number | string
1
Number of iterations
direction
string
"normal"
Direction of the animation
timing
string
"linear"
Timing function of the animation
fill
string
"none"
Fill mode of the animation
state
string
"playing"
Play state of the animation
offset
number | Function
0
Offset between scoped elements
sync
InputAnimationSync
null
Sync of the animation
Tags
Parameter
Type
Default
Description
container
string
"div"
Tag for the container element
text
string
"p"
Tag for the text element
break
string
"br"
Tag for the break element
Css Options
Parameter
Type
Default
Description
default
string
null
Default style
root
string
null
Root element style
container
string
null
Container element style
text
string
null
Text element style
break
string
null
Break element style
raw
string
null
Raw inserted style
dark
CssOptions
null
Dark mode alternative style
number
CssOptions
null
Max width breakpoint styles
Accessibility
Parameter
Type
Default
Description
aria
boolean
true
Aria label for screen readers
prefersContrast
number
15
Applied contrast for user that specify it
prefersReducedMotion
boolean
false
Reduces motion for user that specify it

Controls

Build
Function
Parameter
Return value
Description
mount
void
FunText
Shows the animated text in the given container
unmount
void
FunText
Hides the animated text in the given container
rebuild
void
FunText
Rebuilds the html and style for the animated text
Getters and Setters
Function
Parameter
Return value
Description
getContainer
void
HTMLElement
Gets the funtext container
setContainer
HTMLElement
void
Sets the funtext container
getOptions
void
Options
Gets the funtext options
setOptions
InputOptions
void
Sets the funtext options
getAnimations
void
InputAnimations[]
Gets the funtext animations
setAnimations
InputAnimations[]
void
Sets the funtext animations

An alternative to getters and setters is to use funtext.container, funtext.options, funtext.animations directly.

Playstate
Function
Parameter
Return value
Description
isPlaying
AnimationId
boolean
Returns true if the specified animation is playing
isPlayingAny
void
boolean
Returns true if any animation is playing
isPlayingAll
void
boolean
Returns true if all animations are playing
isPaused
AnimationId
boolean
Returns true if the specified animation is paused
isPausedAny
void
boolean
Returns true if any animation is paused
isPausedAll
void
boolean
Returns true if all animations are paused
play
AnimationId
void
Plays the specified animation
playAll
void
void
Plays all animations
pause
AnimationId
void
Pauses the specified animation
pauseAll
void
void
Pauses all animations
toggle
AnimationId
void
Toggles the specified animation
toggleAll
void
void
Toggles all animations
reset
AnimationId
void
Resets the specified animation
resetAll
void
void
Resets all animations
Animation Id
Parameter
Type
Default
Description
property
string
Required
Property of the specefied animation
scope
number | "word" | "letter"
Required
Scope priority of the specefied animation