Theme Awareness CSS variables InDesign

,

Is there a way to access the current theme colors in UXP plugins for InDesign?
I tried using background-color: var(--uxp-host-background-color); but it doesn’t seem to work in InDesign.

I don’t think the InDesign app supports those variables. Would you be fine with listening to theme changes and applying those styles dynamically?

Well, as I don’t really have information about these themes, this is too unsafe. If InDesign doesn’t give me the needed values, and I can’t solve all UI problems with the current state of UXP, I will apply my own styling, to know what I’m dealing with.

We think it’s working for us by double defining the var. For example, in our CSS we have this:
:root {

/* Declarations to share across the CSS */

--bottomOfResultsFontSize: 11px;
--debuggingBorderColor: none;
--themeAware-background-color: var(--uxp-host-background-color);
--themeAware-border-color: var(--uxp-host-border-color);
--themeAware-color: var(--uxp-h3-color);
--themeAware-contrastingColor: var(--uxp-h1-color);
--themeAware-disabled-color: var(--uxp-host-widget-hover-border-color);
--uxp-label-body-size: 14px;

}

.dialog-s-arraySelector_allContainer {

/* at the bottom of the array selector is a container where the filtered results of the array will be displayed */

border-radius: 5px;
border: 1px solid var(--themeAware-border-color);
display: flex;
flex-direction: column;
height: calc(100%-124px);
margin-top: 0.5em;
max-height: 160px;
min-height: 111px;
overflow-y: scroll;
width: 100%;

}

That second one is just the 1st class where we used one of the root vars to show you how we are accessing them with the second level of var. Maybe it isn’t as hard as we made it, but it is either working or it’s doing a mighty good job of faking it. :slight_smile:

JSW

Very interesting …
Thank you, for sharing your solution. Sadly, this somehow doesn’t work for me, except I misunderstood you.

:root {
    --themeAware-background-color: var(--uxp-host-background-color);
    --themeAware-color: var(--uxp-h3-color);
    --themeAware-disabled-color: var(--uxp-host-widget-hover-border-color);

}
#colortest {
    background-color: white;
    margin: 50px auto;
    padding: 5px;
    > div {
        border: 1px solid black;
        width: 40px;
        height: 40px;
        margin: 10px;

        &:nth-child(1) {
            background-color: var(--themeAware-background-color);
        }
        &:nth-child(2) {
            background-color: var(--themeAware-color);
        }
        &:nth-child(3) {
            background-color: var(--themeAware-disabled-color);
        }
    }
}

This will look like this:

Bildschirmfoto 2024-08-26 um 13.23.23

In the inspector the html element (root) shows the variables, but they seem to be empty.

Bummer. Sorry that didn’t work for you.
While it doesn’t work for this case, does it work for any other elements?

Jon

Very good idea. I thought i maybe works only with the widgets, and not native elements. But sadly, it didn’t work anywhere. The thing I’ve not tested is spectrum web components. Up until now I couldn’t get the webpack-workflow to run properly, and deferred it to a later point.

Here is my experiment:

:root {
    --themeAware-background-color: var(--uxp-host-background-color);
    --themeAware-color: var(--uxp-h3-color);
    --themeAware-disabled-color: var(--uxp-host-widget-hover-border-color);
}

#tests {
    background-color: black;
    padding: 10px;

    > * {
        margin: 7px 0;
    }

    #test-p-color {
        color: var(--themeAware-background-color);
    }
    #test-sp-body-color {
        color: var(--themeAware-background-color);
    }
    #test-p-bg {
        background-color: var(--themeAware-background-color);

    }
    #test-sp-body-bg {
        background-color: var(--themeAware-background-color);
    }
    #test-div-bg {
        background-color: var(--themeAware-background-color);
    }
    #test-sp-action-button-bg {
        background-color: var(--themeAware-background-color);
    }
    #test-sp-button-bg {
        background-color: var(--themeAware-background-color);
    }
}
          <category-content id="tests">
            <p id="test-p-color">p with text-color</p>
            <sp-body id="test-sp-body-color">sp-body with text-color</sp-body>
            <p id="test-p-bg">p with bg-color</p>
            <sp-body id="test-sp-body-bg">sp-body with bg-color</sp-body>
            <div id="test-div-bg">div with bg-color</div>
            <sp-action-button id="test-sp-action-button-bg">sp-action-butto with bg-color</sp-action-button>
            <sp-button id="test-sp-button-bg">sp-action-butto with bg-color</sp-button>
          </category-content>

