Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Style sheets to split text and shading on different layers?

Community Beginner ,
Jul 29, 2025 Jul 29, 2025

I do not think this is possible but as a book designer it would be very nice if there was a script. Is there a way to set my font style where my text is on one layer and my shading or rule (essentially a colour) is on a seperate layer? This is useful if the book needs a language change.

thanks
Dom

TOPICS
How to , Scripting , Type
689
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 3 Correct answers

Community Expert , Jul 29, 2025 Jul 29, 2025

@m1b for a language change if the text is separate from any colored content it's possible to change the language by replacing only one plate (the one with the text). if the shading or rules are tied to the text you risk a shift in postion and then multiple plates must change.

Translate
Community Expert , Jul 29, 2025 Jul 29, 2025

You could duplicate the text frame to a new layer then give the copied text no fill and no stroke. Apply paragraph shading to the invisible text instead of the text on the language layer. Since the text is still there and matches whichever language you used as your source for copying the shading will match that language if you make any style (but not copy) changes.

Translate
Community Beginner , Jul 29, 2025 Jul 29, 2025

Hi, Peter is correct, you do it as a 5 colour job, text as a spot black on its own layer. Printers print the CMYK and spot for one language, then replace the spot for the second language.

Translate
Community Expert ,
Jul 29, 2025 Jul 29, 2025

Is there a way to set my font style where my text is on one layer and my shading or rule (essentially a colour) is on a seperate layer?

 

No, Paragraph Rules and Paragraph Borders and Shading are paragraph attributes. If you wanted a rule or shading on a separate layer you would have to create the rules or shadows as separate objects.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 29, 2025 Jul 29, 2025

Hi @DomRob Can you explain how it would be more useful than using the paragraph shading if the book needs a language change? Wouldn't it be better if, after changing the language, the shading just updated automatically to match the new text? Maybe you could post an example screen shot of what you mean?

- Mark

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 29, 2025 Jul 29, 2025

@m1b for a language change if the text is separate from any colored content it's possible to change the language by replacing only one plate (the one with the text). if the shading or rules are tied to the text you risk a shift in postion and then multiple plates must change.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 29, 2025 Jul 29, 2025

Thanks @Peter Spier that could well be the salient factor.

 

Still, I have no idea what a hypothetical script would do. 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 29, 2025 Jul 29, 2025

Nor do I.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 29, 2025 Jul 29, 2025

Maybe they can change the styles of the original text to no/paper color, which would preserve the shading/rules. Then have a new style for the new language that has no rules/shades.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Jul 29, 2025 Jul 29, 2025

Hi, Peter is correct, you do it as a 5 colour job, text as a spot black on its own layer. Printers print the CMYK and spot for one language, then replace the spot for the second language.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 29, 2025 Jul 29, 2025

Seems like you would need to draw the rules/shading as separate shapes if you don't want them to change with text. Don't really see any other way around it. 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 29, 2025 Jul 29, 2025

You could duplicate the text frame to a new layer then give the copied text no fill and no stroke. Apply paragraph shading to the invisible text instead of the text on the language layer. Since the text is still there and matches whichever language you used as your source for copying the shading will match that language if you make any style (but not copy) changes.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Jul 29, 2025 Jul 29, 2025

Hi Scott

I have done this before, it is possible but it gets complicated, I do books with images, maps, graphs and at the moment I am on a 250 page book. The problem can be solved this way but for a second reprint the author has little changes which is where it gets complicated. Thanks, I thought it was unlikely but just needed to confirm it. 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Jul 29, 2025 Jul 29, 2025

Sadly I think you are correct, thanks

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 02, 2025 Sep 02, 2025

Hi @DomRob, I wanted to write a script similar to what you are asking about, so here it is. Perhaps it could be helpful. All it does is search for specific paragraph-styled text and draw a box behind it. If you edit the text (eg. replace with translation) then re-run the script and it will update. Try out the attached demo.indd if you want to see it in action.

- Mark

 

demo.gif

 

