Веб-разработка

индекс
236,88

Поддержка Data:URL Internet Explorer'ом

Многим известен данный способ отображения картинок, но особой популярностью он не пользуется, т.к. имеет проблемы с отображением в Internet Explorer (IE 6,7 — вообще не понимают, что им дают. А IE8 — принимает только картинки меньше 32кб).

Как же решить эту проблему?

Согласно RFC 2397, картинка (как и любые другие данные) должна быть представлена в следующем формате:
data:[<mediatype>][;base64],<data>

Изучим синтаксис более подробно:


dataurl := "data:" [ mediatype ] [ ";base64" ] "," data
mediatype := [ type "/" subtype ] *( ";" parameter )
data := *urlchar
parameter := attribute "=" value


Что же здесь такого интересного? Дело в том, что mediatype может содержать в себе дополнительные параметры (например, charset).
Соответственно, никто не запрещает нам хранить в нем свои данные.

К чему я все это?


Internet Explorer не может прочитать закодированные в base64 изображения, но спокойно может загрузить их, если мы укажем их url.
Так что, если указать url прямо в mediatype?

Сделать это можно примерно следующим образом:
data:image/png;src=habr.png;далее_base64_кодировка...

Это все, конечно, очень хорошо и интересно, но как же IE поймет, что дополнительный параметр и есть наша картинка?

Я предлагаю использовать behavior.
Это css-атрибут, поддерживаемый только в Internet Explorer и многим известный по такому проекту как PNGFix (одной из его реализаций).

Выглядеть это будет примерно так (код CSS):
#A {
background-image: url(data:image/png;src=habr.png;далее_base64_кодировка...);
behavior: url(ieb64.htc);
}


А это код ieb64.htc:
<public:attach event="ondocumentready" onevent="ondocumentready()" />
<script type="text/javascript">
function ondocumentready() {
  this.style.backgroundImage =
    this.currentStyle
      .backgroundImage
        .replace(
          /^url\s*\(\s*\"?\s*data:[^;]+;src=([^;]+);.*$/,
          function(all, url) {
            return "
url(\"" + url + "\")";
          }
        );
}

</script>


Посмотреть демонстрацию можно здесь.
А тут можно скачать htc-файл.

Спасибо за чтение!
+31
31 июля 2010, 17:29
38

комментарии (36)

+2
sunnybear #
и чем это круче IE6/7 хаков?
* html
*+html
+1
donnerjack13589 #
CSS-правило, полученное моим методом, проходит валидацию
+5
cst #
Все валидно что в браузере видно, метериал интересный но больше познавательный, чем практический.
+6
sunnybear #
:) * html, *+html — валидные селекторы
www.w3.org/TR/css3-selectors/
0
donnerjack13589 #
Спасибо :)
+1
aisergeev #
в любом случае спасибо автору за еще один вариант
0
sunnybear #
не знаю, с какой стороны это хороший вариант, — наличием behavior, грузящего проц?
+1
donnerjack13589 #
Вы, конечно, правы!
Но боюсь, что это не единственная (и вряд ли главная) вещь, которая будет грузить проц на IE.
+1
tenshi #
поэтому давайте грузить его ещё больше? х)
+1
ScRiPt #
я сейчас начал копать в сторону метода описанного тут… В Вашем же варианте требуется чтобы Javascript был включен.
0
donnerjack13589 #
блестяще!
0
sunnybear #
если уж говорить о методах, то проще и элегатнее data:URI+mhtml еще не придумали
+5
pepelsbey #
behaviour — это не атрибут, а свойство.
0
AMCDM #
А кто может мне объяснить в трех словах, зачем это нужно?
Я в верстке не шарю, стало интересно…
+2
tenshi #
чтобы уменьшить число запросов с 2 до 1, но увеличить трафик на 30% х)
0
AMCDM #
Хех) Спасибо)

