Неприятный сюрприз в новых браузерах WebKit

Артем Фенога
01 июня 2009
Артем Фенога,
Дизайнер интерфейсов OWOX

Любой большой проект в вебе не может обойтись без изображений-спрайтов. В интернете есть масса статей и публикаций о пользе и целесообразности их применения, поэтому мы эту часть опустим. Перейдем сразу к сути вопроса.

Совсем недавно вышла вторая версия браузера Google Chrome. И мы выявили для себя проблему неотображения в этой версии наших спрайтов, хотя в первой версии все было отлично. К слову сказать, бета-версия Safari 4 также не показывала спрайты, но у нас была надежда, что это недоработка самого браузера и что в релизе ее исправят. Теперь же, после выхода второй версии Хрома, стало понятно, что это не недоработка, а некая особенность в движке WebKit, на котором работают и Сафари и Хром.


Наша реализация спрайтов

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

Вот фрагмент спрайта, который в ширину растянулся более чем на 1000 пикселов и собрал в себе 40 отдельных иконок.

фрагмент спрайта

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

<div class="cart">
<a href="#" class="sprite"><i></i>В корзине</a>
<div>

Как это работает? Изображение-спрайт позиционируется внутри строчного элемента <i></i>, для которого прописан внутренний отступ размером в 18 пикселов (стандартная иконка 16 пикселов + 2 пиксела на отступ), затем он выносится отрицательным внешним отступом за пределы родительского элемента, в данном случае это ссылка.

Вот как выглядит общее описание спрайта в стилях CSS и конкретное позиционирование иконки корзины:

.sprite i {
margin-left: -18px;
padding-right:18px;
background:url(i/sprite.gif) no-repeat 0 0
}
.cart .sprite i{background-position:-148px 0}

Естественно, что для ИЕ такого описания будет мало. Он никак не хочет показывать элемент спрайта , если он не имеет определения позиции (hasLayout). Поэтому только для браузеров ИЕ в отдельном файле стилей style-ie.css мы прописываем:

.sprite i {zoom:1}

или

.sprite i {position:absolute}

Из всех вариантов дать определение позиции элементу в ИЕ, это как раз те два относительно безболезненных способа решения данной проблемы.

В итоге, на сайте мы увидим такую красоту:

Неприятный сюрприз в новых браузерах

Такая реализация спрайтов отлично работает в файерфоксе, опере, хроме, ИЕ (6, 7 и 8 версии). В сафари иногда встречались особенности отображения, но их можно было решить всего лишь добавив

.sprite {white-space:nowrap}

или

.sprite i {vertical-align:top}


«Хром редьки не слаще»

После релиза Хрома второй версии и обнаружения особенности отображения наших спрайтов в браузерах WebKit, нужно было заново пересмотреть нашу реализацию спрайтов и понять в чем же причина этой проблемы, откуда у нее растут корни.

Вооружившись скальпелем и детально посмотрев в Хроме Inspect Element спрайта, стало понятно, что браузер не определяет ему высоту и ширину. Поэтому хром и не показывает спрайт. Естественно, если мы просто допишем строчному элементу высоту и ширину — это не поможет. Поэтому спрайту нужно дописать такое css-свойство, которое сделало его как бы блочным элементом, но в тоже время не повлияв на его соседей. Таким свойством является position:absolute. Абсолютное позиционирование выбивает спрайт из общего потока, делает его блочным, но в тоже время спрайт не влияет на своих соседей и не ломает верстку.

Первый вариант решения нашей проблемы такой:

.sprite i {
position: absolute;
width: 18px;
height:18px;
margin-left: -18px;
background:url(i/sprite.gif) no-repeat 0 0
}

Но не все так просто. Каждый наш проект очень глубоко использует спрайты в самых разных ипостасях. И нам очень не хотелось кардинально менять верстку спрайтов в уже реализованных проектах, потому что это может повлечь за собой другие глобальные изменения. Поэтому первый вариант откладываем в сторону и занимаемся поиском другого решения.

В процессе работы была замечена одна особенность:

Неприятный сюрприз в новых браузерах

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

Итак, теперь стала понятна суть этой особенности в браузерах WebKit, и вариант решения пришел сам собой — нужно определить такое css-свойство, которое добавит перед спрайтом контент.

Вот наше решение:

.sprite i:before{content:''}

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

Таким образом, проблема решена, спрайт так и остался строчным элементом, структура не поменялась и «новый велосипед» придумывать не пришлось.

Метка: css

Комментарии

03 июля 2009
Максим
display:inline-block не помогает?
03 июля 2009
Артем Фенога
display:inline-block не только не помогает. С ним спрайты не отображаются в файерфоксе, опере и сафари.

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