
Любой большой проект в вебе не может обойтись без изображений-спрайтов. В интернете есть масса статей и публикаций о пользе и целесообразности их применения, поэтому мы эту часть опустим. Перейдем сразу к сути вопроса.
Совсем недавно вышла вторая версия браузера 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 как раз и добавляет пред нашим спрайтом контент, которого не будет нигде видно, и он ни на что не повлияет.
Таким образом, проблема решена, спрайт так и остался строчным элементом, структура не поменялась и «новый велосипед» придумывать не пришлось.
Комментарии