Каскадные Таблицы Стилей / YUI CSS Grids — мина замедленного действия, или еще раз про инлайн-блоки, letter-spacing, word-spacing и браузеры

в 23:13, , рубрики: css2.1, inline-block, баги браузеров, вред бездумной копипасты, польза чтения спецификаций, метки: , , , ,

Думаю, мало кто возразит, что верстка на инлайн-блоках становится модной. Многие верстальщики, впервые узнав о них, видят в них улучшенную замену float-ам, и не зря — они и вправду дают куда больше свободы по части центрирования, вертикального выравнивания блоков и т.д. Неудивительно, что недавняя детальная статья коллеги psywalkerа (css-live.ru), посвященная самой неинтуитивной для начинающих особенности инлайн-блоков, оказалась столь полезной и востребованной.
Однако эта статья (точнее, комменты к ней) высветили еще одну проблему, которая сейчас расползается по вебу, как вирус, и очень скоро может «аукнуться» на множестве сайтов. Нет, катастрофы не случится, странички не превратятся в тыкву, буквы не провалятся в черную дыру (как тут:), даже колонки не разъедутся особо. Просто при очередном обновлении одного из Webkit-браузеров стройная сетка на некоторых страничках «скукожится», блоки прижмутся друг к другу и чуть сползут к левому краю, ломая красоту и огорчая дизайнеров.
Корень зла — в том, что «за бугром» многие вебмастера тоже не любят читать спецификации, предпочитая «метод тыка». И, увы, часто верят в магию. Одно из таких «магических решений» стремительно завоевывает нынешний веб:
.yui3-g {
letter-spacing: -0.31em; /* webkit: collapse white-space between units */
*letter-spacing: normal; /* reset IE < 8 */
word-spacing: -0.43em; /* IE < 8 && gecko: collapse white-space between units */
}

Этот код впервые появился во фреймворке YUI CSS Grids, где «сетка» строится именно на инлайн-блоках, и стремительно распространился по вебу путем копипасты. Казалось бы, он протестирован и надежно работает во всех ведущих браузерах, надежно решая «проблему», о которой пишет psywalker — пробелы между блоками.
Никого не смутило ни то, что исходник носит гордую приставку «бета» (а что сейчас не бета?), ни — вот это уже интереснее — почему для, казалось бы, одной задачи (убрать ширину одного и того же пробела) для разных браузеров используются разные «магические» значения. И никому не стало даже любопытно, почему так.
Прежде всего зададимся вопросом: зачем вообще два свойства? Почему нельзя обойтись одним?
Те, кто читал вышеупомянутую статью, наверное, уже всё поняли. Для остальных кратенько поясню.
По стандарту CSS2.1, для управления шириной межсловных пробелов (у нас именно они) предназначено свойство word-spacing. Его значение прибавляется к нормальной ширине пробела (колеблющейся где-то в пределах 0,2–0,4em для разных шрифтов… уже здесь пора бы насторожиться;). При отрицательных значениях ширина пробела уменьшается (следующее слово «наезжает» на него), однако…
...there may be implementation-specific limits

Опыт показывает, что Gecko-браузеры, Опера и IE8-9 не позволяют отрицательному word-spacing'у «сплющить» соседние слова теснее, чем вплотную. Webkit-браузеры и старые IE — позволяют. Оба поведения не противоречат спецификации — просто «implementation-specific limits» у них разные.
Но в Webkit-браузерах word-spacing работает только с текстом и инлайн-элементами. С инлайн-блоками он не работает вообще. Это давно известный их баг.
А вот letter-spacing (предназначенный для управления трекингом, напр. для разрядки текста) прекрасно работает и в Webkit-браузерах. Но его тоже нельзя использовать в качестве «универсальной отмычки»: на сей раз из-за Оперы, отказывающейся применять его… к межсловным пробелам (по-моему, Опера здесь не права: чем пробел не символ текста?).
Вот «методом тыка» кто-то и подобрал вышеуказанную комбинацию. Как она работает? А везде по-разному (о чем автор, похоже, догадывался, судя по комментариям). В Webkit-браузерах работает letter-spacing на «минус ширину пробела» в «эриале» и «гельветике» (при небольшом кегле попадание, считай, идеальное), word-spacing из-за бага игнорируется. В Опере работает только word-spacing: значение больше, чем нужно, но благодаря «браузероспецифичному лимиту» излишек никак не сказыается. В Gecko и новых IE работают оба, но «лимиты» спасают и тут. Наконец, в старых IE, строго говоря, всё работает неправильно (при крупном кегле, а особенно при смене шрифта на Times New Roman с более узкими пробелами, можно увидеть «наезд» блоков на пару пикселей), но там выручают… другие баги: с «фейковым» инлайн-блоком (inline + hasLayout) вместо настоящего, видимо, тоже появляется какой-то «лимит», а для элементов списков просто не возникает пробелов (а с ними и проблемы). Поэтому до сих пор никто не жаловался.
Но представьте, что произойдет, когда баг вебкитов внезапно пофиксят… ;)


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js