Поддержка 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-файл.

    Спасибо за чтение!

    Комментарии 36

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

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

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

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

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

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

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

                              Самое читаемое