Look ma! No H(TML)andlebars... or JS Typed.js ported entirely to CSS (SCSS)
A Pen by Brandon McConnell on CodePen.
// Love dynamically typed text? You're gonna love this | |
// Edit these strings to see them typed on the screen: | |
$strings: ( | |
"CSS typed this string!" | |
"It typed this one too 😱" | |
"Enjoy ☕" | |
); | |
// now for some timing (in seconds) | |
$durCharFwd: 0.10; // character typed | |
$durFullGap: 2.00; // time between typed/delete | |
$durCharBwd: 0.08; // character deleted | |
$durDoneGap: 1.00; // time between strings | |
// initializing some variables and functions ✊🏼 | |
$charCount: 0; $durTotal: 0; | |
@each $string in $strings { | |
$charCount: $charCount + str-length($string); | |
$durTotal: $durTotal | |
+ (str-length($string) * ($durCharFwd + $durCharBwd)) | |
+ $durFullGap + $durDoneGap; | |
} | |
@function percent($string, $letter, $modifier) { | |
$stringsPast: $string - 1; $time: 0; | |
@while $stringsPast > 0 { | |
$time: $time | |
+ (($durCharFwd + $durCharBwd) * (str-length(nth($strings, $stringsPast)))) | |
+ $durFullGap + $durDoneGap; | |
$stringsPast: $stringsPast - 1; | |
} | |
@if $letter <= str-length(nth($strings, $string)) { | |
$time: $time | |
+ ($durCharFwd * ($letter - 1)); | |
} @else { | |
$time: $time | |
+ ($durCharFwd * str-length(nth($strings, $string))) | |
+ $durFullGap | |
+ ($durCharBwd * ($letter - str-length(nth($strings, $string)))); | |
} | |
@return ($time / $durTotal * 100 + $modifier) + "%"; | |
} | |
$currentPercentage: 0; | |
// now THIS is where the magic happens... ✨ | |
@keyframes typed { | |
@for $i from 1 through length($strings) { | |
// @for $j from 1 through (str-length(nth($strings, $i)) * 2 - 1) { | |
@for $j from 1 through (str-length(nth($strings, $i)) * 2) { | |
/* string #{$i}, char #{$j} */ | |
@if $j < str-length(nth($strings, $i)) * 2 { // not last character deleted | |
#{percent($i, $j, 0)}, #{percent($i, $j+1, -0.001)} { | |
@if $j <= str-length(nth($strings, $i)) { | |
content: quote(#{str_slice(nth($strings, $i), 1, $j)}); | |
} @else { | |
content: quote(#{str_slice(nth($strings, $i), 1, str-length(nth($strings, $i)) - ($j - str-length(nth($strings, $i))))}); | |
} | |
} | |
} @else { | |
@if $i < length($strings) { // not last string | |
#{percent($i, $j, 0)}, #{percent($i+1, 1, -0.001)} { | |
content: ""; // zero-width space to retain element height | |
} | |
} @else { // last string | |
#{percent($i, $j, 0)}, 100% { | |
content: ""; // zero-width space to retain element height | |
} | |
} | |
} | |
} | |
} | |
} | |
@keyframes beam-blink { | |
75% { border-color: transparent; } | |
} | |
* { backface-visibility: hidden; } | |
html, body { height: 100%; } | |
body { | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
background-color: #000; | |
background-image: // skeuomorphism anyone? | |
radial-gradient(rgba(#fff, 0.125), rgba(#fff, 0)), | |
linear-gradient(to bottom, #000, #000 2px, #111 3px); | |
background-repeat: repeat-y; | |
background-position: center center; | |
background-size: cover, 100% 3px; | |
font-size: calc(10px + 2vw); | |
font-family: 'VT323', monospace, sans-serif; | |
color: #3f3; // hacker green | |
-webkit-font-smoothing: antialiased; | |
-moz-osx-font-smoothing: grayscale; | |
&::after { | |
content: ""; // zero-width space to retain element height | |
position: relative; | |
top: -13px; | |
@media (max-width: 575px) { top: -33px; } | |
display: inline-block; | |
padding-right: 3px; | |
padding-right: calc(3px + 0.1vw); | |
border-right: 10px solid rgba(#3f3, 0.75); | |
border-right: calc(1.1vw + 4px) solid rgba(#3f3, 0.75); | |
text-shadow: 0 0 5px rgba(51, 255, 51, 0.75); | |
white-space: nowrap; | |
animation: typed #{$durTotal + "s"} linear 1s infinite, beam-blink 1s infinite; | |
} | |
&::before { // just generating some useful stats here 👋🏼 | |
content: "#{length($strings)} strings / #{$charCount} chars / #{$durTotal}s duration"; | |
@media (max-width: 575px) { | |
content: "#{length($strings)} strings \A #{$charCount} chars \A #{$durTotal}s duration"; | |
} | |
display: block; | |
position: absolute; | |
bottom: 0; | |
width: 100%; | |
padding: 3px 0; | |
background: #00f; // aquaman blue | |
color: #fff; // Brandon-McConnell white | |
text-align: center; | |
font-size: 18px; | |
letter-spacing: 0.7px; | |
white-space: pre-wrap; | |
} | |
} | |
// body[onload] { | |
// &::before, &::after { display: none !important; } | |
// background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/1580009/codepen_css-typed-this.png) center / cover; | |
// } |
<link href="https://fonts.googleapis.com/css?family=VT323" rel="stylesheet" /> |
Look ma! No H(TML)andlebars... or JS Typed.js ported entirely to CSS (SCSS)
A Pen by Brandon McConnell on CodePen.