10+ JavaScript Text Effect Examples

This post contains a total of 10+ JavaScript Text Effect Examples with Source Code. All these Text Effects are made using JavaScript & Styled using CSS.

You can use the source code of these examples with credits to the original owner.

Related Posts

JavaScript Text Effect Examples

1. Decode Text Effect

Made by Ben Racicot. Source

<!DOCTYPE html>
<html lang="en" >
<head>
  <title></title>
<style>
@import url(https://fonts.googleapis.com/css?family=Share+Tech+Mono);
.decode-text {
  width: 100%;
  font-size: 30px;
  text-align: center;
}

.space {
  display: inline-block;
  width: 10px;
}

.text-animation {
  display: inline-block;
  position: relative;
  color: transparent;
  text-transform: uppercase;
}
.text-animation:before {
  content: "";
  color: black;
  position: absolute;
  top: 50%;
  left: 50%;
  background: #0e182d;
  width: 0;
  height: 1.2em;
  -webkit-transform: translate(-50%, -55%);
  -ms-transform: translate(-50%, -55%);
  transform: translate(-50%, -55%);
}
.text-animation.state-1:before {
  width: 1px;
}
.text-animation.state-2:before {
  width: 0.9em;
}
.text-animation.state-3 {
  color: black;
}
.text-animation.state-3:before {
  width: 0;
}

#refresh {
  position: absolute;
  top: 20px;
  left: 20px;
  cursor: pointer;
}

div {
  font-family: "Share Tech Mono", monospace;
}

body {
  height: 100vh;
  align-items: center;
  display: flex;
}
</style>
</head>
<body>
  <div class="decode-text">
  	<div class="text-animation">R</div>
  	<div class="text-animation">a</div>
   	<div class="text-animation">n</div>
    <div class="text-animation">d</div>
    <div class="text-animation">o</div>
    <div class="text-animation">m</div>
   	<div class="text-animation">i</div>
    <div class="text-animation">z</div>
    <div class="text-animation">e</div>
    <div class="text-animation">d</div>
    <div class="space"></div>

  	<div class="text-animation">d</div>
  	<div class="text-animation">e</div>
   	<div class="text-animation">c</div>
    <div class="text-animation">o</div>
    <div class="text-animation">d</div>
    <div class="text-animation">e</div>
    <div class="space"></div>

    <div class="text-animation">e</div>
    <div class="text-animation">f</div>
    <div class="text-animation">f</div>
    <div class="text-animation">e</div>
  	<div class="text-animation">c</div>
  	<div class="text-animation">t</div>
</div>

<a id="refresh" onclick="decodeText();">
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/><path d="M0 0h24v24H0z" fill="none"/></svg>
</a>
      <script>
/* ------------------------------------------------------------------------ *  
4 states per letter: Transparent | Line | Block | Visible.
These states are shuffled for a unique "decode" effect each time.
* ------------------------------------------------------------------------ */

function decodeText() {
  var text = document.getElementsByClassName('decode-text')[0];
  // debug with
  // console.log(text, text.children.length);

  // assign the placeholder array its places
  var state = [];
  for (var i = 0, j = text.children.length; i < j; i++) {
    text.children[i].classList.remove('state-1', 'state-2', 'state-3');
    state[i] = i;
  }

  // shuffle the array to get new sequences each time
  var shuffled = shuffle(state);

  for (var i = 0, j = shuffled.length; i < j; i++) {
    var child = text.children[shuffled[i]];
    classes = child.classList;

    // fire the first one at random times
    var state1Time = Math.round(Math.random() * (2000 - 300)) + 50;
    if (classes.contains('text-animation')) {
      setTimeout(firstStages.bind(null, child), state1Time);
    }
  }
}

// send the node for later .state changes
function firstStages(child) {
  if (child.classList.contains('state-2')) {
    child.classList.add('state-3');
  } else if (child.classList.contains('state-1')) {
    child.classList.add('state-2');
  } else if (!child.classList.contains('state-1')) {
    child.classList.add('state-1');
    setTimeout(secondStages.bind(null, child), 100);
  }
}
function secondStages(child) {
  if (child.classList.contains('state-1')) {
    child.classList.add('state-2');
    setTimeout(thirdStages.bind(null, child), 100);
  } else
  if (!child.classList.contains('state-1'))
  {
    child.classList.add('state-1');
  }
}
function thirdStages(child) {
  if (child.classList.contains('state-2')) {
    child.classList.add('state-3');
  }
}

function shuffle(array) {
  var currentIndex = array.length,temporaryValue,randomIndex;

  // While there remain elements to shuffle...
  while (0 !== currentIndex) {
    // Pick a remaining element...
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;

    // And swap it with the current element.
    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }
  return array;
}


// Demo only stuff
decodeText();

// beware: refresh button can overlap this timer and cause state mixups
setInterval(function () {decodeText();}, 10000);
    </script>
</body>
</html>

2. Futuristic Resolving/Typing Text Effect

Made by Kevin. Source

<!DOCTYPE html>
<html lang="en" >
<head>
  <title></title>
  <link rel='stylesheet' href='https://fonts.googleapis.com/css?family=Unica+One'>
<style>
* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
  margin: 0;
  font-family: "Unica One", sans-serif;
  background: #111;
}

.container {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  padding: 5rem;
}

.heading {
  color: #eee;
  font-size: 5rem;
  font-weight: 300;
  text-transform: uppercase;
}
</style>
</head>
<body>
  <div class="container">
  <h1 class="heading" data-target-resolver></h1>
</div>
      <script>
const resolver = {
  resolve: function resolve(options, callback) {
    // The string to resolve
    const resolveString = options.resolveString || options.element.getAttribute('data-target-resolver');
    const combinedOptions = Object.assign({}, options, { resolveString: resolveString });

    function getRandomInteger(min, max) {
      return Math.floor(Math.random() * (max - min + 1)) + min;
    };

    function randomCharacter(characters) {
      return characters[getRandomInteger(0, characters.length - 1)];
    };

    function doRandomiserEffect(options, callback) {
      const characters = options.characters;
      const timeout = options.timeout;
      const element = options.element;
      const partialString = options.partialString;

      let iterations = options.iterations;

      setTimeout(() => {
        if (iterations >= 0) {
          const nextOptions = Object.assign({}, options, { iterations: iterations - 1 });

          // Ensures partialString without the random character as the final state.
          if (iterations === 0) {
            element.textContent = partialString;
          } else {
            // Replaces the last character of partialString with a random character
            element.textContent = partialString.substring(0, partialString.length - 1) + randomCharacter(characters);
          }

          doRandomiserEffect(nextOptions, callback);
        } else if (typeof callback === "function") {
          callback();
        }
      }, options.timeout);
    };

    function doResolverEffect(options, callback) {
      const resolveString = options.resolveString;
      const characters = options.characters;
      const offset = options.offset;
      const partialString = resolveString.substring(0, offset);
      const combinedOptions = Object.assign({}, options, { partialString: partialString });

      doRandomiserEffect(combinedOptions, () => {
        const nextOptions = Object.assign({}, options, { offset: offset + 1 });

        if (offset <= resolveString.length) {
          doResolverEffect(nextOptions, callback);
        } else if (typeof callback === "function") {
          callback();
        }
      });
    };

    doResolverEffect(combinedOptions, callback);
  } };


