css
Как рождался CSS
Мне стало интересно: автор «Виолы» первым догадался отделить стилизацию элементов от структуры, или эта идея уже активно обсуждалась? Нашёл объёмное исследование о том, как зарождался CSS. Браузер «Виола» со своими собственными таблицами стилей там тоже упомянут.
Оказалось, что таблицы стилей как концепция гораздо старше самого веба. Ещё в конце
Язык разметки описывал структуру документа — слова, строки, страницы, интервалы, заголовки, подстрочные примечания, нумерацию, оглавление и т. д. — по принципу, близкому к HTML. Далее специальный компилятор использовал базу стилей (Style Database), где хранились определения оформления — шрифты, поля, отступы и прочие параметры.
Позже, с появлением веба и браузеров, эта идея перекочевала и туда. До стандартизации CSS существовало множество предложений о том, каким должен быть синтаксис таблиц стилей в вебе, в найденном мной исследовании можно с ними ознакомиться.
Синтаксис «Виолы» был не самым продуманным, не был и единственным, но был одним из первых — он появился уже в 1993 году.
STG: таблицы стилей в «Виоле»
Чем меня в своё время поразила «Виола» в самое сердечко, — предвосхищением идеи стилевых таблиц и браузерного языка программирования. Мне очень нравятся такие пророческие находки, хочется увидеть как они были сделаны и как автор до этого вообще дошёл.
«Википедия» в своё время заронила интерес, но полностью тему не раскрыла — про стилевые таблицы этого браузера там написано совсем мало, да ещё и с ошибками, как я смог убедиться. «Спецификация», если так можно назвать страницу, сохранившуюся благодаря стараниям
Оказалось — показалось, в браузере было реализовано даже меньше.
Несмотря на простоту спецификации, «Виола» мало что из описанного умела, пришлось дописать. Сейчас всё, надеюсь, работает так, как задумывал автор. Интересный момент — код на Си только парсит стили, остальным занимается интерпретируемый код, написанный на языке программирования, реализованный в браузере.
Стилевые таблицы подключаются тегом LINK и имеют расширение .stg, хотя это не обязательно, но в спецификации так:
<link rel="style" href="HTML_sodium.stg">Таблиц может быть подключено много и они работают «вниз», то есть от момента включения в код ниже места включения применяются стили, которые там описаны.
Селекторов всего два — можно выбрать тег или стиль тега (это работает немного не так как в CSS):
(BODY,SECTION
BGColor=green
FGColor=red
(P)
(KBD
BDColor=black
border=1
)
)Что тут написано? Что в тегах BODY и SECTION будет зелёный фон и красный цвет шрифта, а кроме того эти атрибуты унаследуют теги P и KBD, причём у последнего будет ещё и чёрный бордюр.
Атрибутов, к слову немного, в основном это характеристики шрифтов, цвет, бордюр
Ещё есть стилизованный браузером элементы, некие встроенные стили (например, WARNING, NOTE и так далее), которые можно навешивать на произвольные теги при помощи атрибута STYLE. На картинке пример того как выглядит встроенный стиль WARNING: оранжевый бордюр и картинка.
К тегам, помеченным атрибутом STYLE тоже можно применять собственные стили:
(P
BGColor=white
FGColor=black
{STYLE "WARNING"
FGColor=red
fontSlant=italic
}
)У тега P здесь белый фон и чёрный цвет шрифта, а если у него есть атрибут STYLE, равный WARNING, то добавляются ещё два стиля, определяющие красный шрифт наклонного начертания.
В коде как будто бы есть небольшой намёк на то, что селектор должен работать и с другими атрибутами (да и синтаксис стилевых таблиц это позволяет), но в спецификации про это нигде не сказано. Я пока тоже не реализовал.
На второй картинке тест со страницы спецификации, который проходит дописанный браузер. В самом тесте, кстати, тоже были две ошибки — не закрытая скобка и неправильные стили синего блока.
Заказ щедро оплачен
На днях баловался со стилями магазина «Озон» при помощи браузерного плагина Stylus — избавлялся от навязчивой рекламы внутри списка товаров. Это те бесячие предложения, которые игнорируют выбранную сортировку.
Скрипт приводить не буду, всё равно его приходится править время от времени — у «Озона» используется фреймворк «vue»
Заодно, в качестве баловства, заменил себе надпись «Заказ оплачен» на «Заказ щедро оплачен». Эту часть могу привести, может
.tsBodyM[data-widget="orderStatus"]::before {
content: 'Заказ щедро оплачен';
color: var(--ozTextPrimaryNegative);
font-size: var(--bodyMFont);
line-height: 1.29;
}
«Магический шар» ★
Свой путь в вебе я начинал с вёрстки — в конце
Из того набора атрибутов и тегов, что тогда были доступны, мне довелось использовать всё, кроме
Использование его в те годы могло бы выглядеть
<A HREF=/cgi-bin/action.pl><IMG SRC=/i/pict.gif WIDTH=200 HEIGHT=100 ISMAP></A>Чтобы вы прочувствовали дух времени, специально пишу большими буквами (так было принято) и без кавычек (экономили и на этом тоже).
При нажатии на картинку с этим атрибутом и ссылкой к урлу добавляются в качестве параметров координаты курсора на картинке. Видимо это нужно было
Я уже несколько лет как не верстаю,
И вот два года назад меня осенило использовать его в вёрстке «магического шара» из фильма «Трасса 60». Если не смотрели, там у главного героя был шар, который давал ответы на заданные вопросы, если его потрясти.
Мой шар «отвечает» в том случае, если на нём щёлкнуть мышкой. В качестве случайных значений используются координаты, передаваемые при помощи атрибута ISMAP, плюс картинка вращается при помощи CSS, поэтому даже под неподвижным курсором всегда разные координаты.
Принцип получился довольно простой — все координаты, в которые пользователь может щёлкнуть мышкой, заданы как идентификаторы скрытых слоёв, лежащих поверх рисунка шара. Как только пользователь выбирает
HTML с таким подходом становится довольно жирным — у меня получился 1,2 мегабайта, но по нынешним временам это не объём.
Вообще я планировал дооформить шар и сгенерировать координаты более экономно (сейчас я генерирую под охватывающий квадрат, получается, что у меня есть бесполезные строки в его углах), но проект два года провалялся в локальном репозитории, а воз и ныне там.
Поэтому решил выложить что есть,
text-decoration-line