/**
 * @file Draw Boxes Around Styled Text.js
 *
 * Instructions:
 * 1. Configure the `searchTerms` at the start of the script,
 *    so that script will search for text set in a particular
 *    paragraph style and draw a box around it.
 * 
 * 2. Ensure that your document has the configured paragraph style
 *    and object style.
 * 
 * 3. Run script.
 * 
 * @author m1b
 * @version 2025-09-02
 * @discussion https://community.adobe.com/t5/indesign-discussions/style-sheets-to-split-text-and-shading-on-different-layers/m-p/15435479
 */
function main() {

    /**
     * searchTerm properties
     * @property {String} paragraphStyleName - the paragraph style to search for.
     * @property {String} objectStyleName - the object style to apply to the box.
     * @property {String} label - *unique* label used to identify each box type.
     * @property {String} layerName - the layer to draw boxes on.
     * @property {Array<Number>} padding - the padding, in points, from each side of the text [T,L,B,R].
     * @property {Boolean} oneBoxPerParagraph - if `true` draws one box per unbroken paragraph; if `false`, consectutive paragraphs will fit in the same box (default: false).
     */
    var searchTerms = [

        // demo search 1
        {
            paragraphStyleName: 'Breakout 1',
            objectStyleName: 'Breakout 1',
            label: 'box type 1',
            layerName: 'Boxes',
            padding: [2, 2, 2, 2],
            oneBoxPerParagraph: true,
        },

        // demo search 2
        {
            paragraphStyleName: 'Breakout 2',
            objectStyleName: 'Breakout 2',
            label: 'box type 2',
            layerName: 'Boxes',
            padding: [10, 2, 10, 2],
            oneBoxPerParagraph: true,
        },

    ];

    app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
    const isEmpty = /^[\s\r\n]*$/;

    var doc = app.activeDocument;
    var errors = [];

    searchTermLoop:
    for (var s = 0; s < searchTerms.length; s++) {

        var searchTerm = searchTerms[s];

        // collect the destination layer
        var layer = getThing(doc.layers, 'name', searchTerm.layerName);

        if (!layer) {
            layer = doc.layers.add({ name: searchTerm.layerName });
            layer.move(LocationOptions.AFTER, doc.layers.lastItem());
        }

        // collect the box object style
        var objectStyle = getThing(doc.objectStyles, 'name', searchTerm.objectStyleName);

        if (!objectStyle) {
            errors.push('No object style "' + searchTerm.objectStyleName + '" found.');
            continue searchTermLoop;
        }

        var paragraphStyle = getThing(doc.allParagraphStyles, 'name', searchTerm.paragraphStyleName);

        if (!paragraphStyle) {
            errors.push('No parragraph style "' + searchTerm.paragraphStyleName + '" found.');
            continue searchTermLoop;
        }

        // collect the texts
        var texts = findText(doc, { appliedParagraphStyle: paragraphStyle });

        if (0 === texts.length) {
            errors.push('No texts found for "' + searchTerm.paragraphStyleName + '" found.');
            continue searchTermLoop;
        }

        if (searchTerm.oneBoxPerParagraph) {

            // collect each paragraph from the texts
            var paragraphs = [];

            for (var i = 0; i < texts.length; i++)
                paragraphs = paragraphs.concat(texts[i].paragraphs.everyItem().getElements());

            texts = paragraphs;

        }

        // remove the previous boxes
        var oldBoxes = doc.allPageItems;

        for (var i = oldBoxes.length - 1; i >= 0; i--) {
            if (searchTerm.label === oldBoxes[i].label)
                oldBoxes[i].remove();
        }

        // draw the boxes
        drawBoxesLoop:
        for (var i = 0, bounds, box; i < texts.length; i++) {

            if (isEmpty.test(texts[i].contents))
                continue drawBoxesLoop;

            bounds = getTextBounds(texts[i]);
            bounds = [bounds[0] - searchTerm.padding[0], bounds[1] - searchTerm.padding[1], bounds[2] + searchTerm.padding[2], bounds[3] + searchTerm.padding[3]];

            box = drawRectangleIndesign(doc, bounds, { label: searchTerm.label, appliedObjectStyle: objectStyle });
            box.move(layer);

        }

    } // end search terms loop

    if (errors.length)
        alert('Errors:\n' + errors.join('\n'));

};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Draw Boxes Around Styled Text');

