Статьи

Псевдо-комментарии в CSS (или, как браузеры анализируют стили)

Спецификация CSS не упоминает об этом, но вы можете имитировать строковые комментарии в стиле C и / или Unix в файлах CSS (с некоторыми оговорками). Другие уже писали о них раньше (см., В частности, публикацию Site Foundation, посвященную комментариям CSS ). Настоящий пост рассматривает их более подробно.

Комментарии CSS

CSS-парсеры, согласно спецификации , официально благословляют один стиль для комментариев, многострочный комментарий из языков стиля C, который использует начальный токен /* и конечный токен */ следующим образом:

 /* characters between, and including, the start and end tokens are ignored by the parser, */ 

И поэтому объявление правила в комментариях будет игнорироваться:

 body { background: red; /* background: white; */ } 

Объявление блока в комментариях будет игнорироваться:

 /* body { background: red; } */ 

В каждом из этих примеров мы намеренно используем синтаксис комментариев, чтобы дать парсеру команду игнорировать содержимое.

Тем не менее, мы можем сделать это случайно, как с искаженными декларациями, такими как

 body { background: red /* missing semi-colon */ background: blue; } 

В этом примере ни одно фоновое объявление не применяется из-за отсутствующей точки с запятой. Парсер сканирует следующую точку с запятой, определяет, что весь двухстрочный оператор искажен, и поэтому игнорирует весь лексированный контент. То же самое происходит, если мы вообще пропускаем значение свойства:

 body { background: background: blue; /* this declaration is not applied */ } 

И это показывает, что мы можем использовать искаженные декларации как …

Псевдо-комментарий

Мы будем называть их «псевдо-комментариями», потому что, собственно говоря, это не комментарии, заканчивающиеся символом конца строки. Вместо этого они работают, искажая ввод, который следует за ними, даже в последующих строках. И это связано с процессом обработки ошибок для наборов правил, блоков объявлений и селекторов :

«Весь оператор должен игнорироваться, если в селекторе есть ошибка, даже если остальная часть селектора может выглядеть разумно в CSS 2.1».

В следующем примере, взятом из спецификации, второй набор правил игнорируется из-за наличия недопустимого символа «&» в селекторе:

 h1, h2 {color: green } h3, h4 & h5 {color: red } /* <= ignored */ h6 {color: black } 

Опять же, в дальнейшем второе и третье объявления игнорируются из-за присутствия дополнительных символов в имени свойства фона:

 body { background: red; xbackground: white; /* property name is not recognized */ y background: blue; /* property name is not well-formed */ } 