Есть такая договорённость в вебе — псевдоссылки (которые похожи на ссылки, но не уводят со страницы) подчёркивать не сплошной чертой, а прерывистой или точечной. Обычно такую черту делают бордюром снизу тега, но если настоящие ссылки сделаны через
Сейчас браузеры начинают поддерживать свойство
Оказалось, в данном случае — доверяй, но проверяй. «Сафари» (по крайней мере восьмая версия)
Короткий способ определить есть ли поддержка dataURI
Придумал короткий способ определить поддержку data URI в браузере:
<script src="data:text/javascript,self.dataURI=1"></script>Потом просто проверяете у window свойство dataURI, если оно есть, то есть и поддержка. Способ не работает в IE8 и IE9 — тот и другой не умеют загружать Джаваскрипт этим образом. Собственно, меня это не волнует — мне как раз и нужно определить, что Джаваскрипт так работает, но если вам нужно не это, то должен работать вот такой способ:
<link rel="stylesheet" href="data:text/css,html{font-size:99px}">То есть устанавливаем у тега HTML
/99/.test($('html').css('font')); // true, если есть поддержка dataURIUse SVG
Поскольку «Макбук» у меня с «ретиной», я давно озаботился тем, чтобы продукт, разработкой которого я управляю, хорошо смотрелся и на «ретине» тоже. Я считаю за такими экранами будущее и не грех позаботиться об этом будущем уже в настоящем. Если уж и не внедрить везде, так хоть научиться верстать.
Одним из главных помощников в такой вёрстке является, без сомнения, формаг СВГ — формат векторной графики, который на данный момент поддерживают все распространённые браузеры (включая ИЕ, с девятой версии). Особенно приятно, что его можно включать прямо внутрь ХТМЛя, это очень удобно — если СВГ используется для кучи мелких значков на странице, то не будет лишних соединений с сервером — ведь всё грузится вместе с основным кодом.
Но встаёт другая проблема — проблема повторного использования. Если одни и те же значки присутствуют на странице в изобилии, страница будет распухать, что печально.
К счастью, есть выход. СВГ — гибкая штука, в этом формате есть возможность использования частей изображения повторно. Первым шагом нужно определить
<svg style="display:none">
<symbol id="folder" viewBox="0 0 49.833 67.167">
<!-- код не рабочий, только для примера -->
<path d="M15.938,67.…"/>
<path d="M3.59,30.531c…"/>
</symbol>
<symbol id="file" viewBox="0 0 49.833 67.167">
<path d="M12.233c0.…"/>
<path d="M3.28C2.76…"/>
</symbol>
</svg>Тут у нас два изображения — folder и file, на которые мы можем сослаться следующим образом:
<svg width="28" height="37">
<use xlink:href="#folder"/>
</svg>
<svg width="28" height="37">
<use xlink:href="#file"/>
</svg>Таких вставок может быть сколько угодно и все они будут использовать одни и те же изображения, описанные
svg.green {
fill: green;
}
svg.red {
fill: red;
}Классы можно повесить на ссылающиеся теги СВГ, жаль только этот способ полон ограничений. Кроме как в ФФ более избирательные селекторы использовать не удаётся — всё, что ниже тега use для таблицы стилей как будто не существует. Если и есть
Chrome (but not Safari) CSS hack
Обратил внимание, что половина интернета сбилась с ног в попытках найти стильевой хак для «Хрома», который не срабатывал бы в «Сафари». Неясно почему его ещё никто не придумал, у меня на это ушла пара минут:
@supports (top: 0__qem) {
.chrome-only {
border: 1px solid #000; /* стиль только для Chrome (не Safari) */
}
}Работает начиная
Эта стандартная конструкция предназначена для проверки — поддерживает ли браузер указанное свойство. Недостаточно подставить туда свойство с префиксом webkit — сейчас многие браузеры читают такие свойства как свои,
Чтобы отсечь лишнее, я использую нестандартную единицу измерения Вебкита — «__qem», я о ней писал несколько лет назад. Вместе получается, что стиль в «Сафари» не срабатывает, потому что тот не поддерживает «@supports», а в остальных браузерах — потому что они не поддерживают «__qem».
Естественно, обёртки над Вебкитом (новая «Опера», браузер «Яндекса» и прочее) стиль увидят — но на то они и обёртки.
CSS variables
Константы в ЦСС (которые
Идея замечательная — если у вас есть
:root {
--bgcolor: #000;
}
body {
background-color: var(--bgcolor);
}Как видите, префикс «var» сменился на два минуса в полном соответствии с изменениями в стандарте. Чем не устроил предыдущий синтаксис мне не интересно, но этот префикс набирать определённо быстрее —
IE9 и таблицы

В продукте, которым я занимаюсь, минимальная версия Эксплорера, которую я решил поддерживать — девятая. В будущем я хочу поднять это требование до десятой, а пока приходится жить с тем, что есть — клиенты не готовы к резким переменам и я их понимаю.
Наткнулись на странную проблему в этой версии Эксплорера — некоторые таблицы выглядят как на снимке выше — ячейки в строках иногда выпирают вправо безо всякой видимой причины.
Дело оказалось в пробелах между ячейками — верстальщик отформатировал шаблон, чтобы он лучше читался, и все браузеры всё показали правильно, один девятый Эксплорер сошёл с ума. Лечится проблема запросто — либо убираем форматирование в шаблоне, либо убираем его прямо в браузере.
Я выбрал второй путь. Пусть лучше шаблон выглядит читаемо, а костыль для девятого Эксплорера всегда можно будет убрать лёгким движением руки. Выглядит он вот так, кстати (используется jQuery, само собой):
$("table tr").contents().filter(function() {
return this.nodeType == 3;
}).remove();Свёртка в вебе
Я
<style>
.edge {
-webkit-filter: url(#edge);
filter: url(#edge);
}
</style>
<svg style="width: 0; height: 0">
<filter id="edge">
<feConvolveMatrix kernelMatrix="-1 -1 -1 -1 9 -1 -1 -1 -1" />
</filter>
</svg>
<image src="sample.jpg" class="edge">Магические числа в матрице — специальное ядро.
Впрочем, и раньше можно было внедрить в ХТМЛ
С таким возможностями, немудрено, что онлайновых «фотошопов» развелось, как грязи. Немного помучавшись с консолью, можно найти способ как поменять матрицу и это тоже будет работать! Например, вот так меняется число по центру (где у меня в примере девятка записана):
var arr = document.getElementById('edge').childNodes;
for (var i = 0; i < arr.length; i++) {
if (arr[i].kernelMatrix) {
arr[i].kernelMatrix.baseVal.getItem(4).value = newvalue;
break;
}
}Осталось только соединить этот код с «крутилкой» и готов
CSS parent selector
Тема родительского селектора в ЦСС всплывает ужа давно, если не ошибаюсь, в Вебките даже
Что такое родительский селектор? О, это очень простая и мощная штука, к примеру, если клиент выбрал
.window < :checked { /* экспериментальный синтаксис родительского селектора из Вебкита */
display: none;
}Сразу скажу, задумка мощная, а реализация плохая. Какую проблему тут видно сразу? Непонятно что значает этот знак. Непосредственного родителя мы здесь выбираем или любого? Если непосредственного, как выбрать любого и наоборот?
Все синтаксисы родительского селектора (включая, например, :parent) грешат
Мне бы хотелось видеть абсолютную гибкость в отношении родительского селектора и мне кажется, синтаксис тут напрашивается сам собой:
.window > (:checked ~ :checked) {
display: none;
}Всё сразу становится логично, на мой взгляд: применить стиль к тегу с классом window, у которого два непосредственных
IE 10 CSS hack
Придумал CSS-хак для Эксплорера
@media , {
.:valid, body {
background: red; /* будет красным в Internet Explorer 10 (режим совместимости) */
}
}Проверил при помощи сайта «Браузер шотс» ложные срабатывания, как будто всё в порядке, их нет. Не проверял на IE11, не знаю будет ли там работать. Если
Так же придумал новый хак для обычного режима IE 10:
@media all\0 {
_:valid, body {
background: red; /* будет красным в IE 10 */
}
}И ещё один:
_:valid\0, body {
background: green; /* будет зелёным в IE10 */
}Так же не тестировал на IE11 (мне негде).
-khtml-border-radius
На «Хабре» постоянно всплывает тема того, что, якобы, никогда не существовало свойства «-

Вот на скриншоте вверху версия 4.4 отображает свойство -
Размытие шрифта на Ретине в Сафари

Как и ожидалось, Ретина ещё
Заменили на обычное свойство opacity, стало выглядеть, как на скриншоте справа.
Оптимизация картинок поворотом
Есть такой старый трюк, который с развитием CSS получил новое прочтение. Дело в том, что при упаковке изображения в графические форматы, в основном, сканируют и упаковывают изображение, двигаясь по его линиям слева направо. Первом об этом на русском языке написал, думаю, Лебедев, вот что написано в книге «Реактивные вебсайты», соавтором которой я являюсь:
Изображения GIF хорошо поддаются оптимизации. В параграфе №8 «Ководства» Артемия Лебедева есть небольшое, но интересное исследование особенностей этого формата. Вывод из параграфа простой: чем больше на картинке горизонтальных линий одного цвета, тем лучше сжимается изображение. Алгоритм компрессии LZW, применяемый в GIF, вообще лучше сжимает регулярные горизонтальные структуры в пределах одной линии.
Соответственно, если есть возможность повернуть картинку, то, бывает, она сжимается лучше.
Но не всегда так везёт, гораздо чаще, согласитесь, встречаются изображения, которые повернуть нельзя. Значит о способе забываем?
Вот тут нам и пригодятся нововведения в ЦСС. Берём свою картинку, сохраняем ещё три копии повёрнутые на 90°, 180° и 270°, а потом все четыре изображения оптимизируем, выбираем то, которое меньше занимает. А дальше просто поворачиваем его при помощи ЦСС (я ещё фильтр для старых ИЕ добавил и некоторые свойства для других браузеров):
.rotate90 {
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); /* IE 5.5+ */
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"; /* IE 8 */
-ms-transform: rotate(90deg); /* IE 9 */
-o-transform: rotate(90deg); /* Opera 10.5+ */
-webkit-transform: rotate(90deg); /* Chrome, Opera 15+, Safari 3.1+, Android 2.1+, iOS 3.2+ */
-moz-transform: rotate(90deg); /* FF 3.5+ */
transform: rotate(90deg); /* FF 16+, IE 10+, Opera 12.1-14.99 */
}Картинка поворачивается браузером и визуально остаётся как была.
Вообще, конечно, можно поворачивать на любой угол, если фон картинки прозрачный или совпадает с окружающим фоном, но в старых ИЕ для этого придётся использовать другой фильтр — Matrix, формула расчёта параметров такая:
progid:DXImageTransform.Microsoft.Matrix(
M11 = cos(угол),
M12 = -sin(угол),
M21 = sin(угол),
M22 = cos(угол),
sizingMethod = 'auto expand'
);Метод не лишён недостатков, конечно.
Как узнать, что пользователь печатает веб-страницу на принтере?
У нас тут задача в процессе производства продукта появилась — занести в лог, что пользователь сделал попытку печати
Придумал такое решение — перед печатью браузер накладывает стиль CSS для печати, если он есть, этим можно воспользоваться:
@media print {
body {
background: url(http://example.org/user-tries-to-print.php);
}
}Браузер попытается загрузить фоновое изображение (и загружает, я попробовал), выполнится серверный скрипт и положит в логи то, что нужно.
Обнаружение Ретины
Поскольку у меня теперь «Макбук» с Ретиной, я изучаю вопрос как сделать сайты пригодными к отображению на таких экранах. Возможно читатели с Ретинами уже заметили
Наиболее животрепещущий вопрос — подготовка изображений для Ретины.
Напомню, что Ретина — технология Эпл, ставшая уже нарицательной, заключающаяся в примерении экранов высокого разрешения (например, на моём ноуте это 2560×1600) с отображением на нём обычной графики так, как бы это выглядело на экранах вдвое низкого разрешения. При этом шрифт смотрится просто великолепно, как на бумаге, а вот с картинками беда.
В вебе бо́льшая часть графики выглядит не очень (хотя масса сайтов уже подготовилась). Для того, чтобы стало хорошо, все изображения надо готовить вдвое большего размера, при этом указывая для них в коде вдвое меньший размер, тогда проявляется вся мощь Ретины — будет видно самые мелкие детали изображения и пропадёт размытие.
Пока ещё не у всех Ретины, хочется, чтобы клиенты, у которых её нет, не грузили лишнего. К сожалению, загвоздка в том, что браузеры пока не научились сообщать серверу, что мы имеем дело с таким (пока) необычным экраном и есть только клиенские способы выяснить это.
Появилось уже несколько библиотек, которые на стороне клиента делают замены картинок на подходящие под тип экрана. Это всё равно вызывает лиший трафик, так как некоторые картинки успевают загрузиться, а если изображений много, замена, бывает, подтормаживает.
Насколько я вижу, даже в Эпл не придумали достойной альтернативы этой техники и у них сайт «улучшается» по мере загрузки — сначала грузятся обычные изображения, потом «ретиновые», если это необходимо.
Вообще, у Джипега, например, есть прогрессивная загрузка — по мере загрузки «прогрессивное» изображение не грузится сверху вниз, а становится всё чётче и чётче (хорошая иллюстрация этого есть в одном из параграфов «Ководства»). Надо будет поэксперементировать в эту сторону — нельзя ли прервать передачу на нужной детализации, если экран не «ретиновый».
А пока, у меня такое решение. Используем
На стороне клиента первой строкой каждой нашей страницы ставим проверку по «ретиновые» экраны с установкой «печенья»:
<script>if(window.devicePixelRatio>=2)document.cookie='retina=1'</script>Этот скрипт выполнится первым и все дальнейшие запросы на сервер будут содержать строку «retina=1», если мы имеем дело с Ретиной. Все изображения, для которых у нас есть две копии — обычная и «ретиновая» (в два раза большая) называем одинаково, но с постфиксом «@2x» для большей, при этом в коде указываем данные разрешения для более мелкой картинки:
<img src="/images/owl@2x.jpg" width="400" height="560" alt="Совушка">Сейчас, конечно, Апач теряет популярность, но я воспользуюсь синтаксисом mod_rewrite, желающие могут переделать в Энжин Икс
RewriteEngine On
RewriteCond %{HTTP_COOKIE} !retina=1
RewriteRule (.*)@2x\.(gif|jpe?g|png|webp) $1.$2 [L,NC]Этот код означает, что если не установлено «печенье» «retina=1», то нужно убрать постфикс «@2x» из имени картинки.
В итоге, если у нас Ретина, «печенька» ставится в самом начале, все дальнейшие запросы к серверу идут с ней и картинки грузятся как указано в коде — например, если указано «owl@2x.jpg», то эта картинка и грузится.
Если у нас обычный экран, «печеньки» нет, запросы к серверу идут без неё и из картинок вырезается постфикс «@2x», т. е. картинка «cat.jpg» грузится по своему имени, а вместо «owl@2x.jpg» загрузится «owl.jpg».
Voilà!
Инвертирование в CSS без фильтров
Немногие знают, что инвертирование части
Я говорю о поддержке значения invert свойства

Наложить сверху элемент с аутлайном можно любым способом, я использовал position: absolute:
<style>
.invert {
outline: invert solid 75px;
position: absolute;
width: 50px; height: 0;
margin: 75px 0 0 75px;
}
.content {
width: 200px;
height: 150px;
position: absolute;
left: 200px;
top: 200px;
text-align: center;
}
</style>
<div class="content">
<div class="invert"></div>
<img src="/i/foto.jpg">
</div>Для того, чтобы высчитать размеры накрывающего блока, нужно немного арифметики. У меня большую размерность имеет ширина (накрываемый блок размером 200×150), поэтому будем плясать от неё. Высота накрывающего блока должна быть в этом случае равна нулю, ширина — разности между шириной и высотой накрываемого блока,
Думаю, ни для кого не составит труда самостоятельно провести вычисления для обратного случая — когда высота больше ширины.
Тонкое подчёркивание ссылок с разрывами на буквах «р», «у» и других
У меня на сайте два изменения.
Но просто сделать так же не интересно, и я решил сделать лучше. Спорно получилось ли лучше, тут есть простор для экспериментов.
Подчёркивание ссылок и Тёмы и Ильи сделано одинаково — убрано родное подчёркивание, а взамен установлено свойство
Сначала позвольте показать что получилось, обратите внимание на разрыв на хвостике «р», когда я добился более плотного прилегания, оказалось, что перечёркивание хвостов меня не устраивает, хорошо что удалось это поправить:

Собственно, мне захотелось сначала исправить этот недостаток — слишком далеко отстоящее подчёркивание. Готовое решение у меня было, я
Я довольно долго эксперементировал и нашёл,
И вот тут меня ждала неприятность. Дело в том, что некоторое время назад появился способ, позволяющий узнать какие сайты вы посещали; интернет пестрел скриптами, которые в шутку журили вас, если обнаруживали, что вы до этого посещали
Способ проверки простой — на экран выводится ссылка, посещение которой пользователем мы хотим проверить, а потом мы смотрим у неё, скажем, цвет или другой параметр, который мы установили различающимся для посещённых и не посещённых ссылок. Я хорошо помню эту историю, потому что сделал на основе этого скрипт, который определял логинились ли вы в Гмейл — я просто смотрел загружал ли ваш браузер определённые ресурсы, которые грузятся только после логина. Но прежде чем я придумал как это можно практически использовать, дыру начали закрывать, так что скрипт не пригодился.
Естественно, браузеры не могли не отреагировать на эту дыру. Кажется, Файерфокс первым отреагировавшим на проблему — они предложили «врать» разработчику о стиле посещённых ссылок и разрешили менять для них только строго определённый список
Увы, это меняет многое. У меня для того, чтобы цвет посещённых ссылок не различался с цветом подчёркивания, нужно было поменять
В голове перед сном я прокручивал список разрешённых к изменению свойств и одно из них,

Теперь, если выставить его в качестве стиля заднего фона ссылки, а потом ещё задать цвет фона, ссылка оказывается аккуратно подчёркнутой в нужном мне, регулируемом месте (я же могу сделать прозрачным любой пиксель в фоне).
Ок, это сработало для посещённых ссылок, но в «Хроме» и «Сафари» меня ждал неприятный сюрприз: на мгновение, до того как браузер успевал отрисовать мой ГИФ на заднем фоне, все ссылки выглядели уродливо: был виден их цветной задний фон:

Я подумал, что мне бы помогло, если я бы
Получился следующий стиль:
a {
background: #00e url(data:image/gif;base64,R0lGODlhAQA7APABAP …и так далее… AAACCISPqcvtEEwBADs=) 0 100% repeat-x;
background-image: -webkit-linear-gradient(90deg, #fff 0, #fff 2px, rgba(0,0,0,0) 2px, #fff 3px, #fff 59px);
}Это полностью решило проблему — мигание на вебкитовских браузерах пропало. Кстати, я применил стиль линейного градиента, в новом формате — он работает в «Сафари» с версии 5.1 и в «Хроме» с десятой. Мне кажется, в этом нет ничего страшного — доля старых браузеров, в данном случае, ничтожна мала.
Когда я поставил подчёркивание куда мне хочется, возникла другая проблема. Эстетическая. Подчёркивание довольно уродливо перечёркивало нижние выносные элементы букв. На память, по аналогии, пришло моё баловство с фильтром Glow в Интернет Эксплорере. Там удавалось добиться интересных эффектов с задним фоном, поскольку эффект ложится и на него. Тут у меня ситуация такая же, но фильтров больше не существует, правда есть их реинкарнация —W3C заботливо слизало идею в другом синтаксисе.
После некоторых экспериментов, я решил, что тут подходит
a {
text-shadow: 1px -1px 1px white, -1px -1px 1px white, 2px -1px 2px white, -2px -1px 2px white;
}В браузерах, которые этот стиль не поддерживают, подчёркивание просто не будет разорвано.
Стиль, в результате выглядит примерно так:
a {
text-shadow: 1px -1px 1px white, -1px -1px 1px white, 2px -1px 2px white, -2px -1px 2px white;
text-decoration: none;
background: #00e url(data:image/gif;base64,R0lGODlhAQA7APABAP … и так далее … AAACCISPqcvtEEwBADs=) 0 100% repeat-x;
background-image: -webkit-linear-gradient(90deg, #fff 0, #fff 2px, rgba(0,0,0,0) 2px, #fff 3px, #fff 59px);
}
a:visited {
color: #551a8b;
background-color: #551a8b;
}
a:hover {
background-color: red;
color: red;
}Очень компактно, без лишнего и с плавной деградацией для старых браузеров.