Аж стало интересно, что покажет в адресной строке браузер, если кликнуть «Открыть изображение в новой вкладке»
0
tenshi #
<a href=«data:text/html;base64;charset=utf-8,ZGF0YSAtICYjMTA5MDsmIzEwNzI7JiMxMDgyOyYjMTA4NjsmIzEwODE7ICYjMTA3ODsmIzEwNzc7ICYjMTA4NzsmIzEwODg7JiMxMDg2OyYjMTA5MDsmIzEwODY7JiMxMDgyOyYjMTA4NjsmIzEwODM7ICYjMTA4OTsgJiMxMDkwOyYjMTA4NjsmIzEwOTU7JiMxMDgyOyYjMTA4MDsgJiMxMDc5OyYjMTA4ODsmIzEwNzc7JiMxMDg1OyYjMTA4MDsmIzExMDM7IHVyaSAmIzEwODI7JiMxMDcyOyYjMTA4MjsgJiMxMDgwOyBodHRwICYjMTA4MDsmIzEwODM7JiMxMDgwOyB1cm4=»data:text/html;base64;charset=utf-8,ZGF0YSAtICYjMTA5MDsmIzEwNzI7JiMxMDgyOyYjMTA4NjsmIzEwODE7ICYjMTA3ODsmIzEwNzc7ICYjMTA4NzsmIzEwODg7JiMxMDg2OyYjMTA5MDsmIzEwODY7JiMxMDgyOyYjMTA4NjsmIzEwODM7ICYjMTA4OTsgJiMxMDkwOyYjMTA4NjsmIzEwOTU7JiMxMDgyOyYjMTA4MDsgJiMxMDc5OyYjMTA4ODsmIzEwNzc7JiMxMDg1OyYjMTA4MDsmIzExMDM7IHVyaSAmIzEwODI7JiMxMDcyOyYjMTA4MjsgJiMxMDgwOyBodHRwICYjMTA4MDsmIzEwODM7JiMxMDgwOyB1cm4=
+1
tenshi #
data:text/html;base64;charset=utf-8,ZGF0YSAtICYjMTA5MDsmIzEwNzI7JiMxMDgyOyYjMTA4NjsmIzEwODE7ICYjMTA3ODsmIzEwNzc7ICYjMTA4NzsmIzEwODg7JiMxMDg2OyYjMTA5MDsmIzEwODY7JiMxMDgyOyYjMTA4NjsmIzEwODM7ICYjMTA4OTsgJiMxMDkwOyYjMTA4NjsmIzEwOTU7JiMxMDgyOyYjMTA4MDsgJiMxMDc5OyYjMTA4ODsmIzEwNzc7JiMxMDg1OyYjMTA4MDsmIzExMDM7IHVyaSAmIzEwODI7JiMxMDcyOyYjMTA4MjsgJiMxMDgwOyBodHRwICYjMTA4MDsmIzEwODM7JiMxMDgwOyB1cm4=
0
Iskin #
Кстати, трафик не всегда растёт на 30 %. Base64-кодирование конечно увеличивает, но потом gzip обратно уменьшает.
0
tenshi #
ничего подобного. для хорошего зипования нужны длинные повторяющиеся последовательности, а base64 за счёт преобразования 3 байт в 4 уменьшает их повторяемость, ибо исходные данные не выстроены по 3-хбайтовой сетке
0
rPman #
Большинство упаковщиков данных используют не только алгоритмы удаления повторяющихся блоков, но и уменьшения средней длинны слов (байт) за счет изменения количество бит в слове для каждого значения (читать Префиксный код и алгоритм Хаффмана)

Например конкретно эту последовательность base64 длиной 394 байт bzip2 уменьшил до 240 байт — 40%
0
tenshi #
исходный текст был длиной в 96 байт в utf-8
0
iStyx #
А вы не путаете с LZW? Разве gzip не по алгоритму Хаффмана работает?
0
tenshi #
да без разницы какой алгоритм, ибо в исходных данных увеличивается энтропия

«base64 » — YmFzZTY0ICA=
" base64 " — IGJhc2U2NCA=
" base64" — ICBiYXNlNjQ=

если исходный текст можно закодировать всего 2 словами " " и «base64», то для закодированного в base64 нам потребуется словарь по крупнее
0
iStyx #
Извините, вы ошибаетесь, gzip использует алгоритм DEFLATE, который построен на комбинации алгоритмов LZ77 и Хаффмана. И ему для хорошего сжатия не нужны «длинные повторяющиеся последовательности», ему важен размер таблицы вхождений и равномерность распределения.
0
tenshi #
это ты ошибаешься, ю считая, что сказал что-то принципиально иное х)
+1
dfn #
Чтобы уменьшить число http-запросов к серверу. Если есть много мелких картинок, то достаточно много времени тратится на такие запросы. С аналогичных
рассуждений, кстати, склеивают много картинок в одну (спрайтинг) — выгоднее грузить одну большую картинку одним запросом.
0
ArtyV #
Неплохо! Как раз думал, как попроще прифигачить data:uri не запариваясь за mhtml, только я наверное бы сделал это не через htc, а через одноразовый экспрешн
0
pashamesh #
Кстати, data:url очень хорош в email-письмах, отправляемых в html формате. Это позволяет обойти столь неприятную ситуацию, когда многие почтовые клиенты рубят все подгружаемые извне изображения
+1
vick #
эту ситуацию можно также обойти путем вложения картинок в само письмо.
0
madimp #
А почему нельзя просто написать 2 правила background-image:

Сначала background-image: url(habr.png);
Потом background-image: url(data:image/png; далее_base64_кодировка...); для тех кто поймет DataURI?
0
donnerjack13589 #
Второе правило перебьет первое
0
madimp #
У тех браузеров, что поймут второе, в которые не входят те, для которых написано первое.
0
donnerjack13589 #
Понимают все, но IE6,7 не могут отобразить.
0
madimp #
Досадно.
0
trilodi #
background-image: url(data:image/png; далее_base64_кодировка...);
*background-image: url(habr.png);
Вот такая конструкция не перебьет. Вторая сработает только для IE

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