Firefox и Chrome перестали отображать мой спрайт после 655 изображений

эта проблема

Привет, я работаю со спрайтами и получил интересное поведение Firefox и Chrome. Когда у моего спрайта есть 655 изображений или меньше, мой спрайт работает нормально. Но когда он становится еще больше (656 или больше), он не отображается (просто становится невидимым). Я предполагаю, что проблема не в моем коде, так как он прекрасно работает в Opera и IE. Как так?


подробности

Я использую PHP для генерации спрайтов на лету. Сгенерированный HTML выглядит так:

<span class="_sprite_images _sprite_images_1"></span>
<span class="_sprite_images _sprite_images_0"></span>
<span class="_sprite_images _sprite_images_2"></span>
<span class="_sprite_images _sprite_images_3"></span>
<span class="_sprite_images _sprite_images_4"></span>
<span class="_sprite_images _sprite_images_5"></span>

[...]

и CSS выглядит так:

._sprite_images{background:url("../sprite_images/sprite.jpg");display:inline-block;}

._sprite_images_0{width:50px;height:50px;background-position:0 0px;}
._sprite_images_1{width:50px;height:50px;background-position:0 -50px;}
._sprite_images_2{width:50px;height:50px;background-position:0 -100px;}

[...]

Каждое изображение моих спрайтов имеет размер 50х50 (px) и составляет от 2 до 6 КБ. Я проверил их с типами JPG, PNG и GIF. Все получили одинаковые результаты.


скриншоты

655 изображений

655 изображений

656 изображений

1 ответ

Решение

Редактировать: Если причина проблемы не в целочисленном значении длины CSS, то это максимальный размер изображения, который могут обрабатывать браузеры. Это, вероятно, больше относится к делу, перечитывая ваш вопрос.

См. Firefox Bug 591822: изображения выше или шире 32767

Я использовал значение, рассчитанное ниже, чтобы быстро найти этот билет через Google;)

Если вы хотите, чтобы это работало, помогите cairo, базовой библиотеке изображений.

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

0: 0 0
...
654: 0 -32700
655: -50 0

и так далее. PHP:

$offset = -50;
$x = (int)($n/655) * $offset;
$y = $n % 655 * $offset;

У вас есть смещение -50 пикселей на спрайт.

Первый спрайт имеет смещение 0 ((1-1) * -50).

Для спрайта #655 смещение равно 654 * -50 который -32,700,

Спрайт #656 имеет смещение 655 * -50 который -32,750,

Спрайт #657 имеет смещение 656 * -50 который -32,800,

16-разрядное целочисленное Википедия без знака (половина слова, слово, короткий) варьируется от 0 в 65535Подписано коллегой из -32,768 в 32,767,

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

-32,800 is lower than -32,768

Что может произойти в этом случае, это то, что он получает туда-обратно:

-32,800 => 32

Если вы поместите спрайт на панель спрайтов по (относительной) координате -32 (что невозможно), вы сможете увидеть его.

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

Однако это может привести к некоторой стратегии быстрого решения, которая справедлива, если она работает быстро:

Как решить?

Вы можете попытаться (если это не влияет на алгоритмы рендеринга) использовать другой модуль. Поместите все свои спрайты в родительский элемент, например <div>:

<div class="sprites">
  <span class="img-1"></span>
  <span class="img-2"></span>
  <span class="img-3"></span>
  ...
  <span class="img-656"></span>
</div>

CSS:

div.sprites {font-size:50px;}
    div.sprites span {background: ... ; height: 1em; width: 1em;} /* default sprite definition*/
        div.sprites span.img-1 {background-position:0 0;}
        div.sprites span.img-2 {background-position:0 -1em;}
        div.sprites span.img-3 {background-position:0 -2em;}
        ...
        div.sprites span.img-656 {background-position:0 -655em;}

Это может быть более кросс-браузерной совместимостью, так как целочисленная длина каждого блока не намного меньше.

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

Другие вопросы по тегам