Skip to main content
ShiveringCactus
Community Expert
Community Expert
Sep 12, 2026 2:00 PM UTC
Answered

Bake in Text Styling expression

I’ve an interesting issue.  I have spent a bit of time recreating the look of AE’s expression editor as a Per Character styling expression.  It’s not complete yet, but serves my purposes… but the per-frame render time add 5s each frame.  And rendering out a 90 second sequence took 90 minutes.

 

I’m wondering if there’s a way to bake the expression styling once done.

 

Here’s the code if anyone wants to experiment:

///// HEX COLOR CONFIGURATION //////
var hexBase = "#D4D4D4"; // Off-white
var hexBlue = "#3E8FE1"; // Blue (Keywords)
var hexLtBlue = "#48D9FD"; // Light Blue (Numbers)
var hexPink = "#F67476"; // Pink (Strings)
var hexYellow = "#9D9039"; // Yellow (Brackets)
var hexLightYellow = "#DCBE84"; // Yellow (reserved terms)
var hexGreen = "#6A9955"; // Green (Comments)
var hexCursor = "#FFFFFF"; // White (Cursor)

///// Convert Hex to AE-friendly RGB [0,1]
function hexToRgb(hex) {
var r = parseInt(hex.slice(1, 3), 16) / 255;
var g = parseInt(hex.slice(3, 5), 16) / 255;
var b = parseInt(hex.slice(5, 7), 16) / 255;
return [r, g, b, 1];
}

//// TYPEWRITER & CURSOR LOGIC
var fullText = value;
var typeProgress = effect("Typewriter")("Slider");
var charCount = Math.floor(typeProgress);
var currentText = fullText.substring(0, charCount);

var cursorChar = "|";
const blinkSpeed = 2.5;
const isVisible = Math.floor(time * blinkSpeed) % 2 === 0;
if (effect("Show Cursor")("Checkbox") == 0) {
cursorChar = "";
}

//// Add cursor to the currently typed text
var finalDisplay = isVisible ? currentText + cursorChar : currentText + " ";

//// the Style object
var outText = createStyle().setText(finalDisplay).setFillColor(hexToRgb(hexBase));

//// Colour logic

// Blue Keywords
["var", "let", "const", "if", "Math", "continue", "push", "min", "sqrt", "else", "return", "function", "true", "false", "continue", "return", "length", "sin", "cos", "tan"].forEach(word => {
const regex = new RegExp(`\\b${word}\\b`, "g");
let m;
while ((m = regex.exec(currentText)) !== null) {
outText = outText.setFillColor(hexToRgb(hexBlue), m.index, word.length);
}
});



/// Yellow Brackets/Punctuation
const punctRegex = /[\[\]\{\}\(\)\=\<\>\\.\;]/g;
let p;
while ((p = punctRegex.exec(currentText)) !== null) {
outText = outText.setFillColor(hexToRgb(hexYellow), p.index, 1);
}
// Yellow Brackets/Punctuation
["thisComp", "layer", "isClosed", "inTangents", "createPath", "value", "outTangents", "frameDuration", "time", "effect", "thisProperty", "length", "linear","degreesToRadians"].forEach(word => {
const ReservedRegex = new RegExp(`\\b${word}\\b`, "g");
let r;
while ((r = ReservedRegex.exec(currentText)) !== null) {
outText = outText.setFillColor(hexToRgb(hexLightYellow), r.index, word.length);
}
});

/////// Pink Strings
const stringRegex = /"(.*?)"|'(.*?)'/g;
let s;
while ((s = stringRegex.exec(currentText)) !== null) {
outText = outText.setFillColor(hexToRgb(hexPink), s.index, s[0].length);
}

// Green Comments
const commentRegex = /\/\/.*/g;
let c;
while ((c = commentRegex.exec(currentText)) !== null) {
outText = outText.setFillColor(hexToRgb(hexGreen), c.index, c[0].length);
}

// Light Blue Numbers
const numRegex = /\d+/g;
let n;
while ((n = numRegex.exec(currentText)) !== null) {
outText = outText.setFillColor(hexToRgb(hexLtBlue), n.index, n[0].length);
}

////// style for cursor
if (isVisible) {
outText.setFillColor(hexToRgb(hexCursor), currentText.length, 1);
}

outText

 

​@Nishu Kushwaha - what’s the code style I should choose to make the forum code look like AE?  EDIT: Oh, it updates on saving.

    David.Arbor
    David.ArborCorrect answer
    Community Manager
    Sep 30, 2026 4:44 PM UTC

    Yup, this is definitely going to get slow because you’re constantly evaluating the text block as it reveals each new character. 

    If you want to bake the styling first, I would suggest splitting this on two layers and adding `posterizeTime(0);` to the first line, so the styling expression evaluates only one time (scrub the CTI before and after doing this and you’ll see a huge perf improvement.

    AE also ships with a preset called Blinking Cursor Typewriter Console which is almost perfect for what you need. By default, the preset works on a single text layer, and the way it reveals text won’t copy the styling, even if you reference an already styled text layer.

    However, I’ve attached a .aep where I modified the setup a bit.

    1. On the Blinking Cursor layer, I modified the expression to reference the SourceText layer.
    2. On the SourceText layer (the stylized one), I added an Opacity animator and linked its Offset parameter to the Blinking Cursor’s animation. This lets the stylized text reveal at the same rate you set for the preset.
    3. I added another Opacity animator to the Blinking Cursor layer and set it to 0%. This hides the plain text.

    So you’re left with two linked layers where one styles the text and the other animates the cursor. 

    Does this work for you?

     

    -David, After Effects Engineering Team 

    3 replies

    David.Arbor
    Community Manager
    David.ArborCommunity ManagerCorrect answer
    Community Manager
    Sep 30, 2026 4:44 PM UTC

    Yup, this is definitely going to get slow because you’re constantly evaluating the text block as it reveals each new character. 

    If you want to bake the styling first, I would suggest splitting this on two layers and adding `posterizeTime(0);` to the first line, so the styling expression evaluates only one time (scrub the CTI before and after doing this and you’ll see a huge perf improvement.

    AE also ships with a preset called Blinking Cursor Typewriter Console which is almost perfect for what you need. By default, the preset works on a single text layer, and the way it reveals text won’t copy the styling, even if you reference an already styled text layer.

    However, I’ve attached a .aep where I modified the setup a bit.

    1. On the Blinking Cursor layer, I modified the expression to reference the SourceText layer.
    2. On the SourceText layer (the stylized one), I added an Opacity animator and linked its Offset parameter to the Blinking Cursor’s animation. This lets the stylized text reveal at the same rate you set for the preset.
    3. I added another Opacity animator to the Blinking Cursor layer and set it to 0%. This hides the plain text.

    So you’re left with two linked layers where one styles the text and the other animates the cursor. 

    Does this work for you?

     

    -David, After Effects Engineering Team 

    Translate
    ShiveringCactus
    Community Expert
    Community Expert
    Oct 1, 2026 10:49 AM UTC

    Oh that’s such an elegant solution ( posterizeTime(0); )

    I’m using v26 right now and the project you shared is v27, so I haven’t been able to try out the cursor blinking.  But I was able to use the opacity animator to achieve the same result.

    25 years+ (of using AE) and still learning.   Thank you.

     

     

    Translate
    David.Arbor
    Community Manager
    Community Manager
    Oct 1, 2026 7:08 PM UTC

    Oops, sorry about that! I work in the beta all day long. For good measure, I’m uploading a 26.x version. But glad I was able to help!

    -David, After Effects Engineering Team

    Translate