5

.foo bar:last-of-type {
  background-color: red;
}
<div class="foo">
  <bar>bar</bar>
  <bar>bar</bar>
  <bar>bar</bar>
  <span>span</span>
</div>

<div class="foo">
  <bar>bar</bar>
  <bar>bar</bar>
  <bar>bar</bar>
  <baz>baz</baz>
</div>

The last bar appears red in both cases in Chrome and Firefox. In IE11 and Edge, however, it doesn't work in the second scenario. What's going on?

adamdport
  • 11,687
  • 14
  • 69
  • 91

3 Answers3

7

IE appears to be treating all unknown elements as being the same element type. If you remove the bar type selector, you'll see that IE matches the baz element (and only that):

.foo :last-of-type {
  background-color: red;
}
<div class="foo">
  <bar>bar</bar>
  <bar>bar</bar>
  <bar>bar</bar>
  <span>span</span>
</div>

<div class="foo">
  <bar>bar</bar>
  <bar>bar</bar>
  <bar>bar</bar>
  <baz>baz</baz>
</div>

This behavior has also been seen in Microsoft Edge.

Has this been acknowledged as a bug by Microsoft? Well I haven't found any bug reports to this effect. Is this a spec violation? That depends on whether you consider unknown elements to be of the same element type (note that I'm speaking in terms of the DOM, not HTML). Neither the Selectors nor DOM specs make even so much as a mention of unknown elements (presumably because unknown elements are non-conforming in the first place).

Note that I keep saying "unknown element" because you don't actually have a custom element until you register it (thereby making it a known element like all other standard elements). Furthermore, IE does not support custom elements as defined by any of the upcoming standards, and Microsoft Edge hasn't shipped the feature yet. Custom elements are fine, as long as you're working with browsers that either support the feature or polyfills thereof. Unknown elements, as with any other intentional deviation from the standard, are unequivocally bad practice and can result in unexpected behavior, even if the spec requires browsers to treat them as first-class citizens for the purposes of the DOM and CSS, and the reasons for this are well argued in this answer.

Community
  • 1
  • 1
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • I thought that *all* elements were unknown to the browser until they were introduced via the default style sheet. However, by simply "registering" a custom element in author styles, that was enough to put it to work. I wrote about it here: http://stackoverflow.com/q/36380449/3597276 – Michael Benjamin Jul 30 '16 at 13:19
  • Unknown elements *are* standard when creating AngularJS directives. This is a bummer. – adamdport Jul 30 '16 at 14:54
  • @Michael_B: A browser's knowledge of elements is controlled by its DOM implementation, not by any style sheet. CSS is simply a consumer of the DOM. This is the same reason why ["CSS class" is a misnomer](http://stackoverflow.com/questions/18701670/can-i-use-non-existing-css-classes/18701712#18701712). – BoltClock Jul 30 '16 at 16:34
  • @adamdport: It depends on how you interpret the word "standard". AngularJS is just some third-party framework created by Google that relies on certain browser behavior to work. It's not a standard that browsers have to implement or something. – BoltClock Jul 30 '16 at 16:37
  • The HTML 5 `main` element is unrecognized by IE 9, 10 & 11. However, upon adding it to author styles (and applying `display: block` is useful), it's suddenly a recognized element, and behavior is hence uniform with other browsers http://stackoverflow.com/q/35820429/3597276 – Michael Benjamin Jul 30 '16 at 16:38
  • How is `main` different from `bar` and `baz`? – Michael Benjamin Jul 30 '16 at 16:39
  • I just tested `main` with `last-of-type` in IE11, and it also fails, like the example in the question. Maybe this is more of a `last-of-type` issue in IE, and not really one of custom elements. – Michael Benjamin Jul 30 '16 at 16:43
  • 1
    @Michael_B: It's no different. IE9+ is different from IE8 in that it doesn't require you to use document.createElement to make its DOM processor recognize them as elements for the purposes of CSS - and that's why simply setting display: block works in the newer versions. Yet somehow the newer versions still treat these elements as all belonging to the same type - that, however is a separate issue. – BoltClock Jul 30 '16 at 16:47
  • Whether or not you think the use of user-defined tag-names (which should contain at least one hyphen, but not as the first character) are of the same or different DOM class, the application of selectors to elements is well-defined by https://www.w3.org/TR/html5/disabled-elements.html#selectors as being case-insensitive ASCII, so it seems to me that MS Edge violates the spec by not applying the selector based on name rather than some unknown internal concept. – Victoria May 06 '17 at 05:58
  • And here's somewhat of a bug report of the issue: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/5249985/ – Victoria May 06 '17 at 06:40
  • @Victoria: Thanks for the link to the bug report. Yeah, I'd be hard-pressed to disagree with you that it's a spec violation. I'll speak to the team about this - it's nice that I happen to be investigating a couple other CSS issues with Edge at the time. – BoltClock May 06 '17 at 10:12
  • @Victoria: I found the part of the spec where it says that unknown elements should match selectors as known elements do, and have updated my answer. The section you quoted doesn't state anything about unknown elements per se - it just says that type selectors (and presumably the :*-of-type pseudos by extension) should match case-insensitively. – BoltClock May 10 '17 at 11:59
  • Ah yes, that is a more direct requirement, as it says: User agents must treat elements and attributes that they do not understand as semantically neutral; leaving them in the DOM (for DOM processors), and styling them according to CSS (for CSS processors), but not inferring any meaning from them. – Victoria May 10 '17 at 16:15
1

Looks like IE11/Edge are being thrown off by a custom element coming after the bar element when applying last-of-type.

In your first example, your list ends with a span – a recognized HTML element.

In your second example, if you replace baz with a recognized element – span, textarea, etc. – it also works in IE11/Edge.

This appears to be a bug, as there should be no problem using custom elements: Proper way to apply CSS to HTML5 custom elements

Community
  • 1
  • 1
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • You just repeated my question back to me. Is this an acknowledged bug or is it bad practice to use custom elements or what? – adamdport Jul 29 '16 at 19:45
  • I thought you were looking for an explanation. It looks like a bug to me, but I haven't seen any documentation. In terms of using custom elements, see this answer: http://stackoverflow.com/q/36380449/3597276 – Michael Benjamin Jul 29 '16 at 19:48
  • Thanks. I didn't think custom elements were bad, but couldn't find any acknowledgement of a bug. – adamdport Jul 29 '16 at 20:23
-1

With HTML5, you can create custom elements. It is valid and it is legitimate. It is even part of the push behind projects such as the Polymer-Project. So in summary, yes you can use custom elements.

However, as with all good things, there are some caveats. A quick glance at browser support for such custom elements via caniuse.com shows a lack of support in almost all major browsers except Chrome. In fact, the W3C has the Custom Element Spec outlined as a Working Draft (Last Updated: 21 July 2016) so assume there will be changes to come.

If you're still interesting in using custom elements, I'd suggest using something like Polymer. According to their compatibility chart:

The Polymer library is a lightweight sugaring layer on top of the Web Components APIs. Unlike a typical javascript framework, Polymer is designed to leverage features baked into the web platform itself to let you build components. Some features used by Polymer are not (yet) supported natively in all browsers. For broad web components support, Polymer uses the polyfills from webcomponents.org. They're lightweight, work well, and provide the feature support Polymer requires.

the library provides the necessary polyfills to make this functionality work in browsers that have not yet fully implemented the spec so you should be safe to use custom elements despite the relatively low amount of native support.

War10ck
  • 12,387
  • 7
  • 41
  • 54