/* Some GLaDOS quotes from Portal 2 chapter 9: The Part Where He Kills You
 * Source: http://theportalwiki.com/wiki/GLaDOS_voice_lines#Chapter_9:_The_Part_Where_He_Kills_You
 */
const strings = [
'Oh thank god, you\'re alright.',
'You know, being Caroline taught me a valuable lesson. I thought you were my greatest enemy. When all along you were my best friend.',
'The surge of emotion that shot through me when I saved your life taught me an even more valuable lesson: where Caroline lives in my brain.',
'Goodbye, Caroline.',
'You know, deleting Caroline just now taught me a valuable lesson. The best solution to a problem is usually the easiest one. And I\'ll be honest.',
'Killing you? Is hard.',
'You know what my days used to be like? I just tested. Nobody murdered me. Or put me in a potato. Or fed me to birds. I had a pretty good life.',
'And then you showed up. You dangerous, mute lunatic. So you know what?',
'You win.',
'Just go.',
'It\'s been fun. Don\'t come back.',
'......'];


let counter = 0;

const options = {
  // Initial position
  offset: 0,
  // Timeout between each random character
  timeout: 5,
  // Number of random characters to show
  iterations: 10,
  // Random characters to pick from
  characters: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'x', 'y', 'x', '#', '%', '&', '-', '+', '_', '?', '/', '\\', '='],
  // String to resolve
  resolveString: strings[counter],
  // The element
  element: document.querySelector('[data-target-resolver]') };


// Callback function when resolve completes
function callback() {
  setTimeout(() => {
    counter++;

    if (counter >= strings.length) {
      counter = 0;
    }

    let nextOptions = Object.assign({}, options, { resolveString: strings[counter] });
    resolver.resolve(nextOptions, callback);
  }, 1000);
}

resolver.resolve(options, callback);
    </script>
</body>
</html>

3. Sliding text effect

Made by ChenXin_nth. Source

<!DOCTYPE html>
<html lang="en" >
<head>
  <title></title>
    <link href="https://fonts.googleapis.com/css?family=Montserrat:900&display=swap" rel="stylesheet">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
<style>
* {
  margin: 0;
  padding: 0;
}
body {
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}
.line {
  width: 100vw;
}
.left, .right {
  width: 50vw;
  overflow: hidden;
  display: inline-block;
}
.left {
  color:pink;
  transform: skew(0deg, -15deg);
}
.right {
  color: black;
  transform: skew(0deg, 15deg);
}
.left .content {
  width: 100vw;
  text-align: center;
}
.right .content {
  width: 100vw;
  text-align: center;
  transform: translate(-50vw);
}
span {
  display: inline-block;
  font-family: 'Montserrat', sans-serif;
  font-size: 10vw;
  text-transform: uppercase;
  line-height: .8;
  transition: ease-out .6s;
}
</style>
</head>
<body>
  <div class="wrap">
    <div class="line">
      <div class="left">
        <div class="content">
          <span class="spanSlow">Aladdin</span>
        </div>
      </div><!--
      --><div class="right">
        <div class="content">
          <span class="spanSlow">Aladdin</span>
        </div>
      </div>
    </div>
    <div class="line">
      <div class="left">
        <div class="content">
          <span class="spanSlow">What do</span>
        </div>
      </div><!--
      --><div class="right">
        <div class="content">
          <span class="spanSlow">what do</span>
        </div>
      </div>
      </div>
      <div class="line">
          <div class="left">
            <div class="content">
              <span class="spanFast">you</span>
            </div>
          </div><!--
          --><div class="right">
            <div class="content">
              <span class="spanFast">you</span>
            </div>
          </div>
        </div>
        <div class="line">
            <div class="left">
              <div class="content">
                <span class="spanSlow">want</span>
              </div>
            </div><!--
            --><div class="right">
              <div class="content">
                <span class="spanSlow">want</span>
              </div>
            </div>
          </div>
</div>
      <script>
// The place I saw this effect:
// https://angle2.agency/

// Red Staper made a NICE tutorial about this effect! You should check it out!
// https://www.youtube.com/watch?v=LgiadQQM6mo&t=5s

window.addEventListener('mousemove', handleMouseMove);
window.addEventListener('resize', handleWindowResize);

const spansSlow = document.querySelectorAll('.spanSlow');
const spansFast = document.querySelectorAll('.spanFast');

let width = window.innerWidth;

function handleMouseMove(e) {
  let normalizedPosition = e.pageX / (width / 2) - 1;
  let speedSlow = 100 * normalizedPosition;
  let speedFast = 200 * normalizedPosition;
  spansSlow.forEach(span => {
    span.style.transform = `translate(${speedSlow}px)`;
  });
  spansFast.forEach(span => {
    span.style.transform = `translate(${speedFast}px)`;
  });
}
//we need to recalculate width when the window is resized
function handleWindowResize() {
  width = window.innerWidth;
}
    </script>
</body>
</html>

4. Bubbling Text Effect

Made by Html5andblog. Source

<!DOCTYPE html>
<html lang="en" >
<head>
  <title></title>
  <link rel='stylesheet' href='//fonts.googleapis.com/css?family=Luckiest+Guy'> 
<style>
/* Non essential CSS - Just for example centering */

html, body {
width: 100%;
height: 100%;
margin: 0;
}

.center-outer {
display: table;
width: 100%;
height: 100%;
}

.center-inner {
display: table-cell;
vertical-align: middle;
text-align: center;
}

/* Essential CSS - Makes the effect work */

body {
background-color: #3498db;
}

.bubbles {
display: inline-block;
font-family: arial;
position: relative;
}

.bubbles h1 {
position: relative;
margin: 1em 0 0;
font-family: 'Luckiest Guy', cursive;
color: #fff;
z-index: 2;
}

.individual-bubble {
position: absolute;
border-radius: 100%;
bottom: 10px;
background-color: #fff;
z-index: 1;
}
</style>
</head>
<body>
  <div class="center-outer">
<div class="center-inner">

<div class="bubbles">
<h1>Bubbling Header</h1>
</div>

</div>
</div>
  <script src='//cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js'></script>
      <script>
// Created for an Articles on:
// https://www.html5andbeyond.com/bubbling-text-effect-no-canvas-required/

jQuery(document).ready(function ($) {

  // Define a blank array for the effect positions. This will be populated based on width of the title.
  var bArray = [];
  // Define a size array, this will be used to vary bubble sizes
  var sArray = [4, 6, 8, 10];

  // Push the header width values to bArray
  for (var i = 0; i < $('.bubbles').width(); i++) {
    bArray.push(i);
  }

  // Function to select random array element
  // Used within the setInterval a few times
  function randomValue(arr) {
    return arr[Math.floor(Math.random() * arr.length)];
  }

  // setInterval function used to create new bubble every 350 milliseconds
  setInterval(function () {

    // Get a random size, defined as variable so it can be used for both width and height
    var size = randomValue(sArray);
    // New bubble appeneded to div with it's size and left position being set inline
    // Left value is set through getting a random value from bArray
    $('.bubbles').append('<div class="individual-bubble" style="left: ' + randomValue(bArray) + 'px; width: ' + size + 'px; height:' + size + 'px;"></div>');

    // Animate each bubble to the top (bottom 100%) and reduce opacity as it moves
    // Callback function used to remove finsihed animations from the page
    $('.individual-bubble').animate({
      'bottom': '100%',
      'opacity': '-=0.7' },
    3000, function () {
      $(this).remove();
    });



  }, 350);

});
    </script>
