20

Consider the CSS selection I have here:

http://jsfiddle.net/dx8w6b64/

/* This works:
 #myChart .ct-series-b .ct-bar { 
 */


/* This does not (chromium, glnxa64) */
['ct\:series-name'='second'] .ct-bar {
  /* Colour of your points */
  stroke: black;
  /* Size of your points */
  stroke-width: 20px;
  /* Make your points appear as squares */
  stroke-linecap: round;
}

This is a sample chart using https://gionkunz.github.io/chartist-js/

I am trying to select the ct-bar elements:

enter image description here

The colon appears to be throwing off the selector. I have tried various escape approaches :, \3A with a space after, single and double quotes - no luck.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
Ashish Uthama
  • 1,331
  • 1
  • 9
  • 14
  • don't put the attribute in quotes at all, i.e. `[ct\:series-name='second']` (not tested but I just read about this somewhere yesterday) – Jaromanda X Dec 24 '15 at 02:14
  • That's kinda odd. `[ct\:series-name="second"]` [works here](https://jsfiddle.net/f75pc8jg/), but [not here](http://jsfiddle.net/zytLyyjo/). In the DOM, the attribute is displayed as `ct:series-name="second"`, but when you inspect the actual HTML, the attribute is `series-name="second"` (for me at least in the Chrome console). – Josh Crozier Dec 24 '15 at 02:19
  • See http://stackoverflow.com/questions/24628932/do-css-namespace-attribute-selectors-work-with-xhtml-html-elements and http://stackoverflow.com/questions/24390558/css-attribute-namespace-selector-in-svg – Ruan Mendes Dec 24 '15 at 02:24
  • @JoshCrozier: I am on Chrome v49... dev-m and it does display as `ct:series-name="second"` in the console but neither `ct\:series-name` nor `ct|series-name` works. Very interesting. (And your first fiddle works fine for me too) – Harry Dec 24 '15 at 02:28
  • 1
    Does nobody here know XML? That is very clearly a namespace prefix - and we're dealing with SVG, an XML-based markup language here, not HTML. – BoltClock Dec 24 '15 at 05:51
  • 1
    @BoltClock: It took sometime to figure that out but I did eventually :D – Harry Dec 24 '15 at 05:52
  • 1
    Possible duplicate of [How to use CSS attribute selector for an SVG element with namespaced attribute href?](http://stackoverflow.com/questions/27398745/how-to-use-css-attribute-selector-for-an-svg-element-with-namespaced-attribute-h) – Kaiido Dec 25 '15 at 00:31
  • @Kaiido - Maybe for the core solution, but the answer shows here how to deduce the namespace url to use. So it goes beyond the one you linked. – Ashish Uthama Dec 25 '15 at 03:06
  • But I marked the questions as duplicates, not the answers. – Kaiido Dec 25 '15 at 10:18
  • For anyone interested in the JavaScript side of the question, see http://stackoverflow.com/questions/23034283/is-it-possible-to-use-htmls-queryselector-to-select-by-xlink-attribute-in-an – Fabien Snauwaert Feb 18 '17 at 13:07

3 Answers3

9

I've never used Chartist, but judging by the ct: namespace prefix, it appears to be an extension to SVG markup. So you're no longer really dealing with HTML here; you're dealing with XML, because SVG is an XML-based markup language.

Escaping the colon or otherwise specifying it as part of the attribute name doesn't work because the ct: no longer becomes part of the attribute name when it's treated like a namespace prefix (which is what it is). In a regular HTML document, an attribute name like ct:series-name would indeed include the prefix, because namespace prefixes only have special meaning in XML, not in HTML.

Anyway, the web inspector shows the following XML for your svg start tag:

<svg class="ct-chart-bar" xmlns:ct="http://gionkunz.github.com/chartist-js/ct" width="100%" height="100%" style="width: 100%; height: 100%;">

What you need to do is reflect this XML namespace in your CSS using a @namespace rule:

@namespace ct 'http://gionkunz.github.com/chartist-js/ct';

And, rather than escaping the colon, use a pipe to indicate a namespace prefix:

[ct|series-name='second'] .ct-bar {
  stroke: black;
  stroke-width: 20px;
  stroke-linecap: round;
}

And it should work as expected.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • Oh I see so that is the reason why `\:` doesn't work even after adding the namespace declaration. – Harry Dec 24 '15 at 05:54
  • 2
    Or easier, use a wildcard namespace (`*|attr`), no need to declare the namespaces. See http://stackoverflow.com/a/23047888/3702797 – Kaiido Dec 25 '15 at 00:53
  • @Kaiido: That's assuming the attribute names are unique enough to their respective namespaces that you don't actually need the namespace name to disambiguate (which is, you know, the whole point of namespaces). – BoltClock Dec 25 '15 at 10:36
  • Well, that's an important notice to add if you want to include it as an edit, but, you know, you can't only select by the attribute, you also need the value to make a match. So the worthiest case is `*|attr*="a_contained_value"`, where another named-space attribute will be exactly the same as the required `attr`, which I assume will represent less than 1% of any reader's case. Moreover, attribute selectors should be used with an other selector type (you probably don't want all your `` tags to get the same width as the ` – Kaiido Dec 25 '15 at 14:32
  • 1
    I have a feeling you don't actually mean "can't" in your first sentence so much as "don't often", because `[*|attr]` is perfectly legal. Again, there is nothing stopping you from making assumptions about your markup if you can rely on them - just remember you made those assumptions once you start running into unforeseen problems. – BoltClock Dec 25 '15 at 14:36
  • Did you ever felt onto such unforeseen problem ? Also, I almost always used it with `querySelector` where there is unfortunately no option to declare the namespaces... – Kaiido Dec 25 '15 at 14:43
  • Pleae note that this namespace declaration have to be placed at the top of your css file. More precisely, as stated in this thread https://stackoverflow.com/questions/24628932/do-css-namespace-attribute-selectors-work-with-xhtml-html-elements, *a normal CSS rule must not precede any \@namespace rules, or the \@namespace rules are invalid*. The CSS Namespaces Module Level 3 http://www.w3.org/TR/css3-namespace/ says that > Any \@namespace rules must follow all \@charset and \@import rules and precede all other non-ignored at-rules and style rules in a style sheet. – AlexLaforge Oct 15 '19 at 12:08
  • 1
    @AlexLaforge: I remember answering that question. I remember the style rule appearing before the at-namespace rule not being there when I first answered it, then the asker realized it by looking at their own code, hence the edit. – BoltClock Oct 19 '19 at 12:00
3

You shouldn't quote the attribute name, otherwise you are correctly escaping the colon.

[ct\:series-name='second'] 

See https://msdn.microsoft.com/en-us/library/ms762307(v=vs.85).aspx

Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
  • I remember trying that too. Like this: http://jsfiddle.net/whfactq2/ ? Still doesn't appear to work :( – Ashish Uthama Dec 24 '15 at 02:16
  • My bad, I usually test my answers, but I'm on my phone, have you seen the @namespace syntax? https://developer.mozilla.org/en-US/docs/Web/CSS/@namespace – Ruan Mendes Dec 24 '15 at 02:20
  • That MSDN document appears to be a very old one - it refers to IE as "Microsoft® Internet Explorer", which was last used with *IE6* before they started calling it "Windows® Internet Explorer" with IE7 in 2006. @namespace was introduced and implemented relatively recently - with IE first implementing it in version 9 in 2011, along with introducing support for application/xhtml+xml. – BoltClock Dec 24 '15 at 05:54
  • @JuanMendes - thanks for the tip about \@namespace - didnt know enough to figure it out without Boltclock's answer. – Ashish Uthama Dec 25 '15 at 01:56
3

It seems like the namespace selector would work only when the namespace is defined within the CSS itself in the below format:

@namespace <namespace-prefix>? [ <string> | <uri> ];

From Selectors Spec: emphasis is mine

The attribute name in an attribute selector is given as a CSS qualified name: a namespace prefix that has been previously declared may be prepended to the attribute name separated by the namespace separator "vertical bar" (|).

An attribute selector with an attribute name containing a namespace prefix that has not been previously declared is an invalid selector.

Once we add the namespace definition for ct into the CSS, the namespace based selector works as expected. The namespace's URI was taken from the <svg> tag that was generated.

var data = {
  labels: ['W1', 'W2', 'W3', 'W4', 'W5', 'W6', 'W7', 'W8', 'W9', 'W10'],
  series: [{
    name: 'first',
    data: [1, 2, 4, 8, 6, -2, -1, -4, -6, -2]
  }, {
    name: 'second',
    data: [3, 4, 2, 6, 3, 2, 1, 4, 6, 2]
  }]
};

var options = {
  high: 10,
  low: -10,
  onlyInteger: true
};

new Chartist.Bar('.ct-chart', data, options);
@namespace ct url(http://gionkunz.github.com/chartist-js/ct);
[ct|series-name="second"] .ct-bar {
  stroke: black !important; /* without important it doesn't seem to work in snippet but works in fiddle */
  stroke-width: 20px;
  stroke-linecap: round;
}
<script src="https://cdn.jsdelivr.net/chartist.js/latest/chartist.min.js"></script>
<link href="https://cdn.jsdelivr.net/chartist.js/latest/chartist.min.css" rel="stylesheet" />
<div id="myChart" class="ct-chart" style="height:400px"></div>

Fiddle Demo.


Note: The below selector doesn't work even after the namespace definition is added. The reason for this is provided by BoltClock in his answer.

[ct\:series-name="second"] .ct-bar {}
Community
  • 1
  • 1
Harry
  • 87,580
  • 25
  • 202
  • 214
  • Pleae note that this namespace declaration have to be placed at the top of your css file. More precisely, as stated in this thread https://stackoverflow.com/questions/24628932/do-css-namespace-attribute-selectors-work-with-xhtml-html-elements, *a normal CSS rule must not precede any \@namespace rules, or the \@namespace rules are invalid*. The CSS Namespaces Module Level 3 http://www.w3.org/TR/css3-namespace/ says that > Any \@namespace rules must follow all \@charset and \@import rules and precede all other non-ignored at-rules and style rules in a style sheet. – AlexLaforge Oct 15 '19 at 12:08