Is there a way to interpolate CSS variables with url()?

css, css-variables

Solution

You can perform interpolation with most CSS functions, including `rgba()` (see an example here). In fact, interpolation is one of the main features of custom properties.

But you cannot do this with `url()`, as `url(var(--url))` is parsed not as a `url(` function token followed by `var(--url)` followed by a `)`, but a single `url()` token that is invalid because the `var(--url)` is being treated as a URL itself, and unquoted URLs in `url()` tokens cannot contain parentheses unless they are escaped. This means the substitution never actually occurs, because the parser never sees any `var()` expressions in the property value — indeed, your `background` declaration is completely invalid.

If you didn't understand any of that, that's fine. Just know that you cannot use `var()` interpolation with `url()` due to legacy reasons.

Even though the problem depicted in the question is related to the legacy `url()` token, you cannot do this by building URL tokens out of several `var()` expressions either, in case you were thinking of trying something like `--uo: url(; --uc: );` or `--uo: url("; --uc: ");`, and `background: var(--uo) var(--url) var(--uc);`. This is because custom properties cannot contain unmatched string delimiters or parts of `url()` tokens (called bad URL tokens).

If you want to specify a URL in a custom property, you need to write out the entire `url()` expression, and substitute that entire expression:

:root {
  --url: url("https://download.unsplash.com/photo-1420708392410-3c593b80d416");
}

body {
  background: var(--url);
}

Or, use JavaScript instead of `var()` to perform the interpolation.

Problem

I want to store my background URLs in custom properties (CSS variables) and use them with the background property. However, I couldn't find a way to interpolate the string when using it as a parameter in `url()`. Here is my sample code: ``` :root { --url: "https://download.unsplash.com/photo-1420708392410-3c593b80d416"; } body { background: url(var(--url)); } ``` I know that this can be easily done in Sass or LESS using the interpolation function but I'm curious if there is a way to do it without any pre-processor.

Original source

Related problems