Краткий обзор клавиатуры на английском языке показывает, что следующие специальные символы будут выступать в роли однострочных комментариев:

 selector { ~ property-name: ignored; ` property-name: ignored; ! property-name: ignored; @ property-name: ignored; # property-name: ignored; $ property-name: ignored; % property-name: ignored; ^ property-name: ignored; & property-name: ignored; * property-name: ignored; _ property-name: ignored; - property-name: ignored; + property-name: ignored; = property-name: ignored; | property-name: ignored; \ property-name: ignored; : property-name: ignored; < property-name: ignored; . property-name: ignored; > property-name: ignored; , property-name: ignored; ? property-name: ignored; / property-name: ignored; } 

Вместо того, чтобы использовать только любой символ, придерживайтесь соглашения C и Unix и используйте либо # либо // :

 // background: ignored; # background: ignored; 

Полуприцепы колоны

Точки с запятой являются конечными токенами деклараций правил. Таким образом, они не могут «комментировать» текст, который следует за ними. В спецификациях синтаксический анализатор рассматривает висячую точку с запятой как искаженное объявление (объявление, в котором отсутствует имя, двоеточие или значение).

Как показано ранее, когда обычные многострочные комментарии искажены, то есть когда начальный и конечный токены не сбалансированы вокруг набора правил или объявления, последующее объявление или набор правил игнорируется анализатором. Следующее фактически «комментирует» оба фоновых объявления, потому что синтаксический анализатор будет искать следующий токен конца объявления (точка с запятой) для затронутого объявления:

 body { background: background: blue; /* both lines ignored */ } 

Это исправлено добавлением точки с запятой после комментария перед следующим объявлением (таким образом, будет применено объявление в синем фоне):

 body { background: ; /* ignored */ background: blue; /* processed */ } 

Эффект тот же с псевдо-комментарием к строке, в которой отсутствует точка с запятой:

 body { background: # red /* ignored */ background: blue; /* also ignored */ } 

и исправить, восстановив точку с запятой:

 body { background: # red; /* ignored */ background: blue; /* processed */ } 

Встраивание против размещения на следующей строке

Именно здесь «псевдо» входит в термин «псевдо-комментарий». Это может быть достаточной причиной, чтобы вообще не называть эти «комментарии», поскольку они выходят за рамки соглашения о конце строки в строковых комментариях в стиле C или Unix. ,

Псевдо-комментарий, размещенный в отдельной строке, будет подавлять объявление в следующей строке. В дальнейшем фон будет синим:

 body { // background: white !important; /* ignored */ background: blue; } 

Псевдо-комментарий, помещенный после правильного объявления в той же строке, будет подавлять объявление в следующей строке. В дальнейшем фон будет белым, а не синим:

 body { background: white; // next line is ignored... background: blue !important; } 

Даже «минимизированная» версия селектора CSS со встроенным псевдо-комментарием будет вести себя как комментарий с одним объявлением. Далее первое фоновое объявление игнорируется из-за присутствия маркера комментария # , распознаваемого синтаксическим анализатором как завершающего в следующей точке с запятой, а второе фоновое объявление распознается как правильно сформированное и поэтому применяется (в в этом случае синий цвет будет применен к фону тела):

 body { // background: red !important; background: blue; } 

Селекторы

Такое же поведение на основе правил применимо к селекторам.

Весь набор правил селектора игнорируется, когда селектору предшествует псевдо-комментарий, будь то встроенный

 // body { background: white !important; } 

или следующая строка:

 // body { background: white !important; } 

Псевдо-комментарии как целенаправленная уродливость

Псевдо-комментарии работают, используя правила Spec для обработки ошибок синтаксического анализа . По сути, они работают, эксплуатируя свою уродливость.

Неизвестные значения

«Пользовательские агенты должны игнорировать объявление с неизвестным свойством».

Объявление, содержащее нераспознанное имя свойства, не будет оцениваться, как, например, свойство comment в следующем наборе правил body :

 body { comment: 'could be text or a value'; } 

Незаконные ценности

«Пользовательские агенты должны игнорировать объявление с недопустимым значением».

Определенное ниже свойство color игнорируется, поскольку значением является строка, а не ключевое слово value или color:

 body { color: "red"; } 

Искаженные заявления и заявления

«Пользовательские агенты должны обрабатывать неожиданные токены, обнаруженные при синтаксическом анализе объявления [или оператора], читая до конца объявления [или оператора], соблюдая правила сопоставления пар (), [], {},« »и И правильно обрабатывать побеги ».

 body { -color: red; } 

Объявления, искаженные несопоставленными парами () , [] , {} , "" и '' , более игнорируются (и, следовательно, более опасны), чем другие. И символы кавычек "" и '' обрабатываются иначе, чем символы группировки () , [] , {} .

Цитирование персонажей

Непарный апостроф во втором объявлении ниже предотвратит обработку последующего объявления в наборе правил (таким образом, фон будет красным):

 body { background: red; 'background: white; /* ignored */ background: blue; /* also ignored */ } 

Тем не менее, третье объявление после апострофа будет обработано (таким образом фон будет золотым):

 body { background: red; 'background: white; /* ignored */ background: blue; /* also ignored */ background: gold; /* processed */ } 

В общем, вы не можете завершить один символ кавычки в своей строке.

Группировка персонажей

В общем, следует избегать группирования символов () , [] , {} как псевдо-комментариев, поскольку они имеют более радикальный эффект, поскольку они более интенсивно влияют на правила распознавания блоков синтаксического анализатора, и поэтому будут «комментировать» больше, чем отдельные объявления. , Для полноты картины мы рассмотрим некоторые из них.

Например, появление несопоставленных символов начальной группы подавляет все последующие объявления до конца таблицы стилей (а не только набор правил). Это верно для запятых, скобок и скобок.

В дальнейшем только background: red; декларация обработана; все объявления и селекторы после этого во всей таблице стилей будут игнорироваться:

 body { background: red; { /* *every* declaration that follows will be ignored, including all subsequent selectors, to the end of the stylesheet. */ background: white; color: aqua; margin: 5px; ... } 

Когда совпадают символы группировки, сгруппированные и последующие разгруппированные объявления в наборе правил будут подавлены. В дальнейшем фон будет красным, а не золотым:

 body { background: red; ( background: white; background: blue; background: fuchsia; ) background: gold; } 

Закрывающая запятая или скобка будет подавлять только следующее объявление, которое появляется. В дальнейшем фон будет золотым:

 body { background: red; ] background: white; background: blue; } 

Однако закрывающая фигурная скобка } будет подавлять все объявления до конца набора правил. В дальнейшем фон будет красным:

 body { background: red; } background: white; background: blue; } 

В-правил

У правил есть две формы:

  • объявление тела, обозначенное фигурными скобками, { ... } (например, @media ),
  • объявление правила, закрытое точкой с запятой ; (например, @charset ).

Псевдокомментарии в правилах блока body ведут себя так же, как и в селекторах (то есть все правило at игнорируется)

Псевдо-комментарии применяются к правилам с блоками тела

Для правил, содержащих блоки тела, такие как @keyframes , @media , @page . и @font-face , весь набор правил at-rule игнорируется, когда at-rule предшествует псевдо-комментарий, будь то встроенный

 // @media (min-width: 0) { body { background: white !important; } } 

или следующая строка:

 // @media (min-width: 0) { body { background: white !important; } } 

Псевдо-комментарии применяются к правилам без блоков тела

At-правила без блоков, такие как @charset и @import , обеспечивают захватывающее исключение для встроенного поведения псевдо-комментариев.

Правило at с псевдо-комментарием после ключевого слова будет проигнорировано:

 /* the pseudo-comment before url() suppresses the entire @import */ @import // url('libs/normalize.css'); 

Но псевдо-комментарий, который предшествует правилу at, подавляет как импорт, так и первое правило или селектор после импорта. Это связано с тем, что синтаксический анализатор рассматривает псевдокомментированный @import как искаженное утверждение и ищет следующие соответствующие скобки, чтобы завершить следующий набор правил.

Таким образом, псевдо-комментарий перед одним @import в серии правил @import будет подавлять все последующие правила @import и первое объявление или селектор после последнего импорта:

 // @import url('libs/normalize.css'); /* NONE of these loads because previous statement is processed as a malformed statement, and the parser looks for the next matching braces. */ @import url('libs/normalize.css'); @import url('libs/example.css'); @import url('libs/other.css'); @import url('libs/more.css'); @import url('libs/another.css'); @import url('libs/yetmore.css'); 

@import это на удивление просто: просто добавьте пустой блок тела после комментария @import

 // @import url('libs/normalize.css'); {} /* now, the next import will load */ @import url('libs/normalize.css'); 

Это весело для отладки, но такое поведение достаточно своеобразно, так что вам следует избегать подхода псевдо-комментариев к at-rules без блоков тела и использовать вместо этого многострочный синтаксис.

Ат-правила и неизвестные ат-ключевые слова

«Пользовательские агенты должны игнорировать недопустимое ключевое слово at вместе со всем, что следует за ним, до конца блока, содержащего недопустимое ключевое слово at, или вплоть до следующей точки с запятой (;), или вплоть до следующего включения блок ({…}), в зависимости от того, что наступит раньше »

Мы можем проиллюстрировать все это, используя неизвестное ключевое слово @comment в качестве пользовательской альтернативы правила многострочного синтаксиса. Например, следующее правило at анализируется с закрывающей скобкой, } , определяется как неправильный и затем игнорируется:

 @comment { I'm not processed in any way. } 

Поначалу это выглядит безобидно и читабельно, но из-за присутствия апострофа в « I'm мы вновь представили проблему с символом цитирования (т. Е. Вы не можете завершить одиночный символ кавычки в отдельной строке). Это означает, что последующее at-rule или селектор также будут игнорироваться, если тело нашего custom @comment закрыто на отдельной строке, потому что объявление правила искажено присутствием апострофа в I'm :

 @comment { I'm not processed in any way. } body { background: blue; } /* this whole block will not be processed either! */ 

Это может быть спасено с помощью внешних кавычек, либо внутри фигурных скобок

 @comment { "I'm not processed in any way." } /* fixed */ body { background: blue; } /* this block will work */ 

Или, сняв скобки и вместо этого заканчивая псевдо-комментарий точкой с запятой, либо встроенный:

 @comment "I'm not processed in any way."; body { background: blue; } /* this works */ 

или следующая строка

 @comment "I'm not processed in any way."; body { background: blue; } /* this works */ 

Pre-процессоры

Различные препроцессоры CSS поддерживают похожие многострочные и однострочные комментарии.

пререкаться

Sass поддерживает стандартные многострочные комментарии CSS с / * * /, а также однострочные комментарии с //. Многострочные комментарии по возможности сохраняются в выводе CSS, а однострочные комментарии удаляются.

источник

Сжатый режим обычно удаляет все комментарии, если только комментарию не предшествует /*! ,

Однако вы можете использовать односимвольный псевдо-комментарий, такой как # и вывод будет содержать закомментированную строку.

 body { # background: red; } 

Меньше

Можно использовать как блочные, так и встроенные комментарии.

источник

Неясно (по крайней мере мне), будет ли Less подавлять эти комментарии или выводить их на выход. Из сообщений StackOverflow кажется, что Less будет собирать комментарии к строкам на уровне блоков.

стилус

Стилус также поддерживает многострочные /* */ и однострочные комментарии // , но подавляет их из вывода, если включена директива compress . Если вы всегда хотите, чтобы многострочные комментарии выводились на печать, используйте многострочные буферизованные комментарии.

Многострочные комментарии, которые не подавляются, начинаются с / * !. Это говорит Стилусу выводить комментарий независимо от сжатия.

 /*! * This will appear in the output. */ 

источник

Лучшая практика

«Читаемость имеет значение.»
https://www.python.org/dev/peps/pep-0020/ ‘> Zen of Python

Комментарии могут сделать неясный код более читабельным, но читаемость зависит от нескольких соглашений. Псевдо-комментарии в CSS меньше о читабельности, чем о игре против соглашения (иначе, парсер).

Если вы обнаружите, что вам нужно использовать псевдо-комментарии:

  • Придерживайтесь соглашения C и Unix и используйте либо // либо # для разделителя псевдо-комментариев.
  • Поместите псевдо-комментарии в одну и ту же строку перед игнорируемым элементом.
  • Используйте пробел для отделения разделителя псевдо-комментариев от намеченного правила ~ например # background: ignored; ,

Используйте псевдо-комментарии:

  • Используйте псевдо-комментарии для отладки , особенно при использовании интерактивной панели редактирования CSS, такой как расширение для веб-разработчика Криса Педерика (chrome, firefox, opera).
  • Используйте псевдо-комментарии, чтобы предотвратить обработку отдельных объявлений, селекторов или правил с телами.

Избегайте псевдо-комментариев:

  • Избегайте псевдо-комментариев для использования с текстовыми описаниями и правилами без тел (например, @import) ~ используйте вместо этого многострочные /* ... */ комментарии.
  • Избегайте цитирования символов '', "" ~, их трудно сканировать человеческим глазом, и они не могут быть завершены в отдельной строке.
  • Избегайте группирования символов (), [], {} ~, они вводят более сложное сканирование (и не могут быть завершены в отдельной строке).
  • Избегайте псевдо-комментариев в производственном коде, хотя и не «вредных», они просто лишние байты на этом этапе.