От автора: в спецификации об этом ничего не сказано, но в файлах CSS можно имитировать C-подобные и/или Unix комментарии (с небольшими оговорками). Множество статей было написано на эту тему. В данной же статье мы более подробно их рассмотрим.
CSS комментарии
В парсерах CSS, согласно спецификации, приемлем только один стиль комментирования: многострочное комментирование, как в C-подобных языках. Открывающий символ /*, закрывающий символ */. Т.е. вот так можно проигнорировать стили:
1 2 3 4 5 6 |
body { background: red; /* background: white; */ } |
Можно закомментировать целый блок:
1 2 3 4 5 |
/* body { background: red; } */ |
Также проигнорировать целый блок можно случайно, допустив ошибку:
1 2 3 4 |
body { background: red /* потерянная точка с запятой */ background: blue; } |
В этом примере оба селектора не сработают из-за пропущенной точки с запятой в первой строке. Парсер отделяет селекторы точкой с запятой, обнаруживает селектор, записанный в две строки. Из-за неправильной записи игнорируется весь контекст, то есть блок. То же самое будет, если пропустить значение свойства:
1 2 3 4 |
body { background: background: blue; /* это свойство не сработает */ } |
А это значит, что мы можем использовать неправильное объявление свойств, как…
Псевдо-комментарии
Мы называем такую форму записи «псевдо-комментарием», так как, по сути, это и не комментарий вовсе. Из-за своей неправильно записи они портят идущее следом свойство. Все из-за ошибки во время обработки правил, объявлений блоков и селекторов:
«Если хоть в одном селекторе допущена ошибка, будет проигнорировано все выражение, даже если остальные свойства записаны по правилам CSS 2.1.»
В следующем примере из спецификации второй блок будет пропущен из-за лишнего символа «&» в селекторе:
1 2 3 |
h1, h2 {color: green } h3, h4 & h5 {color: red } /* <= будет проигнорировано */ h6 {color: black } |
И снова, второе и третье свойство не сработают, так как в их именах присутствуют лишние символы:
1 2 3 4 5 |
body { background: red; xbackground: white; /* свойство не найдено */ y background: blue; /* название свойства записано некорректно */ } |
Быстрый ликбез по английским символам, которые можно использовать для однострочных комментариев:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
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 комментарии, # или //:
1 2 |
// background: ignored; # background: ignored; |
Точка с запятой
Точка с запятой является окончанием правила. Т.е. их нельзя использовать для комментирования стоящего впереди текста. В спецификации говорится, что парсер обрабатывает отсутствие точки с запятой, как неправильное объявление (пропущено название свойства, двоеточие или значение).
Как упоминалось уже выше, при неправильном объявлении многострочного комментария, также игнорируется и внутреннее объявление. В примере ниже оба свойства background будут работать, как комментарии, из-за того, что парсер будет искать символ конца объявления (точка с запятой):
1 2 3 4 |
body { background: background: blue; /* обе строки игнорируются */ } |
Исправить это можно, добавив точку с запятой перед следующим свойством (т.е. свойство background: blue сработает):
1 2 3 4 |
body { background: ; /* игнорируется */ background: blue; /* выполняется */ } |
Тот же эффект с пропущенной точкой с запятой и в псевдо-комментариях:
1 2 3 4 |
body { background: # red /* игнорируется */ background: blue; /* тоже */ } |
И работает, если вернуть точку с запятой на место:
1 2 3 4 |
body { background: # red; /* игнорируется */ background: blue; /* обрабатывается */ } |
Размещение на той же и на следующей строке
Вот тут и подходит термин «псевдо». Может быть, и вовсе не стоит называть эту форму записи «комментарием». Из-за псевдо-комментария будет игнорироваться следующее за ним свойство. В следующем примере фон будет синим:
1 2 3 4 5 |
body { // background: white !important; /* игнорируется */ background: blue; } |
Псевдо-комментарий, размещенный после правильно-объявленного свойства на одной с ним строке, будет подавлять выполнение свойства на следующей строке. В примере ниже фон будет белый, а не синий:
1 2 3 4 |
body { background: white; // следующая строка игнорируется... background: blue !important; } |
Даже в минифицированном виде, когда все свойства записаны в одну строку, псевдо-комментарий распространяется только на следом идущее свойство. В примере ниже первое объявление background игнорируется. Парсер доходит до символа конца строки, и второе объявление background уже распознается. (фон будет синим):
1 |
body { // background: red !important; background: blue; } |
Селекторы
Те же правила применяются и к селекторам. Весь селектор будет проигнорирован при наличии перед ним на одной с ним строке псевдо-комментария, даже однострочного:
1 2 3 |
// body { background: white !important; } |
Или на следующей строке:
1 2 3 4 |
// body { background: white !important; } |
Неправильная запись псевдо-комментариев
Работа псевдо-комментариев основана на правилах по обработке ошибок парсера. По сути, они работают из-за своей же неправильной записи.
Неизвестное значение
«Юзер агенты должны игнорировать неизвестные свойства». Объявления с нераспознанными именами свойств не будут работать. К примеру, свойство comment в селекторе body:
1 2 3 |
body { comment: 'текст или число'; } |
Недопустимые значения
«Юзер агенты должны игнорировать объявления с недопустимыми значениями.» Свойство color будет проигнорировано, так как его значение записано в формате строки:
1 2 3 |
body { color: "red"; } |
Неправильные объявления и выражения
«Юзер агенты должны обрабатывать неожиданные символы [или выражения] до конца объявления [или выражения], если соблюдено правило парных скобок (), [], {} и кавычек «».»
1 2 3 |
body { -color: red; } |
Несовпадение символов (), [], {}, «» и ‘’ приводит к игнорированию всего блока (и более опасно). Символы кавычек «» и ‘’ обрабатываются не так как скобки (), [], {}.
Символы кавычек
Символ одиночной кавычки в начале второй строки в примере ниже лишний, поэтому вторая и третья строки будут проигнорированы (т.е. фон будет красный):
1 2 3 4 5 |
body { background: red; 'background: white; /* не выполняется */ background: blue; /* тоже */ } |
Однако третье объявление после одной кавычки выполняется (т.е. фон будет золотым):
1 2 3 4 5 6 |
body { background: red; 'background: white; /* не выполняется */ background: blue; /* тоже */ background: gold; /* выполняется */ } |
В общем, символом кавычки нельзя закомментировать одну строку.
Символы скобок
В целом, символы скобок (), [], {} не стоит использовать в псевдо-комментариях, т.к. они оказывают куда больший эффект. Это связано с возможностью парсера распознавать блоки. Их использование может закомментировать больше одного блока за раз. Для полноты картины, рассмотрим некоторые из них.
К примеру, одиночный символ фигурной скобки заблокирует вообще все последующие стили до конца файла (не только текущего блока). То же самое применимо и к запятым, квадратным и обычным скобкам. В примере ниже сработает только свойство background: red;. Все остальные свойства будут пропущены вплоть до конца файла:
1 2 3 4 5 6 7 8 9 10 11 12 |
body { background: red; { /* *каждое* следующее свойство будет проигнорировано, включая все следующие селекторы вплоть до конца файла. */ background: white; color: aqua; margin: 5px; ... } |
При совпадении парных символов, внутренние свойства и последующие за закрывающим парным символом свойства будут проигнорированы. В примере ниже фон будет красный, а не золотой:
1 2 3 4 5 6 7 8 9 10 11 |
body { background: red; ( background: white; background: blue; background: fuchsia; ) background: gold; } |
Закрывающая запятая или квадратная скобка подавляют только следующее за ними свойство. В примере ниже фон будет голубой:
1 2 3 4 5 6 7 |
body { background: red; ] background: white; background: blue; } |
Однако закрывающая фигурная скобка } блокирует вообще все последующие свойства в селекторе. В примере ниже фон будет красный:
1 2 3 4 5 6 7 |
body { background: red; } background: white; background: blue; } |
@-правила
@-правила бывают в двух формах:
С фигурными скобками {…} как @media
С точкой с запятой ; как @charset
Псевдокомментарии в @-правилах ведут себя так же, как и в селекторах (т.е. блокируют весь блок).
Псевдо-комментарии в @-правилах с фигурными скобками
Если свойства находятся внутри селектора body, а тот в свою очередь внутри @-правила типа @keyframes, @media, @page или @font-face, и псевдо-комментарий поставить перед @-правилом на одной с ним строке, то весь блок стилей будет заблокирован:
1 2 3 4 5 |
// @media (min-width: 0) { body { background: white !important; } } |
Или на следующей строке:
1 2 3 4 5 6 |
// @media (min-width: 0) { body { background: white !important; } } |
Псевдо-комментарии в @-правилах без фигурных скобок
Псевдо-комментарии в неблоковых @-правилах типа @charset или @import блокируют все правило целиком. Псевдо-комментарий после ключевого слова блокирует всю конструкцию:
1 2 |
/* Псевдо-комментарий перед url блокирует весь @import */ @import // url('libs/normalize.css'); |
Однако псевдо-комментарий перед @-правилом блокирует и его и следующее за ним такое же правило. Так происходит потому, что парсер воспринимает псевдо-комментарий, как неправильно-записанное свойство, тем самым парсер его пропускает и ищет следующее за ним.
Поэтому псевдо-комментарий перед одним @import заблокирует серию из таких же @import’ов и первое свойство после последнего @import’а.
1 2 3 4 5 6 7 8 9 |
// @import url('libs/normalize.css'); /* НИ ОДНО из выражений ниже не будет применено, т.к. парсер воспринимает запись выше, как неправильную, и будет искать следующие фигурные скобки. */ @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
1 2 3 4 5 |
// @import url('libs/normalize.css'); {} /* теперь следующее выражение сработает */ @import url('libs/normalize.css'); |
Хотя это и весело поиграться с отладкой кода, лучше избегать псевдо-комментариев в @-правилах без фигурных скобок из-за их непредсказуемого поведения.
@-правила и неизвестные @-ключи
«Юзер агенты должны игнорировать неправильно записанные ключевые слова в @-правилах и все что следует за ними вплоть до конца блока, в котором @-правило записано, или до точки с запятой, или до следующих фигурных скобок»
Проиллюстрировать данную ситуацию можно с помощью неизвестного @-правила @comment с фигурными скобками. К примеру, правило ниже парсится до закрывающей фигурной скобки }, распознается неверно-записанным и пропускается:
1 2 3 |
@comment { Не ‘выполняется вообще. } |
Сперва, это может показаться вообще безвредным, блок просто пропускается целиком. Однако одинарная кавычка должна где-то закрыться. Из-за отсутствия второй одинарной закрывающей кавычки на той же строке мы получаем ошибку. Это приводит к тому, что если закрывающая фигурная скобка в @-правиле находится на той же строке, что и одинарная кавычка, то следующее @-правило или селектор тоже будут блокироваться.
1 2 3 4 |
@comment { Не ‘выполняется вообще } body { background: blue; } /* весь этот блок тоже будет заблокирован! */ |
Исправить это можно с помощью двойных кавычек:
1 2 3 4 |
@comment { " Не ‘выполняется вообще" } /* пофиксили */ body { background: blue; } /* этот селектор будет работать */ |
Или можно стереть фигурные скобки, перенести выражение на одну строку и добавить в конце точку с запятой:
1 2 3 |
@comment "Не ‘выполняется вообще"; body { background: blue; } /* работает */ |
Или на следующей строке:
1 2 3 4 |
@comment " Не ‘выполняется вообще"; body { background: blue; } /* работает */ |
Препроцессоры
В различных препроцессорах CSS поддерживаются схожие однострочные и многострочные комментарии.
Sass
«В Sass поддерживаются стандартные многострочные CSS комментарии /* */ и однострочные //. Многострочные комментарии при компиляции сохраняются, а однострочные удаляются.»
В режиме сжатия, обычно, удаляются все комментарии, если открывающий символ не начинается с /*!. Однострочные комментарии также можно оставить на выходе с помощью символа #.
1 2 3 |
body { # background: red; } |
Less
«Можно использовать и блочные и однострочные комментарии.»
Я не очень понимаю, в каких случаях в Less комментарии удаляются или остаются при компиляции. По информации с сайта StackOverflow линейные комментарии сохранятся на выходе, если они находятся внутри фигурных скобок.
Stylus
В Stylus тоже присутствуют как /* */, так и // комментарии. Но они будут удаляться при компиляции при включенной директиве compress. Если вам нужно, чтобы многострочные комментарии всегда оставались на выходе, воспользуйтесь многострочным буферным комментарием.
«Многострочные комментарии не удаляются, если они начинаются с /*!. В таком случае Stylus оставит их при компиляции, несмотря на режим сжатия.»
1 2 3 |
/*! * Этот комментарий останется. */ |
Лучшие практики
«Читабильность можно посчитать»
//www.python.org/dev/peps/pep-0020/>Zen of Python
Комментарии добавляют ясности кода, но его читаемость зависит не только от этого параметра. Псевдо-комментарии в CSS в меньшей мере предназначены для человека, но для парсера. Если вдруг вам нужно воспользоваться псевдо-комментариями:
Используйте символы C-подобных и unix комментариев // или #.
Разместите псевдо-комментарий над тем правилом, которое необходимо проигнорировать.
Или используйте пробел на одной строке с правилом, чтобы заблокировать только одно свойство # background: ignored;
Применение псевдо-комментариев:
Для отладки, особенно в сочетании с CSS панелью разработчика типа Web Developer extension (chrome, firefox, opera).
Для блокировки объявлений, селекторов или @-правил с фигурными скобками.
Не используйте псевдо-комментарии:
Для пояснения контекста в @-правилах без фигурных скобок (типа @import). Используйте обычные /*…*/
Избегайте символов кавычек. Человеку их сложно различить.
Избегайте скобок (), [], {} – они только усложнят вам работу с отладкой.
Не используйте псевдо-комментарии в готовом минимизированном коде – они не угробят ваш код, но все же пару лишних байт добавят.
Автор: David Kaye
Источник: //www.sitepoint.com/
Редакция: Команда webformyself.