</body>
</html>
 

5. Spotlight Cursor Text Screen

Made by Caroline Artz. Source

<!DOCTYPE html>
<html lang="en" >
<head>
  <title></title>
  <link href="https://fonts.googleapis.com/css?family=Montserrat:900&display=swap" rel="stylesheet">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
<style>
body {
  font-family: Montserrat, sans-serif;
  font-weight: 900;
}
body, body * {
  cursor: none;
}

.shapes {
  position: relative;
  height: 100vh;
  width: 100vw;
  background: #2128bd;
  overflow: hidden;
}

.shape {
  will-change: transform;
  position: absolute;
  border-radius: 50%;
}
.shape.shape-1 {
  background: #005ffe;
  width: 650px;
  height: 650px;
  margin: -325px 0 0 -325px;
}
.shape.shape-2 {
  background: #ffe5e3;
  width: 440px;
  height: 440px;
  margin: -220px 0 0 -220px;
}
.shape.shape-3 {
  background: #ffcc57;
  width: 270px;
  height: 270px;
  margin: -135px 0 0 -135px;
}

.content {
  top: 0;
  left: 0;
  position: absolute;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  width: 100vw;
  background: #fff;
  mix-blend-mode: screen;
}

h1 {
  font-size: 100px;
  color: #000;
  margin: 0;
  text-align: center;
}
@media (min-width: 419px) {
  h1 {
    font-size: 100px;
    font-size: calc((0.0989119683 * 100vw + (58.5558852621px)));
  }
}
@media (min-width: 1430px) {
  h1 {
    font-size: 200px;
  }
}

.cursor {
  position: fixed;
  background: #2128bd;
  width: 20px;
  height: 20px;
  margin: -10px 0 0 -10px;
  border-radius: 50%;
  will-change: transform;
  -webkit-user-select: none;
     -moz-user-select: none;
      -ms-user-select: none;
          user-select: none;
  pointer-events: none;
  z-index: 10000;
}

::-moz-selection {
  color: #fff;
  background: #2128bd;
}

::selection {
  color: #fff;
  background: #2128bd;
}
</style>
</head>
<body>
  <div class="cursor"></div>
<div class="shapes">
  <div class="shape shape-1"></div>
  <div class="shape shape-2"></div>
  <div class="shape shape-3"></div>
</div>
<div class="content">
  <h1>Hello there!</h1>
</div>
  <script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/gsap-latest-beta.min.js'></script>
      <script>
document.body.addEventListener("mousemove", evt => {
  const mouseX = evt.clientX;
  const mouseY = evt.clientY;

  gsap.set(".cursor", {
    x: mouseX,
    y: mouseY });


  gsap.to(".shape", {
    x: mouseX,
    y: mouseY,
    stagger: -0.1 });

});
    </script>
</body>
</html>

6. Text Morph

Made by Valgo. Source

<!DOCTYPE html>
<html lang="en" >
<head>
  <title></title>
<style>
/* Explanation in JS tab */

/* Cool font from Google Fonts! */
@import url('https://fonts.googleapis.com/css?family=Raleway:900&display=swap');

body {
	margin: 0px;
}

#container {
	/* Center the text in the viewport. */
	position: absolute;
	margin: auto;
	width: 100vw;
	height: 80pt;
	top: 0;
	bottom: 0;
	
	/* This filter is a lot of the magic, try commenting it out to see how the morphing works! */
	filter: url(#threshold) blur(0.6px);
}

/* Your average text styling */
#text1, #text2 {
	position: absolute;
	width: 100%;
	display: inline-block;
	
	font-family: 'Raleway', sans-serif;
	font-size: 80pt;
	
	text-align: center;
	
	user-select: none;
}
</style>
</head>
<body>
  <!-- Explanation in JS tab -->

<!-- The two texts -->
<div id="container">
	<span id="text1"></span>
	<span id="text2"></span>
</div>

<!-- The SVG filter used to create the merging effect -->
<svg id="filters">
	<defs>
		<filter id="threshold">
			<!-- Basically just a threshold effect - pixels with a high enough opacity are set to full opacity, and all other pixels are set to completely transparent. -->
			<feColorMatrix in="SourceGraphic"
					type="matrix"
					values="1 0 0 0 0
									0 1 0 0 0
									0 0 1 0 0
									0 0 0 255 -140" />
		</filter>
	</defs>
</svg>
      <script>

const elts = {
  text1: document.getElementById("text1"),
  text2: document.getElementById("text2") };


// The strings to morph between. You can change these to anything you want!
const texts = [
"Why",
"is",
"this",
"so",
"satisfying",
"to",
"watch?"];


// Controls the speed of morphing.
const morphTime = 1;
const cooldownTime = 0.25;

let textIndex = texts.length - 1;
let time = new Date();
let morph = 0;
let cooldown = cooldownTime;

elts.text1.textContent = texts[textIndex % texts.length];
elts.text2.textContent = texts[(textIndex + 1) % texts.length];

function doMorph() {
  morph -= cooldown;
  cooldown = 0;

  let fraction = morph / morphTime;

  if (fraction > 1) {
    cooldown = cooldownTime;
    fraction = 1;
  }

  setMorph(fraction);
}

// A lot of the magic happens here, this is what applies the blur filter to the text.
function setMorph(fraction) {
  // fraction = Math.cos(fraction * Math.PI) / -2 + .5;

  elts.text2.style.filter = `blur(${Math.min(8 / fraction - 8, 100)}px)`;
  elts.text2.style.opacity = `${Math.pow(fraction, 0.4) * 100}%`;

  fraction = 1 - fraction;
  elts.text1.style.filter = `blur(${Math.min(8 / fraction - 8, 100)}px)`;
  elts.text1.style.opacity = `${Math.pow(fraction, 0.4) * 100}%`;

  elts.text1.textContent = texts[textIndex % texts.length];
  elts.text2.textContent = texts[(textIndex + 1) % texts.length];
}

function doCooldown() {
  morph = 0;

  elts.text2.style.filter = "";
  elts.text2.style.opacity = "100%";

  elts.text1.style.filter = "";
  elts.text1.style.opacity = "0%";
}

// Animation loop, which is called every frame.
function animate() {
  requestAnimationFrame(animate);

  let newTime = new Date();
  let shouldIncrementIndex = cooldown > 0;
  let dt = (newTime - time) / 1000;
  time = newTime;

  cooldown -= dt;

  if (cooldown <= 0) {
    if (shouldIncrementIndex) {
      textIndex++;
    }

    doMorph();
  } else {
    doCooldown();
  }
}

