last-of-type не работает с настраиваемыми элементами в IE11 и Edge

.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>

Последний bar отображается красным в обоих случаях в Chrome и Firefox. Однако в IE11 и Edge это не работает во втором сценарии. В чем дело?


person adamdport    schedule 29.07.2016    source источник


Ответы (3)


IE, похоже, обрабатывает все неизвестные элементы как элементы одного и того же типа. Если вы удалите селектор типа bar, вы увидите, что IE соответствует элементу baz (и только ему):

.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>

Такое поведение также наблюдалось в Microsoft Edge.

Было ли это признано ошибкой со стороны Microsoft? Что ж, я не нашел никаких отчетов об ошибках на этот счет. Это нарушение спецификации? Это зависит от того, считаете ли вы неизвестные элементы одним и тем же типом элемента (обратите внимание, что я говорю в терминах DOM, а не HTML). Ни в спецификациях селекторов, ни в спецификациях DOM нет даже упоминания о неизвестных элементах (вероятно, потому, что неизвестные элементы изначально не соответствуют требованиям).

Обратите внимание, что я продолжаю говорить «неизвестный элемент», потому что на самом деле у вас нет настраиваемого элемента, пока вы его не зарегистрируете (тем самым сделав его элементом известным, как и все другие стандартные элементы). Кроме того, IE не поддерживает настраиваемые элементы, как это определено ни одним из будущих стандартов, а Microsoft Edge еще не предоставил эту функцию. Пользовательские элементы подходят, если вы работаете с браузерами, которые поддерживают эту функцию или ее полифиллы. Неизвестные элементы, как и любое другое преднамеренное отклонение от стандарта, однозначно являются плохой практикой и могут привести к неожиданному поведению, , даже если спецификация требует, чтобы браузеры относились к ним как к первоклассным гражданам для целей DOM и CSS, и причины этого хорошо аргументированы в этот ответ.

person BoltClock    schedule 30.07.2016
comment
Я думал, что все элементы были неизвестны браузеру, пока они не были введены через таблицу стилей по умолчанию. Однако достаточно было просто зарегистрировать настраиваемый элемент в авторских стилях, чтобы заставить его работать. Я писал об этом здесь: stackoverflow.com/q/36380449/3597276 - person Michael Benjamin; 30.07.2016
comment
Неизвестные элементы являются стандартными при создании директив AngularJS. Это облом. - person adamdport; 30.07.2016
comment
@Michael_B: знание элементов браузером контролируется его реализацией DOM, а не какой-либо таблицей стилей. CSS - это просто потребитель DOM. По той же причине, почему класс CSS неправильно употреблен. - person BoltClock; 30.07.2016
comment
@adamdport: это зависит от того, как вы интерпретируете слово «стандарт». AngularJS - это просто сторонняя структура, созданная Google, которая полагается на определенное поведение браузера для работы. Это не стандарт, который браузеры должны реализовывать или что-то в этом роде. - person BoltClock; 30.07.2016
comment
Элемент HTML 5 main не распознается IE 9, 10 и 11. Однако при добавлении его в стили автора (и применение display: block полезно) он внезапно становится распознанным элементом, и поэтому его поведение одинаково с другими браузерами stackoverflow.com/q/35820429/3597276 - person Michael Benjamin; 30.07.2016
comment
Чем main отличается от bar и baz? - person Michael Benjamin; 30.07.2016
comment
Я только что протестировал main с last-of-type в IE11, и он тоже не работает, как в примере в вопросе. Возможно, это скорее last-of-type проблема в IE, а не один из пользовательских элементов. - person Michael Benjamin; 30.07.2016
comment
@Michael_B: Ничего особенного. IE9 + отличается от IE8 тем, что не требует использования document.createElement, чтобы его DOM-процессор распознавал их как элементы для целей CSS - и поэтому простая установка display: block работает в более новых версиях. Однако каким-то образом в более новых версиях все эти элементы рассматриваются как принадлежащие к одному типу, однако это отдельная проблема. - person BoltClock; 30.07.2016
comment
Независимо от того, считаете ли вы, что использование определенных пользователем имен тегов (которые должны содержать хотя бы один дефис, но не в качестве первого символа) относятся к одному или разному классу DOM, применение селекторов к элементам четко определяется w3.org/TR/html5/disabled-elements.html#selectors как ASCII без учета регистра, поэтому мне кажется, что MS Edge нарушает спецификацию, не применяя селектор на основе имени, а не какой-то неизвестной внутренней концепции. - person Victoria; 06.05.2017
comment
И вот что-то вроде отчета об ошибке: разработчик. microsoft.com/en-us/microsoft-edge/platform/issues/ - person Victoria; 06.05.2017
comment
@Victoria: Спасибо за ссылку на отчет об ошибке. Да, мне трудно не согласиться с вами в том, что это нарушение спецификации. Я поговорю с командой об этом - приятно, что в то время я занимаюсь исследованием пары других проблем с CSS в Edge. - person BoltClock; 06.05.2017
comment
@Victoria: Я нашел часть спецификации, в которой говорится, что неизвестные элементы должны соответствовать селекторам, как это делают известные элементы, и обновил свой ответ. В процитированном вами разделе ничего не говорится о неизвестных элементах как таковых - он просто говорит, что селекторы типов (и, предположительно, псевдонимы типа: * - по расширению) должны соответствовать без учета регистра. - person BoltClock; 10.05.2017
comment
Ах да, это более прямое требование, поскольку оно гласит: пользовательские агенты должны рассматривать элементы и атрибуты, которые они не понимают, как семантически нейтральные; оставляя их в DOM (для процессоров DOM) и стилизуя их в соответствии с CSS (для процессоров CSS), но не выводя из них никакого смысла. - person Victoria; 10.05.2017

