Каковы правила вокруг пробелов в селекторах атрибутов?

Я читаю спецификацию в селектора атрибутов, но я не могу найти ничего, что говорит о разрешении пробела. Я предполагаю, что это разрешено в начале, до и после оператора, и в конце. Правильно ли это?

Ответ 1

Правила пробелов в селекторах атрибутов указаны в грамматике. Здесь Selectors 3 для селекторов атрибутов (некоторые токены, заменяемые их эквивалентами строк для иллюстрации; S* представляет 0 или более пробельных символов):

attrib
  : '[' S* [ namespace_prefix ]? IDENT S*
        [ [ '^=' |
            '$=' |
            '*=' |
            '=' |
            '~=' |
            '|=' ] S* [ IDENT | STRING ] S*
        ]? ']'
  ;

Конечно, грамматика не очень полезна для тех, кто хочет понять, как писать селектор атрибутов, поскольку он предназначен для тех, кто внедряет механизм селектора.

Здесь приведено простое английское объяснение:

Пробел перед селектором атрибутов

Это не рассматривается в вышеприведенной постановке, но первое очевидное правило заключается в том, что если вы прикрепляете селектор атрибутов к другому простому селектору или псевдоэлементу, не используйте пространство:

a[href]::after

Если вы это сделаете, пространство рассматривается как компилятор потомков, а универсальный селектор подразумевает селектор атрибутов и все, что может следуйте за ним. Другими словами, эти селекторы эквивалентны друг другу, но отличаются от вышеперечисленных:

a [href] ::after
a *[href] *::after

Пробел внутри селектора атрибутов

Если у вас есть пробелы в скобках и вокруг оператора сравнения, это не имеет значения; Я считаю, что браузеры, похоже, относятся к ним так, как будто их там не было (но я не тестировал их широко). Все они действительны в соответствии с грамматикой и, насколько я знаю, работают во всех современных браузерах:

a[href]
a[ href ]
a[ href="#" onclick="location.href='http://stackoverflow.com'; return false;" ]
a[href ^= "http://"]
a[ href ^= "http://" ]

(Очевидно, что нарушение ^ и = с пробелом неверно.)

Если IE7 и IE8 правильно реализуют грамматику, они также смогут обрабатывать их все.

Если используется префикс пространства имен, между префиксом и именем атрибута не допускается пробел.

Это неверно:

unit[sh| quantity]
unit[ sh| quantity="200" ]
unit[sh| quantity = "200"]

Это верно:

unit[sh|quantity]
unit[ sh|quantity="200" ]
unit[sh|quantity = "200"]

Пробел внутри значения атрибута

Но обратите внимание на цитаты вокруг значений атрибутов выше; если вы их оставите, и вы попытаетесь выбрать что-то, чей атрибут имеет пробелы в своем значении, у вас есть синтаксическая ошибка.

Это неверно:

div[class=one two]

Это правильно:

div[class="one two"]

Это связано с тем, что значение некотируемого атрибута рассматривается как идентификатор, который не включает пробелы (по понятным причинам), тогда как цитируемое значение рассматривается как строка. Подробнее см. эту спецификацию.

Чтобы предотвратить такие ошибки, я настоятельно рекомендую всегда указывать значения атрибутов, будь то в HTML, XHTML (обязательно), XML (обязательно), CSS или jQuery (как только требуется).

Пробел после значения атрибута

Как и для селекторов 4, селектора атрибутов могут принимать флаги в форме идентификатора, появляющегося после значения атрибута. Пока что для чувствительность к регистру (а точнее, нечувствительность к регистру) был определен один флаг:

div[data-foo="bar" i]

Грамматика была обновлена ​​ таким образом:

attrib
  : '[' S* attrib_name ']'
    | '[' S* attrib_name attrib_match [ IDENT | STRING ] S* attrib_flags? ']'
  ;

attrib_name
  : wqname_prefix? IDENT S*

attrib_match
  : [ '=' |
      PREFIX-MATCH |
      SUFFIX-MATCH |
      SUBSTRING-MATCH |
      INCLUDE-MATCH |
      DASH-MATCH
    ] S*

attrib_flags
  : IDENT S*

На простом английском языке: если значение атрибута не цитируется (т.е. оно является идентификатором), требуется пробел между ним и attrib_flags; в противном случае, если значение атрибута указано, то пробел является необязательным, но настоятельно рекомендуется для удобства чтения. Пробелы между attrib_flags и закрывающей скобой необязательны, как всегда.