// Start the animation.
animate();
    </script>
</body>
</html>

7. Three js text effect

Made by Nanocheng. Source

<!DOCTYPE html>
<html lang="en" >
<head>
  <title></title>
<style>
body {
  margin: 0;
  overflow: hidden;
}

#instructions {
  position: absolute;
  color: #666;
  bottom: 0;
  padding-bottom: 6px;
  font-family: sans-serif;
  width: 100%;
  text-align: center;
  pointer-events: none;
}
</style>
</head>
<body>
  <script>
  THREE.ShapeUtils.triangulateShape = (function() {
  		var pnlTriangulator = new PNLTRI.Triangulator();
  		return function triangulateShape(contour, holes) {
  			return pnlTriangulator.triangulate_polygon([contour].concat(holes));
  		};
  	})();
</script>

<div id="three-container"></div>

<div id="instructions">
  MAX HUANG
</div>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/three.js/r75/three.min.js'></script>
<script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/175711/TextGeometry.js'></script>
<script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/175711/FontUtils.js'></script>
<script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/175711/pnltri.min.js'></script>
<script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/175711/droid_sans_bold.typeface.js'></script>
<script src='//cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/TweenMax.min.js'></script>
<script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/175711/bas.js'></script>
      <script>
window.onload = init;

function init() {
  var root = new THREERoot({
    createCameraControls: !true,
    antialias: window.devicePixelRatio === 1,
    fov: 60 });


  root.renderer.setClearColor(0x000000);
  root.renderer.setPixelRatio(window.devicePixelRatio || 1);
  root.camera.position.set(0, 0, 600);

  var textAnimation = createTextAnimation();
  root.scene.add(textAnimation);

  var light = new THREE.DirectionalLight();
  light.position.set(0, 0, 1);
  root.scene.add(light);

  var tl = new TimelineMax({
    repeat: -1,
    repeatDelay: 0.5,
    yoyo: true });

  tl.fromTo(textAnimation, 4, {
    animationProgress: 0.0 },
  {
    animationProgress: 0.6,
    ease: Power1.easeInOut },

  0);

  tl.fromTo(textAnimation.rotation, 4, {
    y: 0 },
  {
    y: Math.PI * 2,
    ease: Power1.easeInOut },
  0);

  createTweenScrubber(tl);
}

function createTextAnimation() {
  var geometry = generateTextGeometry('ROG ZEPHYRUS G15', {
    size: 40,
    height: 12,
    font: 'droid sans',
    weight: 'bold',
    style: 'normal',
    curveSegments: 24,
    bevelSize: 2,
    bevelThickness: 2,
    bevelEnabled: true,
    anchor: {
      x: 0.5,
      y: 0.5,
      z: 0.0 } });



  THREE.BAS.Utils.tessellateRepeat(geometry, 1.0, 2);

  THREE.BAS.Utils.separateFaces(geometry);

  return new TextAnimation(geometry);
}

function generateTextGeometry(text, params) {
  var geometry = new THREE.TextGeometry(text, params);

  geometry.computeBoundingBox();

  var size = geometry.boundingBox.size();
  var anchorX = size.x * -params.anchor.x;
  var anchorY = size.y * -params.anchor.y;
  var anchorZ = size.z * -params.anchor.z;
  var matrix = new THREE.Matrix4().makeTranslation(anchorX, anchorY, anchorZ);

  geometry.applyMatrix(matrix);

  return geometry;
}

////////////////////
// CLASSES
////////////////////

function TextAnimation(textGeometry) {
  var bufferGeometry = new THREE.BAS.ModelBufferGeometry(textGeometry);

  var aAnimation = bufferGeometry.createAttribute('aAnimation', 2);
  var aEndPosition = bufferGeometry.createAttribute('aEndPosition', 3);
  var aAxisAngle = bufferGeometry.createAttribute('aAxisAngle', 4);

  var faceCount = bufferGeometry.faceCount;
  var i, i2, i3, i4, v;

  var maxDelay = 0.0;
  var minDuration = 1.0;
  var maxDuration = 1.0;
  var stretch = 0.05;
  var lengthFactor = 0.001;
  var maxLength = textGeometry.boundingBox.max.length();

  this.animationDuration = maxDuration + maxDelay + stretch + lengthFactor * maxLength;
  this._animationProgress = 0;

  var axis = new THREE.Vector3();
  var angle;

  for (i = 0, i2 = 0, i3 = 0, i4 = 0; i < faceCount; i++, i2 += 6, i3 += 9, i4 += 12) {
    var face = textGeometry.faces[i];
    var centroid = THREE.BAS.Utils.computeCentroid(textGeometry, face);
    var centroidN = new THREE.Vector3().copy(centroid).normalize();

    // animation
    var delay = (maxLength - centroid.length()) * lengthFactor;
    var duration = THREE.Math.randFloat(minDuration, maxDuration);

    for (v = 0; v < 6; v += 2) {
      aAnimation.array[i2 + v] = delay + stretch * Math.random();
      aAnimation.array[i2 + v + 1] = duration;
    }

    // end position
    var point = utils.fibSpherePoint(i, faceCount, 200);

    for (v = 0; v < 9; v += 3) {
      aEndPosition.array[i3 + v] = point.x;
      aEndPosition.array[i3 + v + 1] = point.y;
      aEndPosition.array[i3 + v + 2] = point.z;
    }

    // axis angle
    axis.x = centroidN.x;
    axis.y = -centroidN.y;
    axis.z = -centroidN.z;

    axis.normalize();

    angle = Math.PI * THREE.Math.randFloat(0.5, 2.0);

    for (v = 0; v < 12; v += 4) {
      aAxisAngle.array[i4 + v] = axis.x;
      aAxisAngle.array[i4 + v + 1] = axis.y;
      aAxisAngle.array[i4 + v + 2] = axis.z;
      aAxisAngle.array[i4 + v + 3] = angle;
    }
  }

  var material = new THREE.BAS.PhongAnimationMaterial({
    shading: THREE.FlatShading,
    side: THREE.DoubleSide,
    transparent: true,
    uniforms: {
      uTime: {
        type: 'f',
        value: 0 } },


    shaderFunctions: [
    THREE.BAS.ShaderChunk['cubic_bezier'],
    THREE.BAS.ShaderChunk['ease_out_cubic'],
    THREE.BAS.ShaderChunk['quaternion_rotation']],

    shaderParameters: [
    'uniform float uTime;',
    'uniform vec3 uAxis;',
    'uniform float uAngle;',
    'attribute vec2 aAnimation;',
    'attribute vec3 aEndPosition;',
    'attribute vec4 aAxisAngle;'],

    shaderVertexInit: [
    'float tDelay = aAnimation.x;',
    'float tDuration = aAnimation.y;',
    'float tTime = clamp(uTime - tDelay, 0.0, tDuration);',
    'float tProgress = ease(tTime, 0.0, 1.0, tDuration);'
    // 'float tProgress = tTime / tDuration;'
    ],
    shaderTransformPosition: [
    'transformed = mix(transformed, aEndPosition, tProgress);',

    'float angle = aAxisAngle.w * tProgress;',
    'vec4 tQuat = quatFromAxisAngle(aAxisAngle.xyz, angle);',
    'transformed = rotateVector(tQuat, transformed);'] },

  {
    diffuse: 0x444444,
    specular: 0xcccccc,
    shininess: 4
    //emissive:0xffffff
  });

  THREE.Mesh.call(this, bufferGeometry, material);

  this.frustumCulled = false;
}
TextAnimation.prototype = Object.create(THREE.Mesh.prototype);
TextAnimation.prototype.constructor = TextAnimation;

