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

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

От автора: в спецификации об этом ничего не сказано, но в файлах CSS можно имитировать C-подобные и/или Unix комментарии (с небольшими оговорками). Множество статей было написано на эту тему. В данной же статье мы более подробно их рассмотрим.

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

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

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

Можно закомментировать целый блок:

/*
body {
  background: red;
}
*/

Также проигнорировать целый блок можно случайно, допустив ошибку:

body {
  background: red    /* потерянная точка с запятой */
  background: blue;      
}

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

body {
  background:
  background: blue; /* это свойство не сработает */
}

А это значит, что мы можем использовать неправильное объявление свойств, как…

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

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

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

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

h1, h2 {color: green }
h3, h4 & h5 {color: red } /* <= будет проигнорировано */
h6 {color: black }

И снова, второе и третье свойство не сработают, так как в их именах присутствуют лишние символы:

body {
  background: red;
  xbackground: white;    /* свойство не найдено */
  y background: blue;    /* название свойства записано некорректно */
}

Быстрый ликбез по английским символам, которые можно использовать для однострочных комментариев:

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;

Точка с запятой

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

Как упоминалось уже выше, при неправильном объявлении многострочного комментария, также игнорируется и внутреннее объявление. В примере ниже оба свойства background будут работать, как комментарии, из-за того, что парсер будет искать символ конца объявления (точка с запятой):

body {
  background:
  background: blue;      /* обе строки игнорируются */
}

Исправить это можно, добавив точку с запятой перед следующим свойством (т.е. свойство background: blue сработает):

body {
  background: ;          /* игнорируется */
  background: blue;      /* выполняется */
}

Тот же эффект с пропущенной точкой с запятой и в псевдо-комментариях:

body {
  background: # red   /* игнорируется */
  background: blue;   /* тоже */
}

И работает, если вернуть точку с запятой на место:

body {
  background: # red;  /* игнорируется */
  background: blue;   /* обрабатывается */
}

Размещение на той же и на следующей строке

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

body { 
  //
  background: white !important;  /* игнорируется */
  background: blue;
}

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

body {
  background: white; // следующая строка игнорируется... 
  background: blue !important;		
}

Даже в минифицированном виде, когда все свойства записаны в одну строку, псевдо-комментарий распространяется только на следом идущее свойство. В примере ниже первое объявление background игнорируется. Парсер доходит до символа конца строки, и второе объявление background уже распознается. (фон будет синим):

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

Селекторы

Те же правила применяются и к селекторам. Весь селектор будет проигнорирован при наличии перед ним на одной с ним строке псевдо-комментария, даже однострочного:

// body {
  background: white !important;
}

Или на следующей строке:

//
body {
  background: white !important;
}

Неправильная запись псевдо-комментариев

Работа псевдо-комментариев основана на правилах по обработке ошибок парсера. По сути, они работают из-за своей же неправильной записи.

Неизвестное значение

«Юзер агенты должны игнорировать неизвестные свойства». Объявления с нераспознанными именами свойств не будут работать. К примеру, свойство comment в селекторе body:

body {
  comment: 'текст или число';
}

Недопустимые значения

«Юзер агенты должны игнорировать объявления с недопустимыми значениями.» Свойство color будет проигнорировано, так как его значение записано в формате строки:

body {
  color: "red";
}

Неправильные объявления и выражения

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

body {
  -color: red;
}

Несовпадение символов (), [], {}, «» и ‘’ приводит к игнорированию всего блока (и более опасно). Символы кавычек «» и ‘’ обрабатываются не так как скобки (), [], {}.

Символы кавычек

Символ одиночной кавычки в начале второй строки в примере ниже лишний, поэтому вторая и третья строки будут проигнорированы (т.е. фон будет красный):

body {
  background: red;
  'background: white;  /* не выполняется */
  background: blue;    /* тоже */
}

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

body {
  background: red;
  'background: white;  /* не выполняется */
  background: blue;    /* тоже */
  background: gold;    /* выполняется */
}

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

Символы скобок

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

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

body {
  background: red;

  {  /* *каждое* следующее свойство будет проигнорировано, 
        включая все следующие селекторы вплоть до конца файла. */

  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, а тот в свою очередь внутри @-правила типа @keyframes, @media, @page или @font-face, и псевдо-комментарий поставить перед @-правилом на одной с ним строке, то весь блок стилей будет заблокирован:

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

Или на следующей строке:

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

Псевдо-комментарии в @-правилах без фигурных скобок

Псевдо-комментарии в неблоковых @-правилах типа @charset или @import блокируют все правило целиком. Псевдо-комментарий после ключевого слова блокирует всю конструкцию:

/* Псевдо-комментарий перед url блокирует весь @import */
@import // url('libs/normalize.css');

Однако псевдо-комментарий перед @-правилом блокирует и его и следующее за ним такое же правило. Так происходит потому, что парсер воспринимает псевдо-комментарий, как неправильно-записанное свойство, тем самым парсер его пропускает и ищет следующее за ним.

Поэтому псевдо-комментарий перед одним @import заблокирует серию из таких же @import’ов и первое свойство после последнего @import’а.

// @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

// @import url('libs/normalize.css');

{}  /* теперь следующее выражение сработает */

@import url('libs/normalize.css');

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

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

«Юзер агенты должны игнорировать неправильно записанные ключевые слова в @-правилах и все что следует за ними вплоть до конца блока, в котором @-правило записано, или до точки с запятой, или до следующих фигурных скобок»

Проиллюстрировать данную ситуацию можно с помощью неизвестного @-правила @comment с фигурными скобками. К примеру, правило ниже парсится до закрывающей фигурной скобки }, распознается неверно-записанным и пропускается:

@comment { 
  Не ‘выполняется вообще.
}

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

@comment { 
  Не ‘выполняется вообще }

body { background: blue; }   /* весь этот блок тоже будет заблокирован! */

Исправить это можно с помощью двойных кавычек:

@comment { 
  " Не ‘выполняется вообще"  }  /* пофиксили */

body { background: blue; }   /* этот селектор будет работать */

Или можно стереть фигурные скобки, перенести выражение на одну строку и добавить в конце точку с запятой:

@comment "Не ‘выполняется вообще";

body { background: blue; }   /* работает */

Или на следующей строке:

@comment 
" Не ‘выполняется вообще";

body { background: blue; }   /* работает */

Препроцессоры

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

Sass

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

Источник

В режиме сжатия, обычно, удаляются все комментарии, если открывающий символ не начинается с /*!. Однострочные комментарии также можно оставить на выходе с помощью символа #.

body {
   # background: red; 
}

Less

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

Источник

Я не очень понимаю, в каких случаях в Less комментарии удаляются или остаются при компиляции. По информации с сайта StackOverflow линейные комментарии сохранятся на выходе, если они находятся внутри фигурных скобок.

Stylus

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

«Многострочные комментарии не удаляются, если они начинаются с /*!. В таком случае Stylus оставит их при компиляции, несмотря на режим сжатия.»

/*!
 * Этот комментарий останется.
 */

Источник

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

«Читабильность можно посчитать»

https://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

Источник: http://www.sitepoint.com/

Редакция: Команда webformyself.

Курс по CSS3

Прямо сейчас изучите CSS3 с нуля!

Смотреть курс

Метки:

Комментарии Вконтакте:

Комментарии Facebook:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree