45

I want to achieve the following in css. How do i do it in a cross browser way?

url('../img/icons/' + attr('type') + '_10.png')
aWebDeveloper
  • 36,687
  • 39
  • 170
  • 242

4 Answers4

29

I don't think you can. In the content property you can "concatenate" just by separating with a space, but in other places I don't think there is such a feature. Which is a shame.

You'll probably be best off specifying this style in a style attribute whenever the type attribute is used.

Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
  • 2
    I believe this is coming in the specification, just not supported in any browser yet. https://developer.mozilla.org/en/docs/CSS/attr#Browser_Compatibility – Fabrício Matté Apr 01 '13 at 14:45
  • @Fabrício Matté: Unfortunately this is an issue with url() and not with attr() regardless of browser support, and it may never be possible unless they re-spec url(). See my answer here: http://stackoverflow.com/questions/42932294/css-attr-concatenation-with-url-path/42932766#42932766 – BoltClock Mar 21 '17 at 16:32
  • 2
    `you can "concatenate" just by separating with a space` That's what we're looking for. – Serj Sagan Oct 12 '18 at 07:20
  • you can concatenate `content` property by separating with a space. eg: `content: 'Page: ' counter(page);` – suhailvs Mar 23 '21 at 04:33
10

CSS performs concatenation without using any operator (e.g. +, &, etc). Keep your strings in quotes combine the strings, attr, var, etc into one line.

Examples:

  • url('not/very' '/useful/concatenation'); // not/very/useful/concatentation
  • url('../img/icons/' attr('type') '_10.png'); //../img/icons/${type}_10.png
  • url(attr('href') '#hash'); // https://${href}/#hash
  • url(var(--hello) ' world'); // Hello World
pseudosavant
  • 7,056
  • 2
  • 36
  • 41
Klaus Veber
  • 297
  • 2
  • 2
  • 2
    **From review queue**: May I request you to please add some more context around your answer. Code-only answers are difficult to understand. It will help the asker and future readers both if you can add more information in your post. – RBT May 13 '17 at 09:43
  • Incredible that CSS uses space \20 as a concatenation operator. – dakab Jul 30 '20 at 10:41
  • 25
    I wonder if the author actually tried those examples. It seems it is not possible, at least with the var() example: https://stackoverflow.com/questions/42330075/is-there-a-way-to-interpolate-css-variables-with-url – Max Waterman Nov 30 '20 at 08:17
  • 4
    This does not work in Firefox and shows as invalid CSS. – nicbou Mar 03 '22 at 10:37
  • 2
    This suggestion doesn't seem to work in Chrome either. At least I tested it with a concatenation in `url()` for an image base url kinf of thing: https://codepen.io/astaco/pen/VwyQwrz – Smamatti Apr 05 '22 at 09:30
  • 1
    I wonder how this answer could get so many upvotes. The first and last point don't work (tried in the provided codepen) and after reading the background from the other comment I believe the other two shouldn't work either. This is just impossible today. (PS: Most of the answer was edited in later, not all is from the first author!) – ygoe Apr 19 '22 at 22:17
  • 1
    Sadly, the last example `url(var(--hello) ' world')` doesn't work, as `var()` cannot be interpolated inside `url()`… See [this question](https://stackoverflow.com/questions/42330075/is-there-a-way-to-interpolate-css-variables-with-url). – Gras Double Sep 01 '22 at 14:35
  • 1
    I'm sure this is a wrong answer. Those case all do not work as my test. – cuixiping May 19 '23 at 09:34
  • according to spec one can use src() instead of url() to do such https://drafts.csswg.org/css-values/#urls – Alexander Sep 01 '23 at 21:30
4

No, you can't do this in plain CSS because the CSS language hasn't control structures or anything like that wich will allow you to dinamically generate CSS code.

Instead, you can use a javascript solutions or a solution based on CSS variables coded in PHP.

Goran
  • 3,292
  • 2
  • 29
  • 32
3

You can't do dynamic string interpolation in the way that you're suggesting, but if you have a limited number of possible values for the [type] attribute, you could create styles for each one:

.your .selector[type="foo"] {
    background-image: url('../img/icons/foo_10.png');
}
.your .selector[type="bar"] {
    background-image: url('../img/icons/bar_10.png');
}
.your .selector[type="baz"] {
    background-image: url('../img/icons/baz_10.png');
}

If you've got an unreasonable number of types, then you'll probably need to come up with a better solution than I've listed here.

zzzzBov
  • 174,988
  • 54
  • 320
  • 367