Object.defineProperty(TextAnimation.prototype, 'animationProgress', {
  get: function () {
    return this._animationProgress;
  },
  set: function (v) {
    this._animationProgress = v;
    this.material.uniforms['uTime'].value = this.animationDuration * v;
  } });


function THREERoot(params) {
  params = utils.extend({
    fov: 60,
    zNear: 10,
    zFar: 100000,

    createCameraControls: true },
  params);

  this.renderer = new THREE.WebGLRenderer({
    antialias: params.antialias });

  this.renderer.setPixelRatio(Math.min(2, window.devicePixelRatio || 1));
  document.getElementById('three-container').appendChild(this.renderer.domElement);

  this.camera = new THREE.PerspectiveCamera(
  params.fov,
  window.innerWidth / window.innerHeight,
  params.zNear,
  params.zfar);


  this.scene = new THREE.Scene();

  if (params.createCameraControls) {
    this.controls = new THREE.OrbitControls(this.camera, this.renderer.domElement);
  }

  this.resize = this.resize.bind(this);
  this.tick = this.tick.bind(this);

  this.resize();
  this.tick();

  window.addEventListener('resize', this.resize, false);
}
THREERoot.prototype = {
  tick: function () {
    this.update();
    this.render();
    requestAnimationFrame(this.tick);
  },
  update: function () {
    this.controls && this.controls.update();
  },
  render: function () {
    this.renderer.render(this.scene, this.camera);
  },
  resize: function () {
    this.camera.aspect = window.innerWidth / window.innerHeight;
    this.camera.updateProjectionMatrix();

    this.renderer.setSize(window.innerWidth, window.innerHeight);
  } };


////////////////////
// UTILS
////////////////////

var utils = {
  extend: function (dst, src) {
    for (var key in src) {
      dst[key] = src[key];
    }

    return dst;
  },
  randSign: function () {
    return Math.random() > 0.5 ? 1 : -1;
  },
  ease: function (ease, t, b, c, d) {
    return b + ease.getRatio(t / d) * c;
  },
  // mapEase:function(ease, v, x1, y1, x2, y2) {
  //   var t = v;
  //   var b = x2;
  //   var c = y2 - x2;
  //   var d = y1 - x1;
  //
  //   return utils.ease(ease, t, b, c, d);
  // },
  fibSpherePoint: function () {
    var v = {
      x: 0,
      y: 0,
      z: 0 };

    var G = Math.PI * (3 - Math.sqrt(5));

    return function (i, n, radius) {
      var step = 2.0 / n;
      var r, phi;

      v.y = i * step - 1 + step * 0.5;
      r = Math.sqrt(1 - v.y * v.y);
      phi = i * G;
      v.x = Math.cos(phi) * r;
      v.z = Math.sin(phi) * r;

      radius = radius || 1;

      v.x *= radius;
      v.y *= radius;
      v.z *= radius;

      return v;
    };
  }() };


function createTweenScrubber(tween, seekSpeed) {
  seekSpeed = seekSpeed || 0.001;

  function stop() {
    TweenMax.to(tween, 1, {
      timeScale: 0 });

  }

  function resume() {
    TweenMax.to(tween, 1, {
      timeScale: 1 });

  }

  function seek(dx) {
    var progress = tween.progress();
    var p = THREE.Math.clamp(progress + dx * seekSpeed, 0, 1);

    tween.progress(p);
  }

  var _cx = 0;

  // desktop
  var mouseDown = false;
  document.body.style.cursor = 'pointer';

  window.addEventListener('mousedown', function (e) {
    mouseDown = true;
    document.body.style.cursor = 'ew-resize';
    _cx = e.clientX;
    stop();
  });
  window.addEventListener('mouseup', function (e) {
    mouseDown = false;
    document.body.style.cursor = 'pointer';
    resume();
  });
  window.addEventListener('mousemove', function (e) {
    if (mouseDown === true) {
      var cx = e.clientX;
      var dx = cx - _cx;
      _cx = cx;

      seek(dx);
    }
  });
  // mobile
  window.addEventListener('touchstart', function (e) {
    _cx = e.touches[0].clientX;
    stop();
    e.preventDefault();
  });
  window.addEventListener('touchend', function (e) {
    resume();
    e.preventDefault();
  });
  window.addEventListener('touchmove', function (e) {
    var cx = e.touches[0].clientX;
    var dx = cx - _cx;
    _cx = cx;

    seek(dx);
    e.preventDefault();
  });
}
    </script>
</body>
</html>

8. Terminal Text Effect

Made by Tobias. Source

<!DOCTYPE html>
<html lang="en" >
<head>
  <title></title>
