I'm creating a multilingual PDF in Illustrator with variables and would like to use single line text area boxes to control type. However, in some languages, the text will be very long. Can I set a specific font size for the text area, and then if the text exceeds its box, have it warp, shrink, or decrease tracking to fit? I do not want it to wrap to a new line.

I'm using ExtendScript to try to do this in many steps and keep running into limitations. In order to get the width of the actual text, I'm converting it to point type using convertAreaObjectToPointObject() which does work when the text is smaller than its box. If it overflows, the method always clips just like its GUI equivalent under Type > Convert to Point Type.

Extending the area type width programmatically before converting to point to avoid clipping using .width stretches the type instead of its containing box. Is there another method I should use which simulates grabbing the area type expansion edge?


Using the unwieldy characters and lines and paragraph scripting objects, you can use some method to check whether the area text is overset. Here in this script there is a function which sums it up.

function isOverset(textBox) {
    if (textBox.lines.length > 0) {
        if (textBox.lines[0].characters.length < textBox.characters.length) {
            return true;
        } else {
            return false;
    } else if (textBox.characters.length > 0) {
        return true;

Also I wrote this LinkedIn article for this subject to whomever may find it useful.

| improve this answer | |
  • 1
    Really beautiful, simple solution. Thank you. – Lucent Feb 1 '17 at 19:39

This seems like a very ugly solution, so I'm eager to see improvement. It turns out I needed to set the width of the textPath, not the textFrame. I also had a lot of unknown problems with applying .convertPointObjectToAreaObject() and its reverse to variables as if they were losing the reference.

function shrink_all_text_frames_to_fit (layer_name) {
    var currentLayer = app.activeDocument.layers[layer_name];
    for (var i = 1; i < currentLayer.textFrames.length; i++) {
        currentLayer.textFrames[i].textRange.characterAttributes.horizontalScale = 100; // reset so the script can be run multiple times
        while (check_text_overflow(currentLayer, i))
            shrinkAndCheckSize(currentLayer, i);

function check_text_overflow(layer, frame_number) {
    var save_box_fontsize = layer.textFrames[frame_number].textRange.characterAttributes.size;
    var save_box_width = layer.textFrames[frame_number].width;
    var save_box_height = layer.textFrames[frame_number].height;
    var save_horizontal_scale = layer.textFrames[frame_number].textRange.characterAttributes.horizontalScale;
    layer.textFrames[frame_number].textPath.width = 200; // Set high to avoid the next line clipping text
    layer.textFrames[frame_number].convertAreaObjectToPointObject(); // Convert to point type to measure width
    var text_width = layer.textFrames[frame_number].width;
    layer.textFrames[frame_number].convertPointObjectToAreaObject(); // Convert back to area and restore size
    layer.textFrames[frame_number].width = save_box_width;
    layer.textFrames[frame_number].height = save_box_height;
    layer.textFrames[frame_number].textRange.characterAttributes.horizontalScale = save_horizontal_scale;
    layer.textFrames[frame_number].textRange.characterAttributes.size = save_box_fontsize;
    return (text_width > save_box_width);

function shrinkAndCheckSize(layer, frame_number) {
    layer.textFrames[frame_number].textRange.characterAttributes.horizontalScale -= 5;

shrink_all_text_frames_to_fit("Layer Name");
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.