Похоже, что IE11 / Edge сбрасывается пользовательским элементом, идущим после элемента bar при применении last-of-type.

В первом примере список заканчивается span распознанным элементом HTML.

Во втором примере, если вы замените baz распознанным элементом span, textarea и т. Д., Он также будет работать в IE11 / Edge.

Похоже, это ошибка, так как проблем с использованием настраиваемых элементов возникнуть не должно: Правильный способ применения CSS к настраиваемым элементам HTML5

person Michael Benjamin    schedule 29.07.2016
comment
Вы только что повторили мой вопрос. Это общепризнанная ошибка или использование настраиваемых элементов - плохая практика? - person adamdport; 29.07.2016
comment
Я думал, вы ищете объяснения. Мне это кажется ошибкой, но я не видел никакой документации. Что касается использования настраиваемых элементов, см. Этот ответ: stackoverflow.com/q/36380449/3597276 - person Michael Benjamin; 29.07.2016
comment
Спасибо. Я не думал, что пользовательские элементы плохие, но не мог найти никаких подтверждений ошибки. - person adamdport; 29.07.2016

С HTML5 вы можете создавать собственные элементы. Это действительно и законно. Это даже часть поддержки таких проектов, как Polymer-Project. Таким образом, да, вы можете использовать пользовательские элементы.

Однако, как и во всем хорошем, есть некоторые предостережения. Быстрый взгляд на поддержку браузером таких настраиваемых элементов через caniuse.com показывает отсутствие поддержки почти во всех основные браузеры, кроме Chrome. Фактически, W3C имеет Спецификацию настраиваемых элементов, обозначенную как рабочий проект ( Последнее обновление: 21 июля 2016 г.), так что предполагаем, что в ближайшее время будут внесены изменения.

Если вам все еще интересно использовать пользовательские элементы, я бы посоветовал использовать что-то вроде Polymer. Согласно их диаграмме совместимости:

Библиотека Polymer - это легкий слой шугаринга поверх API веб-компонентов. В отличие от типичного фреймворка javascript, Polymer предназначен для использования функций, встроенных в саму веб-платформу, чтобы вы могли создавать компоненты. Некоторые функции, используемые Polymer, изначально не поддерживаются (пока) во всех браузерах. Для широкой поддержки веб-компонентов Polymer использует полифиллы с webcomponents.org. Они легкие, хорошо работают и обеспечивают необходимую поддержку функций Polymer.

библиотека предоставляет необходимые полифилы, чтобы эта функциональность работала в браузерах, которые еще не полностью реализовали спецификацию, поэтому вы должны быть в безопасности при использовании пользовательских элементов, несмотря на относительно небольшой объем встроенной поддержки.

person War10ck    schedule 29.07.2016