<style>
@import url(https://fonts.googleapis.com/css?family=Khula:700);
body {
  background: #111;
}
.hidden {
  opacity:0;
}
.console-container {
 
  font-family:Khula;
  font-size:4em;
  text-align:center;
  height:200px;
  width:600px;
  display:block;
  position:absolute;
  color:white;
  top:0;
  bottom:0;
  left:0;
  right:0;
  margin:auto;
}
.console-underscore {
   display:inline-block;
  position:relative;
  top:-0.14em;
  left:10px;
}
</style>
</head>
<body>
  <div class='console-container'><span id='text'></span><div class='console-underscore' id='console'>&#95;</div></div>
      <script>
// function([string1, string2],target id,[color1,color2])    
consoleText(['Hello World.', 'Console Text', 'Made with Love.'], 'text', ['tomato', 'rebeccapurple', 'lightblue']);

function consoleText(words, id, colors) {
  if (colors === undefined) colors = ['#fff'];
  var visible = true;
  var con = document.getElementById('console');
  var letterCount = 1;
  var x = 1;
  var waiting = false;
  var target = document.getElementById(id);
  target.setAttribute('style', 'color:' + colors[0]);
  window.setInterval(function () {

    if (letterCount === 0 && waiting === false) {
      waiting = true;
      target.innerHTML = words[0].substring(0, letterCount);
      window.setTimeout(function () {
        var usedColor = colors.shift();
        colors.push(usedColor);
        var usedWord = words.shift();
        words.push(usedWord);
        x = 1;
        target.setAttribute('style', 'color:' + colors[0]);
        letterCount += x;
        waiting = false;
      }, 1000);
    } else if (letterCount === words[0].length + 1 && waiting === false) {
      waiting = true;
      window.setTimeout(function () {
        x = -1;
        letterCount += x;
        waiting = false;
      }, 1000);
    } else if (waiting === false) {
      target.innerHTML = words[0].substring(0, letterCount);
      letterCount += x;
    }
  }, 120);
  window.setInterval(function () {
    if (visible === true) {
      con.className = 'console-underscore hidden';
      visible = false;

    } else {
      con.className = 'console-underscore';

      visible = true;
    }
  }, 400);
}
    </script>
</body>
</html>

9. Fluid text hover

Made by Robin Delaporte. Source

<!DOCTYPE html>
<html lang="en" >
<head>
  <title></title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
<style>
body {
  position: fixed;
  height: 100%;
  overflow: hidden;
}

canvas {
  position: absolute;
  width: 100%;
  height: 100vh;
  top: 0;
  left: 0;
}

.mask {
  position: absolute;
  z-index: 2;
  background: white;
  height: 100vh;
  width: 100vw;
  mix-blend-mode: screen;
  /* display: none; */
}

svg {
  width: 90%;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
</style>
</head>
<body>
  <div class="mask">
	<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1040 205.1" style="enable-background:new 0 0 1040 205.1;" xml:space="preserve">
        <style type="text/css">
          .st0 {
            fill-rule: evenodd;
            clip-rule: evenodd;
          }
        </style>
        <g>
          <g>
            <path
              class="st0"
              d="M108.7,155.2l24.8,23.3c-2.1,3.1-4.9,6.2-8.3,9.2c-10.2,8.8-26.2,16.4-48.5,16.4C33.4,204.1,1,174.8,1,131.2
      			c0-43.3,32.4-72.6,75.7-72.6c29.8,0,48.4,13.2,56.8,25.5l-28.7,26.7c-5.5-8-14.3-13.2-26.1-13.2c-18.3,0-32.4,12.6-32.4,33.6
      			c0,3.7,0.4,7.2,1.3,10.4c1.5,5.9,4.4,10.8,8.2,14.5c5,4.9,11.6,8,19.1,8.7c1.2,0.1,2.5,0.2,3.8,0.2c10.5,0,18.7-4.6,24.2-11.1
      			c0.7-0.8,1.3-1.6,1.8-2.4L108.7,155.2z"
            />
            <path
              class="st0"
              d="M239.9,59.4v42.5c-2.6-0.6-6.3-1.2-10.9-1.2c-11.5,0-26.7,4.9-32.4,12.6v88.3h-44.2V63.1h44.2V80
      			C205.8,68.8,223.3,59.4,239.9,59.4z"
            />
            <path
              class="st0"
              d="M381.7,181.7c-9.3,9.7-21.1,16.9-34.5,20.4l0.7-0.1L381.7,181.7z"
            />
            <path
              class="st0"
              d="M539.8,92.8c-8.7-26-34.4-34.1-61.4-34.1c-21.2,0-45,6.3-62.8,21.5l7.2,12.6l8.6,15.2
      			c11.2-9.5,25.5-14.6,39.3-14.6c17.8,0,28.1,8,28.1,20.1v16.6c-8.3-10.3-24.7-16.1-43-16.1c-7.1,0-14.8,1.2-21.9,4.1
      			c-14,5.7-25.7,18-25.7,40.3c0,24.8,16.7,39,34.1,43.8c0.7,0.2,1.4,0.4,2.1,0.5c3.8,0.9,7.7,1.3,11.4,1.3c4.3,0,8.5-0.4,12.5-1.2
      			c1.8-0.3,3.5-0.7,5.2-1.2c10.6-2.8,19.6-8.1,25.2-14.9v13.8h44.1V114C542.9,105.9,541.8,98.8,539.8,92.8z M498.8,165.1
      			c-4.6,6.6-14.9,10-24.7,10c-11.8,0-22.1-5.2-22.1-16.1c0-10.9,10.3-16.1,22.1-16.1c9.8,0,20.1,3.4,24.7,9.8V165.1z"
            />
            <path
              class="st0"
              d="M605.3,201.1c-5.9-2.5-10.7-6.2-14.1-11.1C595.1,194.7,599.9,198.5,605.3,201.1z"
            />
            <path
              class="st0"
              d="M656.2,101.5h-28.1v19.6c-1.4-0.1-2.8-0.2-4.2-0.2c-18.2,0-33.7,11.5-39.6,27.5v-46.9h-22.9V63.1h22.9V25.2
      			h43.9v37.9h28.1V101.5z"
            />
            <path
              class="st0"
              d="M660.2,195.9c-2.8,2.6-6.9,4.9-12.4,6.6c-5.1,1.5-11.3,2.5-18.7,2.6c12-1.5,22.4-7.9,29.1-17.2L660.2,195.9z"
            />
            <path
              class="st0"
              d="M725.5,26.2c0,14-11.2,25.5-25.2,25.5s-25.2-11.5-25.2-25.5S686.3,1,700.3,1S725.5,12.2,725.5,26.2z"
            />
            <polygon
              class="st0"
              points="891.5,63.1 879.4,93.8 873.7,108.5 837,201.6 790,201.6 760.2,125.9 747.6,93.8 735.6,63.1 782,63.1
      			792.9,93.8 802.1,119.5 813.2,150.9 825.8,115.8 833.8,93.8 844.8,63.1 		"
            />
            <path
              class="st0"
              d="M939.8,116.6c1.4-8,6.3-18.3,18-22.2c3-1,6.5-1.6,10.4-1.6c20.3,0,27.5,14.1,28.7,23.8H939.8z M968.2,204l2,0
      			c21.2,0,44.1-6,57.9-18.4l-18.6-27.5c-7.7,7.5-24.6,11.8-34.4,11.8c-20.1,0-32.1-11.8-34.7-24.7h98.6v-9.5
      			c0-47-29.8-77.2-70.8-77.2c-28.1,0-50.7,13.6-63.2,34.1c-2,3.3-3.8,6.8-5.2,10.5c-3.4,8.6-5.3,18-5.3,27.9
      			c0,44.3,31.8,71.9,73.5,72.8L968.2,204z"
            />
          </g>
        </g>
        <polyline
          class="st0"
          points="678.2,201.4 678.2,63.1 722.3,63.1 722.3,201.4 "
        />
        <path
          class="st0"
          d="M395.3,135.8c0-10-1.3-19.2-3.8-27.5c-1.7-5.6-3.9-10.8-6.6-15.5c-12.1-21.6-33.9-34.1-60.4-34.1
      	c-9.1,0-17.7,1.4-25.5,4.1c-25.9,11.5-43.9,37.5-43.9,67.8c0,37.8,28.1,69,64.5,73.5c3,0.4,6,0.5,9,0.5c6.4,0,12.7-0.8,18.6-2.4
      	c13.3-3.5,25.2-10.7,34.5-20.4l-15.9-23.5c-7.7,7.5-24.7,11.8-34.4,11.8c-20.1,0-32.1-11.8-34.7-24.7h98.6V135.8z M296.1,116.6
      	c1.7-10,9.2-23.8,28.4-23.8c6.4,0,11.5,1.4,15.5,3.6c8.7,4.8,12.4,13.5,13.1,20.2H296.1z"
        />
        <path
          class="st0"
          d="M658.1,187.8c-6.7,9.3-17.1,15.8-29.1,17.2h0c-1.7,0.2-3.4,0.3-5.2,0.3c-6.6,0-12.9-1.5-18.5-4.2
      	c-5.5-2.7-10.3-6.5-14.1-11.1c0,0,0,0,0-0.1c-4.6-6.5-7-15.1-7-25.6v-15.9c6-16.1,21.4-27.5,39.6-27.5c1.4,0,2.8,0.1,4.2,0.2V152
      	c0,7.1,3.6,12.6,9.8,13.8c0.8,0.1,1.6,0.2,2.5,0.2c4.9,0,9.7-1.7,11.2-3.4l1.9,7.4L658.1,187.8z"
        />
      </svg>
</div>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.3/TweenMax.min.js'></script>
<script src='https://robindelaporte.fr/codepen/bundle.js'></script>
      <script>
var vertex = `
		attribute vec2 uv;
		attribute vec2 position;
		varying vec2 vUv;
		void main() {
				vUv = uv;
				gl_Position = vec4(position, 0, 1);
		}
`;
var fragment = `
		precision highp float;
		precision highp int;
		uniform sampler2D tWater;
		uniform sampler2D tFlow;
		uniform float uTime;
		varying vec2 vUv;
		uniform vec4 res;
		uniform vec2 img;

		vec2 centeredAspectRatio(vec2 uvs, vec2 factor){
				return uvs * factor - factor /2. + 0.5;
		}

		void main() {

			// R and G values are velocity in the x and y direction
			// B value is the velocity length
			vec3 flow = texture2D(tFlow, vUv).rgb;

			vec2 uv = .5 * gl_FragCoord.xy / res.xy ;

			// vec2 uv = .5 * gl_FragCoord.xy / res.xy ;
			vec2 myUV = (uv - vec2(0.5))*res.zw + vec2(0.5);
			myUV -= flow.xy * (0.15 * 1.2);

			vec2 myUV2 = (uv - vec2(0.5))*res.zw + vec2(0.5);
			myUV2 -= flow.xy * (0.125 * 1.2);

			vec2 myUV3 = (uv - vec2(0.5))*res.zw + vec2(0.5);
			myUV3 -= flow.xy * (0.10 * 1.4);

			vec3 tex = texture2D(tWater, myUV).rgb;
			vec3 tex2 = texture2D(tWater, myUV2).rgb;
			vec3 tex3 = texture2D(tWater, myUV3).rgb;

			gl_FragColor = vec4(tex.r, tex2.g, tex3.b, 1.0);
		}
`;
{
  var _size = [2048, 1638];
  var renderer = new ogl.Renderer({ dpr: 2 });
  var gl = renderer.gl;
  document.body.appendChild(gl.canvas);

  // Variable inputs to control flowmap
  var aspect = 1;
  var mouse = new ogl.Vec2(-1);
  var velocity = new ogl.Vec2();
  function resize() {
    gl.canvas.width = window.innerWidth * 2.0;
    gl.canvas.height = window.innerHeight * 2.0;
    gl.canvas.style.width = window.innerWidth + "px";
    gl.canvas.style.height = window.innerHeight + "px";

    var a1, a2;
    var imageAspect = _size[1] / _size[0];
    if (window.innerHeight / window.innerWidth < imageAspect) {
      a1 = 1;
      a2 = window.innerHeight / window.innerWidth / imageAspect;
    } else {
      a1 = window.innerWidth / window.innerHeight * imageAspect;
      a2 = 1;
    }
    mesh.program.uniforms.res.value = new ogl.Vec4(
    window.innerWidth,
    window.innerHeight,
    a1,
    a2);


    renderer.setSize(window.innerWidth, window.innerHeight);
    aspect = window.innerWidth / window.innerHeight;
  }
  var flowmap = new ogl.Flowmap(gl, {
    falloff: 0.3,
    dissipation: 0.92,
    alpha: 0.5 });

  // Triangle that includes -1 to 1 range for 'position', and 0 to 1 range for 'uv'.
  var geometry = new ogl.Geometry(gl, {
    position: {
      size: 2,
      data: new Float32Array([-1, -1, 3, -1, -1, 3]) },

    uv: { size: 2, data: new Float32Array([0, 0, 2, 0, 0, 2]) } });

  var texture = new ogl.Texture(gl, {
    minFilter: gl.LINEAR,
    magFilter: gl.LINEAR });

  var img = new Image();
  img.onload = () => texture.image = img;
  img.crossOrigin = "Anonymous";
  img.src = "https://robindelaporte.fr/codepen/bg3.jpg";

  var a1, a2;
  var imageAspect = _size[1] / _size[0];
  if (window.innerHeight / window.innerWidth < imageAspect) {
    a1 = 1;
    a2 = window.innerHeight / window.innerWidth / imageAspect;
  } else {
    a1 = window.innerWidth / window.innerHeight * imageAspect;
    a2 = 1;
  }

  var program = new ogl.Program(gl, {
    vertex,
    fragment,
    uniforms: {
      uTime: { value: 0 },
      tWater: { value: texture },
      res: {
        value: new ogl.Vec4(window.innerWidth, window.innerHeight, a1, a2) },

      img: { value: new ogl.Vec2(_size[1], _size[0]) },
      // Note that the uniform is applied without using an object and value property
      // This is because the class alternates this texture between two render targets
      // and updates the value property after each render.
      tFlow: flowmap.uniform } });


  var mesh = new ogl.Mesh(gl, { geometry, program });

  window.addEventListener("resize", resize, false);
  resize();

  // Create handlers to get mouse position and velocity
  var isTouchCapable = ("ontouchstart" in window);
  if (isTouchCapable) {
    window.addEventListener("touchstart", updateMouse, false);
    window.addEventListener("touchmove", updateMouse, { passive: false });
  } else {
    window.addEventListener("mousemove", updateMouse, false);
  }
  var lastTime;
  var lastMouse = new ogl.Vec2();
  function updateMouse(e) {
    e.preventDefault();

    if (e.changedTouches && e.changedTouches.length) {
      e.x = e.changedTouches[0].pageX;
      e.y = e.changedTouches[0].pageY;
    }
    if (e.x === undefined) {
      e.x = e.pageX;
      e.y = e.pageY;
    }
    // Get mouse value in 0 to 1 range, with y flipped
    mouse.set(e.x / gl.renderer.width, 1.0 - e.y / gl.renderer.height);
    // Calculate velocity
    if (!lastTime) {
      // First frame
      lastTime = performance.now();
      lastMouse.set(e.x, e.y);
    }

    var deltaX = e.x - lastMouse.x;
    var deltaY = e.y - lastMouse.y;

    lastMouse.set(e.x, e.y);

    var time = performance.now();

    // Avoid dividing by 0
    var delta = Math.max(10.4, time - lastTime);
    lastTime = time;
    velocity.x = deltaX / delta;
    velocity.y = deltaY / delta;
    // Flag update to prevent hanging velocity values when not moving
    velocity.needsUpdate = true;
  }
  requestAnimationFrame(update);
  function update(t) {
    requestAnimationFrame(update);
    // Reset velocity when mouse not moving
    if (!velocity.needsUpdate) {
      mouse.set(-1);
      velocity.set(0);
    }
    velocity.needsUpdate = false;
    // Update flowmap inputs
    flowmap.aspect = aspect;
    flowmap.mouse.copy(mouse);
    // Ease velocity input, slower when fading out
    flowmap.velocity.lerp(velocity, velocity.len ? 0.15 : 0.1);
    flowmap.update();
    program.uniforms.uTime.value = t * 0.01;
    renderer.render({ scene: mesh });
  }
}
    </script>
</body>
</html>

10. Paper Cut Text Effect

Made by Yoav Kadosh. Source

<!DOCTYPE html>
<html lang="en" >
<head>
  <title></title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
<style>
@import url("https://fonts.googleapis.com/css2?family=Raleway:[email protected]&display=swap");
body, html {
  height: 100%;
  width: 100%;
}

body {
  font-family: "Raleway", sans-serif;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #eaece5;
}

.text {
  font-size: 8em;
  position: relative;
  text-transform: full-width;
  display: flex;
}
.text .letter {
  position: relative;
  display: flex;
}
.text .letter .source {
  color: gray;
  -webkit-text-stroke: 0.01em rgba(0, 0, 0, 0.3);
  display: flex;
}
.text .letter .overlay, .text .letter .shadow {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;
  user-select: none;
}
.text .letter .overlay {
  background-image: linear-gradient(90deg, white 50%, #eff0eb);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  transform: rotateY(-30deg) skew(0, -10deg);
  transform-origin: left;
  animation: overlay 3s infinite ease-out var(--delay);
}
.text .letter .shadow {
  filter: blur(5px);
  background-image: linear-gradient(90deg, rgba(0, 0, 0, 0.4) 30%, transparent);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  transform: skew(0, 20deg) translateY(0.1em) translateX(0.05em);
  animation: shadow 3s infinite var(--delay);
}

@keyframes shadow {
  0%, 20%, 100% {
    transform: skew(0, 20deg) translateY(0.1em) translateX(0.05em);
    opacity: 1;
  }
  10% {
    transform: skew(0, 0) translateY(0) translateX(0);
    opacity: 0;
  }
}
@keyframes overlay {
  0%, 20%, 100% {
    transform: rotateY(-30deg) skew(0, -10deg);
  }
  10% {
    transform: rotateY(0deg) skew(0, 0);
  }
}
</style>
</head>
<body>
      <script type="module">
import React from 'https://cdn.skypack.dev/react';
import ReactDOM from 'https://cdn.skypack.dev/react-dom';

const Text = ({ value }) => /*#__PURE__*/
React.createElement("div", { className: "text" },
value.split('').map((char, i) => /*#__PURE__*/
React.createElement("div", { className: "letter", style: { '--delay': `${i * 0.2}s` } }, /*#__PURE__*/
React.createElement("span", { className: "source" }, char), /*#__PURE__*/
React.createElement("span", { className: "shadow" }, char), /*#__PURE__*/
React.createElement("span", { className: "overlay" }, char))));





const App = () => /*#__PURE__*/
React.createElement("div", { className: "app" }, /*#__PURE__*/
React.createElement(Text, { value: "PAPER" }), /*#__PURE__*/
React.createElement(Text, { value: "CUT!" }));


ReactDOM.render( /*#__PURE__*/
React.createElement(App, null),
document.body);
    </script>
</body>
</html>

11. Animated Text Effect

Made by Galen Strasen. Source

<!DOCTYPE html>
<html lang="en" >
<head>
  <title></title>
<style>
body {
  font-size: 100%;
  font-family: Calibri, sans-serif;
  line-height: 1;
  margin: 0;
  width: 100%;
  height: 100vh;
  display: table;
  background: #131300;
}

.center {
  display: table-cell;
  vertical-align: middle;
  text-align: left;
}

h1 {
  font-size: 60px;
  color: #C59B76;
  margin-left: 10%;
}

.word-wrapper {
  position: relative;
}

.word-wrapper b {
  position: absolute;
  left: 0;
  color: #E9806E;

}

.word-wrapper b.visible {
  position: relative;
}

.word-wrapper b i:nth-of-type(2){
  animation-delay: .05s;
}

.word-wrapper b i:nth-of-type(3){
  animation-delay: .1s;
}

.word-wrapper b i:nth-of-type(4){
  animation-delay: .15s;
}

.word-wrapper i:nth-of-type(5){
  animation-delay: .2s;
}

.word-wrapper b i:nth-of-type(6){
  animation-delay: .25s;
}

.word-wrapper b i:nth-of-type(7){
  animation-delay: .3s;
}

.word-wrapper b i:nth-of-type(8){
  animation-delay: .35s;
}

.word-wrapper b i:nth-of-type(9){
  animation-delay: .4s;
}

.word-wrapper b i:nth-of-type(10){
  animation-delay: .45s;
}

.word-wrapper b i:nth-of-type(11){
  animation-delay: .5s;
}

.word-wrapper b i:nth-of-type(12){
  animation-delay: .55s;
}

.word-wrapper b i:nth-of-type(13){
  animation-delay: .6s;
}


.word-wrapper i {
  font-style: normal;
  opacity: 0;
  transform: scale(0);
  animation-duration: .6s;
  animation-fill-mode: backwards;
}

.word-wrapper .visible i {
  opacity: 1;
  transform: scale(1);
  animation-name: scale-up;
}

.word-wrapper .hidden i {
  animation-name: scale-down;
}

/* This animates individual letters of word */
@keyframes scale-up {
  0% {
    opacity: 0;
    transform: scale(0);
  }
  
  60% {
    transform: scale(1.2); /* this creates bounce effect */
  }
  
  100% {
    opacity: 1;
    transform: scale(1);
  }
}

@keyframes scale-down {
  0% {
    opacity: 1;
    transform: scale(1);
  }
  100% {
    opacity: 0;
    transform: scale(0);
  }
}
</style>
</head>
<body>
  <section class="center">
  <h1>
    <span>I wish I lived in</span>
    <span class="word-wrapper">
      <b class="visible">
        <i>O</i><i>a</i><i>k</i><i>l</i><i>a</i><i>n</i><i>d</i>
      </b>
      <b>
        <i>J</i><i>a</i><i>c</i><i>k</i><i>s</i><i>o</i><i>n</i><i> </i><i>H</i><i>o</i><i>l</i><i>e</i>
      </b>
      <b>
        <i>N</i><i>e</i><i>w</i><i> </i><i>Y</i><i>o</i><i>r</i><i>k</i><i> </i><i>C</i><i>i</i><i>t</i><i>y</i>
      </b>
    </span>
  </h1>
</section>
      <script>
var intervalID = setInterval(function () {
  // every 4 seconds execute following
  var visibleWord = document.getElementsByClassName('visible')[0],
  nextWord = visibleWord.nextSibling;
  // check if nextSibling is textnode (whitespace) - if so get next next sibling. 
  if (nextWord.nodeType == 3) nextWord = nextWord.nextSibling;
  // if there is a next node 
  if (!(nextWord == null)) {
    visibleWord.setAttribute('class', 'hidden');
    nextWord.setAttribute('class', 'visible');
  } else {
    clearInterval(intervalID);
  }
}, 4000);
    </script>
</body>
</html>