/**
 * Draws and returns a Rectangle.
 * For Indesign
 * @author m1b
 * @version 2023-08-24
 * @param {Document|Layer|Group} container - the container for the rectangle.
 * @param {Array<Number>} bounds - rectangle bounds [T,L,B,R].
 * @returns {Rectangle}
 */
function drawRectangleIndesign(container, bounds, props) {

    var rectangle = container.rectangles.add({
        geometricBounds: bounds,
    });

    if (props)
        rectangle.properties = props;

    return rectangle;

};


/**
 * Returns the bounds of the text's metrics (not geometry).
 * @author m1b
 * @version 2025-09-02
 * @param {Text} text
 */
function getTextBounds(text) {

    if (
        !text.hasOwnProperty('lines')
        || 0 === text.lines.length
    )
        throw new Error('getTextBounds: bad `lines` property.');

    var top = Infinity;
    var left = Infinity;
    var bottom = -Infinity;
    var right = -Infinity;

    var tsrs = text.lines;

    for (var i = 0, tsr, ltr, first, last; i < tsrs.length; i++) {

        tsr = tsrs[i];
        ltr = ParagraphDirectionOptions.LEFT_TO_RIGHT_DIRECTION === tsr.paragraphDirection;
        first = tsr.characters.firstItem();
        last = tsr.characters.lastItem();

        if (ltr) {

            if (first.horizontalOffset < left)
                left = first.horizontalOffset;

            if (last.endHorizontalOffset > right)
                right = last.endHorizontalOffset;

        }

        else {

            if (last.horizontalOffset < left)
                left = last.horizontalOffset;

            if (first.endHorizontalOffset > right)
                right = first.endHorizontalOffset;

        }

        if (first.baseline - first.ascent < top)
            top = first.baseline - first.ascent;

        if (first.baseline + first.descent > bottom)
            bottom = first.baseline + first.descent;

    }

    return [top, left, bottom, right];

};

/**
 * Returns result of search in the supplied `findIn` object
 * using its findText method.
 *
 * Example:
 *    var headingParas = findText(doc, { appliedParagraphStyle: headingStyle });
 *
 * @author m1b
 * @version 2025-04-18
 * @param {Document|Text} findIn - any object with a valid `findText` method.
 * @param {Object} findWhat - an object containing findChangeTextOptions properties.
 * @returns {Array<Text>}
 */
function findText(findIn, findWhat) {

    if ('function' !== typeof findIn.findText)
        throw new Error('findText: bad `where` supplied.');

    // configure the find
    app.findChangeTextOptions.properties = {
        caseSensitive: false,
        includeFootnotes: true,
        includeHiddenLayers: false,
        includeLockedLayersForFind: false,
        includeLockedStoriesForFind: false,
        includeMasterPages: false,
        wholeWord: false,
    };

    // reset
    app.findTextPreferences = NothingEnum.NOTHING;

    for (var key in findWhat) {

        if (
            findWhat.hasOwnProperty(key)
            && app.findTextPreferences.hasOwnProperty(key)
        )
            app.findTextPreferences[key] = findWhat[key];

    }

    // perform the find
    return findIn.findText();

};

/**
 * Returns a thing with matching property.
 * If `key` is undefined, evaluate the object itself.
 * @author m1b
 * @version 2024-04-21
 * @param {Array|Collection} things - the things to look through.
 * @param {String} [key] - the property name (default: undefined).
 * @param {*} value - the value to match.
 * @returns {*?} - the thing, if found.
 */
function getThing(things, key, value) {

    for (var i = 0; i < things.length; i++)
        if ((undefined == key ? things[i] : things[i][key]) == value)
            return things[i];

};

Edit 2025-09-03: removed debugging line.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Sep 02, 2025 Sep 02, 2025
LATEST

Hi @m1b Please  view my PM in your inbox. Thank You

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines