Revision of Twine: apply CSS to individual characters from Fri, 08/16/2013 - 10:58

This script causes every single character in passages to be wrapped in a <span class="char"> element. This enables a number of mildly interesting CSS effects.

Note: in some versions of Twine, this won't take effect in the Start passage!

Javascript code is as follows:

Wikifier.formatters.push({name:"char",match:".",handler:function(a){insertElement(a.output,"span",null,"char "+(a.matchText===" " ? "space" : a.matchText),a.matchText);
}});Wikifier.formatters.forEach(function(e){if(e.name=="emdash"){e.handler=function(a){var b=insertElement(a.output,"span",null,"char",String.fromCharCode(8212));
};}else{if(e.name=="prettyLink"){e.handler=function(a){var b=new RegExp(e.lookahead,"mg");
b.lastIndex=a.matchStart;var c=b.exec(a.source);if(c&&c.index==a.matchStart&&c[2]){var d=Wikifier.createInternalLink(a.output,c[1]);
setPageElement(d,null,c[1]);a.nextMatch+=c[1].length+2;}else{if(c&&c.index==a.matchStart&&c[3]){var f;
if(tale.has(c[4])){f=Wikifier.createInternalLink(a.output,c[4]);}else{f=Wikifier.createExternalLink(a.output,c[4]);
}setPageElement(f,null,c[1]);a.nextMatch=c.index+c[0].length;}}};}}});

These characters have the class of "char", and also a class equal to themselves ("a" for the letter "a", "2" for "2", etc.) It's recommended that you use the :nth-child pseudo-class to select them. Some potential CSS effects that can be performed include the following (examples only):

Horizontally spin characters on mouseover:

.char:not(.space):hover {
  transform: rotateY(720deg);
  -webkit-transform: rotateY(720deg);
}
.char:not(.space) {
  display: inline-block;
  transition: transform 2s ease-out;
  -webkit-transition: -webkit-transform 2s ease-out;
}

Wavy text:

 .char{ position:relative; }
.char:nth-child(8n) { top:0px; }
.char:nth-child(8n+1) { top:-1px; }
.char:nth-child(8n+2) { top:-1.5px; }
.char:nth-child(8n+3) { top:-1px; }
.char:nth-child(8n+4) { top:-0px; }
.char:nth-child(8n+5) { top: 1px; }
.char:nth-child(8n+6) { top: 1.5px; }
.char:nth-child(8n+7) { top: 1px; }

Animated wavy text:

.passage {
  font-size: 3em;
}
.char { 
  position:relative;
}
.char:nth-child(8n) { 
  animation: wavetext 4s 0s infinite;
  -webkit-animation: wavetext 4s 0s infinite;
}
.char:nth-child(8n+1) { 
  animation: wavetext 4s -0.5s infinite;
  -webkit-animation: wavetext 4s -0.5s infinite;
}
.char:nth-child(8n+2) { 
  animation: wavetext 4s -1s infinite;
  -webkit-animation: wavetext 4s -1s infinite;
}
.char:nth-child(8n+3) { 
  animation: wavetext 4s -1.5s infinite;
  -webkit-animation: wavetext 4s -1.5s infinite;
}
.char:nth-child(8n+4) { 
  animation: wavetext 4s -2s infinite;
  -webkit-animation: wavetext 4s -2s infinite;
}
.char:nth-child(8n+5) { 
  animation: wavetext 4s -2.5s infinite;
  -webkit-animation: wavetext 4s -2.5s infinite;
}
.char:nth-child(8n+6) { 
  animation: wavetext 4s -3s infinite;
  -webkit-animation: wavetext 4s -3s infinite;
}
.char:nth-child(8n+7) { 
  animation: wavetext 4s -3.5s infinite;
  -webkit-animation: wavetext 4s -3.5s infinite;
}
@keyframes wavetext {
  0%, 100% { top: 0em; } 50% { top: 0.5em; }
}
@-webkit-keyframes wavetext {
  0%, 100% { top: 0em; } 50% { top: 0.5em; }
}

Rapid rainbow text:

.char:nth-child(8n) { color:hsl(45,100%,75%); }
.char:nth-child(8n+1) {color:hsl(90,100%,75%); }
.char:nth-child(8n+2) {color:hsl(135,100%,75%); }
.char:nth-child(8n+3) {color:hsl(180,100%,75%); }
.char:nth-child(8n+4) {color:hsl(225,100%,75%); }
.char:nth-child(8n+5) {color:hsl(270,100%,75%); }
.char:nth-child(8n+6) {color:hsl(315,100%,75%); }
.char:nth-child(8n+7) {color:hsl(0,100%,75%); }

Illuminate letters on mouseover

.char { 
  transition: all 5s; -webkit-transition: all 5s;
  opacity: 0.4;
}
.char:hover {
  transition: all 0.1s; -webkit-transition: all 0.1s;
  opacity:1;
  text-shadow: 0 0 1em white;
}

Erase text on mouseover

.char { 
  transition: opacity 999s step-end; -webkit-transition: opacity 999s step-end;
}
.char:hover {
  opacity:0;
  transition: opacity 1ms; -webkit-transition: opacity 1ms;
}

Remove all the T's in the passage text:
.char.t {
  display:none;
}

Change "u" to "U":

.char.u {
  visibility:hidden;
}
.char.u::before {
  content: "U";
  position:absolute;
  visibility:visible;
}

These are to be considered basic examples - prompts for more practical uses.

This code also enables some particularly interesting Javascript visual effects to be performed, which I shall explore in a future blog post.

Feel free to report any bugs to @webbedspace.

AttachmentSize
Myriad-lighttouch.html100.42 KB
TwineCSS-colourwave.html101.5 KB
Myriad-wavytext.html101.33 KB
Myriad-crumbletext.html103.48 KB
pensive-mosquitoes