9

I'm trying to add icons to my navigation (which dynamically changes) via JavaScript.

Here is my code (or JSFiddle):

var icon = document.querySelector('#icon');
icon.setAttribute('data-icon', '†');
#icon:after {
  content: attr(data-icon);
}
<div id="icon" data-icon="">
  Icon
</div>

But it is not working, why? When tried to edit data-icon attribute manually, icon appears. Otherwise just unicode of icon.

Paolo Forgia
  • 6,572
  • 8
  • 46
  • 58
venkatraj
  • 101
  • 1
  • 5
  • Possible duplicate of [Insert Unicode character into JavaScript](https://stackoverflow.com/questions/13093126/insert-unicode-character-into-javascript) – Paolo Forgia Jun 26 '17 at 07:36

3 Answers3

6

HTML entities don't have any meaning in CSS. If you want to follow that path you need to decode it first:

var icon = document.querySelector('#icon');
var tmp = document.createElement("span");
tmp.innerHTML = '&#x86;';
icon.setAttribute('data-icon', tmp.innerText);
#icon:after {
  content: attr(data-icon);
}
<div id="icon" data-icon="">
  Icon
</div>

... or, alternatively, just type character as-is (as long as your application is written in UTF-8):

var icon = document.querySelector('#icon');
icon.setAttribute('data-icon', '†');
#icon:after {
  content: attr(data-icon);
}
<div id="icon" data-icon="">
  Icon
</div>

Last but not least, CSS also accepts escape sequences but you need to use the appropriate syntax. This approach, however, does not seem to work for your specific character:

var icon = document.querySelector('#icon');
// Brackets added for visibility, not part of the syntax
icon.setAttribute('data-icon', '(\u0086)(\u2020)');
#icon:after {
  content: attr(data-icon);
}
<div id="icon" data-icon="">
  Icon
</div>

I presume it's related to the fact that U+2020 'DAGGER' (that works fine) is a regular character but the one you're using U+0086 'START OF SELECTED AREA' (which doesn't show) is a control character. As you mention in a follow-up comment, you're using FontAwesome and such libraries provide custom fonts that map certain code points to display icons (though they normally use private areas to avoid conflicts).

Álvaro González
  • 142,137
  • 41
  • 261
  • 360
  • Thanks Alvaro! That solved the issue. Most liked part in your answer is that the answer itself converts entities into unicode. FYI: It comes from FontAwesome. – venkatraj Jun 27 '17 at 06:05
  • @venkatraj I eventually figured out why I was having issues with `U+0086`. I've updated my answer. – Álvaro González Dec 22 '18 at 10:45
2

That is obviously because setAttribute is escaping your special characters...and anyway you need to use CSS encoded icons and not an HTML entity. use this convertor:

&#x086;\0086

I would suggest working with meaningful names instead of hard-coded writing the icon's code into an attribute.

For example:

var icon = document.querySelector('#icon');
icon.setAttribute('data-icon', 'icon-heart');

[data-icon=icon-heart]{
    content:'\2764';
}

(better that all your icons elements will have a shared class which shared properties)

Community
  • 1
  • 1
vsync
  • 118,978
  • 58
  • 307
  • 400
1

Encoding minefield

See this StackOverflow answer for more details.

Answer updated (see comments and edits).

In short, I recommend using the character instead of any method of encoding it. It will be vital in this case that your HTML files are correctly encoded and that they properly inform browsers what the encoding is.

var js = document.querySelectorAll( ".js" );
js[ 0 ].setAttribute( "data-icon", "\u0086" );
js[ 1 ].setAttribute( "data-icon", "†" );
.css:after {
    content: "\86";
    color: red;
}
.css.char:after {
    content: "†";
    color: blue;
}
.data:after {
    content: attr( data-icon );
}
.js:after {
    content: attr( data-icon );
}
.red:after {
    color: red;
}
.blue:after {
    color: blue;
}
<div class="css">hard coded css content</div>
<div class="css char">hard coded css content char</div>
<br>
<div class="data red" data-icon="&#x086;">hard coded data-icon</div>
<div class="data blue" data-icon="†">hard coded data-icon char</div>
<br>
<div class="js red">data-icon by js</div>
<div class="js blue">data-icon by js char</div>
Fred Gandt
  • 4,217
  • 2
  • 33
  • 41
  • 1
    This should explain it: [Insert Unicode character into JavaScript](https://stackoverflow.com/questions/13093126/insert-unicode-character-into-javascript) – AlexG Jun 26 '17 at 07:34
  • 1
    I run the code snippet but no icon is displayed after text "Icon", it's just blank. Is that expected behavior? – shaochuancs Jun 26 '17 at 07:52
  • @shaochuancs - In what browser do you not see the icon? I am using Google's Chrome, and it's all good. – Fred Gandt Jun 26 '17 at 07:54
  • @FredGandt I'm using Chrome Version 59.0.3071.109 on Mac – shaochuancs Jun 26 '17 at 07:55
  • Also tested on Firefox, Safari and Opera, no luck :( It seems more like a Mac issue... – shaochuancs Jun 26 '17 at 07:57
  • @shaochuancs - I'm not sure why this isn't working for you, and for me, the timing of the need to debug the problem couldn't be worse. I will attempt to figure it out in a couple of hours, but **have** to log off now. Sorry. I'll be back though. Maybe someone else will assist while I'm away. – Fred Gandt Jun 26 '17 at 08:01
  • Thanks @FredGandt – shaochuancs Jun 26 '17 at 08:02
  • It doesn't work here either (Firefox/54.0 x64 on Windows 10) but the reason is probably that the Unicode code point appears to be 2020 and not 0086. – Álvaro González Jun 26 '17 at 08:25
  • @shaochuancs - updated as promised, although I see many other answers arrived whilst I was walking my dog. As long as you have a method that works, it's all good :-) – Fred Gandt Jun 26 '17 at 14:15