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.