(just ignore the custom ‘category-content’-tag, think of it as a div)

It tested themeAware-color as well, but did not work either.
This is the result:

Checking back a year later and it seems InDesign doesn’t have a way to get UXP Theme Colors yet like Photoshop. Is this on the roadmap? @indranil

1 Like

Variables do not work in InDesign, but you can work around this by using media queries.

In the documentation table (Doc), InDesign is not explicitly listed (only Photoshop and XD are), but the feature does work.

@media (prefers-color-scheme: dark) {
…
}

@media (prefers-color-scheme: darkest) {
…
}

@media (prefers-color-scheme: light) {
…
}

@media (prefers-color-scheme: lightest) {
…
}

Hope this helps.

2 Likes

Thanks, that’s better than nothing, still not great having to guess / color pick colors for each category.

I checked the queries, including the query “lightest” which doesn’t work in InDesign 2026, while same CSS code works in InDesign 2025.
Perhaps it’s a bug.

:root {
    --theme-background-color: #666;
}

@media (prefers-color-scheme:darkest) {
    :root {
        --theme-background-color: rgb(62, 47, 150);
    }
}

@media (prefers-color-scheme:light) {
    :root {
        --theme-background-color: #ccc;
    }
}

@media (prefers-color-scheme:lightest) {
    /* doesn't work in InDesign 2026, but it works in 2025*/
    :root {
         --theme-background-color: rgb(231, 255, 215);
    }
}

I agree, the lightest doesn’t work in 2026. It’s the light media query that applies in this case.

1 Like

For querying the color scheme I found a different solution that seems to work in 2026. Kudos to whoever pointed me in that direction, sadly I forgot :man_shrugging:.

// Set theme initially on plugin load
setTheme();
// Update theme when changed in settings
document.theme.onUpdated.addListener(setTheme);

// set theme class on body element
function setTheme() {
    document.body.removeAttribute('theme');
    let theme = undefined;
    let brightness = app.generalPreferences.uiBrightnessPreference;
    if (brightness <= 0) {
        theme = 'darkest';
    } else if ((0 < brightness) && (brightness <= 0.5)) {
        theme = 'dark';
    } else if ((0.5 < brightness) && (brightness < 1.0)) {
        theme = 'light';
    } else if (brightness >= 1.0) {
        theme = 'lightest';
    } else {
        console.warn("Unknown theme: " + brightness);
    }
    document.body.setAttribute('theme', theme);
}

I then use custom CSS variables that I change depending on the body class:

:root {
    // Fallback colors will be overridden by body with theme attribute
    --col-text: #ffffff;
    --col-secondary: #b9b9b9;
    --col-input: #252525;
    [...]
}
body {
    &[theme='lightest'] {
        --col-text: #323232;
        --col-secondary: #747474;
        --col-input: #ffffff;
        [...]
    }
    &[theme='light'] {
        --col-text: #2C2C2C;
        --col-secondary: #6E6E6E;
        --col-input: #ffffff;
        [...]
    }
    [...]

It’s a bit tedious to set all the colors manually, but at least it works.

Interestingly, there’s a strange bug with the light color scheme, which won’t be set correctly if the user switches from lightest to light in the settings. It works correctly if it’s changed from any other theme, just not when the previous theme was lightest.

No one else uses Spectrum Web Components?

Importing the sp-theme component provides you with theme-aware custom properties out of the box.

require("@spectrum-web-components/theme/sp-theme.js");
require("@spectrum-web-components/theme/src/themes.js");
require("@spectrum-web-components/theme/src/express/themes.js");
<sp-theme id="panel-theme" system="spectrum" color="dark" scale="medium" dir="ltr">

Then you can use the SWC color palette. If the color attribute changes in sp-theme, the color value changes accordingly.

e.g.

--spectrum-gray-900
--spectrum-blue-500
--spectrum-accent-color-800

And other style properties
e.g.

--spectrum-corner-radius-75

One disadvantage is that the colors do not exactly match the background colors of the application’s user interface (at least in InDesign). So that you have to adjust them separately. Therefore, variables for the background colors, as requested above, would still be helpful.

This is something that the InDesign team needs to set from its end. I’ve raised an internal ticket but can’t promise when it will be prioritized.

2 Likes

Excellent, thank you!