A client came to me recently with a “branding emergency.” They wanted their new landing page to have that high-energy 1950s Hanna-Barbera look, and their solution was a 4MB transparent PNG for every header. The site crawled. Worse, none of that toon text typography was actual text, so search engines saw a page with no headings on it. I told them to put the Photoshop brushes away and let CSS do it.
My first instinct was a heavy font with a standard text-shadow on it. It looked okay and completely flat, nothing like the “punch” of a hand-painted title card. That depth comes from layering several shadows at different offsets rather than settling for one. I got into this after a series on Smashing Magazine about how classic cartoons feed into modern CSS.
Layered CSS for toon text typography
That “Yuk-Yuk Duck” look comes from combining several shadows with different blurs. One hard shadow on its own reads like a 2005 WordArt project, and there is no limit on how many you stack. I start with a solid sharp shadow for the lift, then add softer semi-transparent layers over it for light diffusion.
.bbioon-toon-header {
color: #f7f76d;
text-shadow:
5px 5px 0 #1e1904,
0 0 15px rgba(233, 206, 150, 0.5);
}
Then there is text-stroke. Anyone who has tried a thick outline on a font in CSS knows it eats the inside of the letters, and for a long time I assumed SVG filters were the only way out. Then I remembered paint-order. Set it to stroke and the browser draws the outline first, then paints the fill over it, which keeps the glyphs sharp even at a 10px border.
.bbioon-thick-outline {
-webkit-text-stroke: 6px #7890b5;
paint-order: stroke;
color: #eff0cd;
}
Character splitting and the jiggle effect
To sell the effect the text has to “move” as if it were hand-drawn, which means every letter needs its own timing. I have watched devs wrap each letter in a <span> tag by hand, and it turns into a maintenance disaster. I use a small script, call it bbioon-splinter, to do the splitting and keep the markup readable to screen readers. Put aria-label on the parent and aria-hidden on the spans. Skip that and you have shipped a heading no assistive tech can read.
With the letters split, I add a subtle jiggle animation on staggered delays. Keep the rotation small. Past about 4 degrees, people start to feel seasick looking at your header.
@keyframes bbioon_jiggle {
0%, 100% { transform: rotate(-2deg); }
50% { transform: rotate(2deg); }
}
.bbioon-char:nth-child(even) {
animation: bbioon_jiggle 0.5s infinite alternate;
}
Most of it is already in the spec
Giving a design “character” rarely needs a big library or a heavy asset. Most of what you want sits in the CSS spec already, and the work is knowing which properties to stack. Clipping a gradient background to your text, shifting baselines with nth-child, either way the browser does the rendering instead of your build pipeline.
CSS like this gets fiddly fast. If you are tired of debugging someone else’s mess and you just want the site to work, drop my team a line. We have probably seen it before.
If your branded headings are still a folder of PNGs, most of that can move into CSS.