data URI
Пару лет назад я занимался проблемой data URL в Internet Explorer, добился определённых результатов, но то, что получилось, использовать было невозможно. Data URL (иногда его ещё называют «протокол data:») — возможность вставлять ресурсы (графику, CSS, JavaScript и так далее) в HTML код.
Подробнее о data URL можно узнать из свежей статьи на «Хабре» «Картинки в теле страницы с помощью data:URL». Хотелось только её дополнить двумя замечаниями: IE8b1 поддерживает data URL длиной не более 32Кб, в современных версиях других браузеров ограничений увидеть не удалось, Safari/Opera/FF показали изображения размером около 700Кб.
Вчера ночью мне пришла в голову идея как можно попытаться корректно совместить data URL и включение картинок через протокол mhtml. То, что у меня не получилось два года назад, получилось сейчас.
Результат — готовый код на PHP из двух функций. Первую функцию («bolk_data_uri_header») нужно вызвать в самом начале перед выводом любого вашего кода, вторую («bolk_data_uri») собственно для включения картинки в код.
Надеюсь на примерах всё понятно:
Код самой библиотеки:
Секрет в совмещении данных, чтобы IE, обратившись к странице по протоколу mhtml нашёл нужный кусор, «спрятанный» внутри тега, а остальные браузеры увидели бы картинку через data URL.
Код тестировался под Opera 9.50b, FF 2.0.0.13, Safari 3.1 и IE6. Предложения и результаты испытаний — прошу в комментарии.
Оригинал записи опубликован в моём блоге.
К вопросу о кроссбраузерных Data URI
BASE64
Формат секций в JPEG:[заголовок][data]
C jpeg все просто и описано у bolk‘а:
Открываем HEX-редактор:
FF D8 — заголовок JPEG для IE
FF E0 — объявление секции APP0, куда прячется всё до данных изображения,
«;background-color:url(data:image/jpeg;base64,» — это видят остальные браузеры.
Когда IE декодирует эту строку, то получается хлам, который ни на что не влияет
FF D8 — начало JPEG для остальных браузеров
«данные изображения» — это место видят уже все браузеры
Смысл в том, что бы строка в CSS выглядела как:
И дешифровалась в IE как:
А другие ее видели как:
Из-за особенностей base64 надо дополнительно передавать некоторое кол-во символов, что бы строка шифровалась\дешифровалась верно. Они вставляются до и после CSS. Количество просчитывалось и подбиралось опытным путем:
/9j/4AA0;background-image:url(data:image/jpeg;base64;00,
Мой скрипт, который это процесс автоматизирует:
#!/usr/bin/ruby
require ‘base64’
# тут строка ВСЕГДА равна одному значению:
a= «/9j/4AA0;background-image:url(data:image/jpeg;base64;00,»
Я выбрал второй вариант, это делает base64 строку более читаемой и позволяет конвертировать любые не анимированные gif.
Более менее стандартный вариант секций GIF: [заголовок][размер][data][00]
Многие GIF имеют не совсем корректный порядок полей. Например если сделать `convert jpeg gif` то полученный файл адекватно обрабатываться скриптом не будет. Юзайте GIMP.
Первые 13 байт это та инфа, сокращать которую нельзя. Причем 11 байт является сложно-составным и описывает Global Color Table. Его меняем на 00
Вырезаем таблицу цветов (от 14 байта и до камента — 21 FE xx, где xx — размер коммента)
Коммент с css и первыми 13ю байтами.
Вырезаем таблицу цветов (от 14 байта и до камента — 21 FE xx, где xx — размер коммента)
‘Внутренний кoммент’ длиной в 1 символ
Вырезаем таблицу цветов (от 14 байта и до камента — 21 FE xx, где xx — размер коммента)
2c 00 00 00 00 — Image descriptor. Его 10й байт является сложно-составным и описывает Local Color Table. Переносим из 11-го байта все что переносится (объявить Local Color Table, сортирована\нет, размер Local color table), подробнее в спецификации формата.
Вставляем таблицу цветов
Продолжение Image descriptor
Смысл в том, что бы строка в CSS выглядела как:
При том что до всех правок файл выглядел как:
Мой скрипт для автоматизации процесса:
# FUTURE HEADER
header=orig[0..25]
# GREP GENERAL COLOR TABLE
# [26..1565]/6 = 256 BYTE (MAX SIZE OF COLOR TABLE)
color_table=orig[26..1565][/(.*)21fe/,1]
if color_table. class == NilClass
color_table=orig[26..1575][/(.*?)2c0000/,1]
end
# FOR DEBUGING
#puts color_table
#puts color_table.length
puts «COLORS IN PALLETE: #
# GIF IMAGE DATA
data=orig[/2c0000.*/]
# SAVE 11 BYTE ‘S INFO AND ADOPT IT FOR LOCAL COLOR TABLE
eleven=header[20..21].to_i(16).to_s(2)
local_mix=»10#
# 11 BYTE TO ZERO
header[20..21]=»00″
# DECLARE LOCAL COLOR TABLE
data[18..19]=local_mix
# MAGIC COMMENT
comment=Base64.decode64(«;background-image:url(data:image/gif;base64;pzd,»).unpack(«H*»).to_s
# MAKE STRING CSS READEABLE
c=File.open(‘ temp ‘,’ r ‘)<|f| f.read>.gsub(/backgroundimageurldataimage\/gifbase64pzd/,»;background-image:url(data:image/gif;base64;pzd,»).gsub(/\n/,»»)
File.delete(‘ temp ‘)
# JUST PASTE TEXT FROM THIS FILE TO CSS
File.open(‘ out_gif64 ‘,’ w’)<|s| s.write( "#
Для анимированного гифа скрипта нет. Я считаю что лучше использовать анимированными CSS sprites.
21 ff SizeSize ‘NETSCAPE2.0’ SizeSize 01 00 00, где SizeSize — 2 байта отвечающие за размер, а 01 байт отвечающий за infinitive loop.
После gif это тихая гавань. У секций размер не ограничен, у них 4байтные заголовки и их очень удобно искать. Для сравнения, для gif я ломал голову и дебажил скрипт почти весь день, а для png все сделал за час.
Формат секций в PNG: [размер(4 байта)][data][CRC(4 байта)]
И тут не обошлось без подводных камней. CRC очень важен для IE, если CRC битый то IE не будет отображать картинку. Всем же остальным глубоко параллельно битый он или нет.
Многие PNG имеют не совсем верную структуру, во всяком случае, мой скрипт с нми работать не будет, пока не прогнать их через optipng. Помимо оптимизации изображения, эта прога выставит поля в нужном порядке. Также, мною замечено что Photoshop иногда режет поля sRGB и им сохраненные png обрабатываются не всегда.
CSS будем прятать в секции tEXt
PNG надо сразу заоптимизировать с помощью optipng, потом нарезать таким образом, что бы tExt был сразу за IHDR.
В секции tEXt обязательно должен передаваться keyword00, его длина учитывается в общей длине секции. У меня это ‘Comment ‘
Общий порядок:
IHDR
tExt
Другая служебная информация
data
Было:
Стало:
Скрипт хорошо комментирован, и в спецификации тоже можно многое почерпнуть
IE6 не видит прозрачности, иногда это можно исправить с помощью bKGD выставляя нужный Background color.
Мой скрипт для автоматизации процесса:
#MAGIC COMMENT
comment=Base64.decode64( «;background-image:url(data:image/png;base64;pzd,» ).unpack( «H*» ).to_s
MHTML
—_
Content-Type: text/css;
*/
html, body <
margin: 0;
padding: 0;
width: 100%;
height: 100%;
>
#half_logo <
/*
—_
Content-Location:logo
Content-Transfer-Encoding:base64
Content-Type: image/png;*/
Тестировалось в FF 3.6, Opera 10.10, chromium, chrome, IE6-8
Data:URI CSS Sprites — современный подход к генерации CSS спрайтов
Мучения со стандартным подходом применения CSS спрайтов, а именно трудности модернизации и в некоторых случаях сложности оптимальной компоновки заставили искать альтернативный вариант оптимизации загрузки изображений. Очередной раз почитывая хабра-статьи, наткнулся на интересный подход реализации спрайтов с применением data:URI. В ходе дискуссий и умозаключений были определены слабые и сильные стороны данного подхода. Одним из значительных недостатков нового подхода является сложность сборки конечного CSS. Однако, при использовании data:URI имеет место возможность автоматизации процесса. Соответственно, было принято решение создать программное обеспечение для автоматической сборки data:URI спрайтов.
Data:URI CSS Sprites
Новый подход генерации CSS спрайтов на основе data:URI решили назвать Data URI Sprites — DURIS.ru. Название немного необычное — но зато уникальное и запоминается хорошо. Как выяснилось позже когда-то давно жил вазописец по имени Дурис.
Что это
В первую очередь это полностью автоматический анализ и сборка CSS спрайтов на основе data:URI.
Некоторые характеристики работы DURIS:
1) загрузка и парсинг всех внутрених (style) и внешних (link) стилей
2) выделение background-image в отдельный внешний стиль
3) загрузка и кодирование в base64 всех изображений которые найдены в стилях
4) оптимизация правил с повторяющимися background-image в стилях
5) удаление CSS правил с отсутствующими на сервере изображениями (устраняет лишние ненужные запросы)
6) специальное подключение data:URI спрайтов для всех браузеров и отдельно для ИЕ6, ИЕ7 Vista (более детально в FAQ
7) другое.
«Зачем мне это надо?»
Современный подход создания CSS спрайтов
— позволяет безболезненно вносить коррективы в изображения и верстку;
— дает возможность свести к минимуму число запросов к серверу для получения информации, которая относится к оформлению страницы;
— позволяет использовать полностью семантическую верстку;
— устраняет проблемы масштабирования для фоновых изображений;
— объединяет изображения разных типов и осей повторения.
— все создается в автоматическом режиме;
ИЕ и другие
В ходе разработки реализации data:URI спрайтов были проанализированы наиболее часто встречающие варианты CSS правил. Также был учтен всеми любимый браузер ИЕ. Кому еще не известно ИЕ не поддерживает до версии 8 технологию data:URI. Однако, для него существует альтернативный вариант реализации спрайтов — на основе MHTML-технологии. Т.е., другими словами, на данный момент мы имеем полный спектр решений для всех современных браузеров (99% процентов всех используемых браузеров). Но как всегда ложку дегтя подкидывает Microsoft. Во время тестирования найдена бага MHTML-технологии в Vista ИЕ7 — а именно браузер ИЕ7 в ОС Vista при кэшировании MHTML файла отказывается показывать изображения (связано с мало документированными проблемами безопасности пр использовании MHTML в Vista ИЕ7). Если сделать файл не кэшируемым, то все работает как и должно работать, но в случае с кэшированием фоновые изображения не отображаются. В общем, Microsoft все же сделал так чтобы «цепь разорвалась». Другими словами, на текущий момент для браузера ИЕ7 в ОС Vista реализация DURIS работает не совсем так, как задумывалось изначально. В подключение стилей внедрен алгоритм проверки ИЕ7 Vista и в случае такового фоновые картинки подключаются стандартным путем. Статистика показывает, что пользователей, которые используют ИЕ7 под Vista около 5% процентов. В любом случае, мы уже знаем, что в ИЕ8 будет нормально реализована Data:URI технология. Хотя, честно говоря есть большие сомнения что разработчики ИЕ опять чего-то не того напрограмируют.
Основные достоинства
Выделим два наиболее важных достоинства использования современного подхода генерации CSS спрайтов:
1) все фоновые изображения, вынесенные в дополнительный файл стилей, загружаются за одно подключение к серверу — это обстоятельство позволяет уменьшить нагрузку на сервер и ускорить отображение фоновых изображений.
2) сборка конечного файла CSS спрайтов производится автоматически — это позволяет безболезненно проводить модернизацию изображений.
Что имеем
Что будем иметь
Ядро DURIS разработано на языке Java и является самодостаточным (т.е. не зависит от сайта). Предполагается, что после получения релиз-кандидата исходный код ядра будет выложен в открытый доступ под OpenSource лицензией. Ядро работает с командной строки наподобии того, как работает YUICompressor. Это позволит удобно интегрировать автоматическую генерацию CSS спрайтов в свои проекты. Кто программирует на Java, при желании, сможет напрямую вызывать методы ядра DURIS.
Итого
Разработанный метод/алгоритм автоматической генерации CSS спрайтов основе data:URI уникален в своем роде и не имеет мировых аналогов. Это еще раз доказывает что славянский народ тоже умеет изобретать инновации, а не только хорошие/плохие велосипеды.
На сайте выложен FAQ, в котором детально расписано что и как работает. Если что не понятно описано — задаем вопросы в комментариях.
Data uri что это
Встроенные (inline) изображения используют схему data:URI для внедрения прямо в тело веб-страницы. Как было определено в RFC 2397, такие URI предназначены для вставки небольших объектов как «непосредственные» данные. Такие объекты должны рассматриваться так же, как и любые другие внешние файлы. Использование встроенных изображений позволяет сэкономить HTTP-запросы к внешних ресурсах.
Поддержка браузерами data:URL
Схема data:URL
В случае простых изображений вам нужно указать mime-тип для них (например, image/gif ), за ним идет base64-представление бинарного файла с изображением. Ниже приведен пример (переводы строк добавлены, чтобы не разрывать страницу, на самом деле, их нет):
В результате вы получите следующее изображение иконки папки (частичный скриншот ниже):
CSS и встроенные изображения
Такие изображения, внедренные в HTML-страницы, не кешируются для повторного использования, и они не кешируются от странице к странице (это логично: ведь нам нужно каждый раз загрузить HTML-код для отображения этой картинки, они будут кешироваться только с HTML, их содержащим). Однако, CSS кешируется браузерами, и такие изображения могут быть повторно использованы вместе с использующим их селектором, например:
Теперь иконка папки будет повторяться для каждого вхождения LI (или можно также использовать соответствующий класс или ID ).
Что выглядит в Firefox примерно следующим образом (частичный скриншот):
Проблемы data:URL
С описанным выше подходом для подключения изображений связано две основные проблемы. Во-первых, вам нужно пересчитывать base64-представление изображений и редактировать CSS-файл каждый раз, когда само изображением меняется. Также IE до версии 7 включительно не поддерживает встроенных изображений. У первой проблемы есть простой решение на PHP:
Этот код читает файл с изображением и автоматически преобразовывает его на сервере в base64. Однако, это простота этого решения повлечет некоторую дополнительную нагрузку на сервер. Как вариант можно рассмотреть автоматический пересчет всех картинок и вставка их в CSS-файл, например, раз в 5 минут по необходимости (если файл с изображением изменился). Дополнительно нужно будет озаботиться, чтобы сбросить кеширование для самого CSS-файла.
Работа в Internet Explorer
Когда ваш сервер анализирует CSS-файл, он автоматически перекодирует бинарный файл изображения в base64 и отправит эти данные внутри CSS-файла. Следующим шагом будет добавление распознавания браузеров для отправки изображения только IE, и встроенных изображений всем остальным. Это можно сделать либо внутри CSS-файла с PHP-кодом, либо с помощью условных комментариев, например:
В файле ie.css должно быть нормальное обращение к картинке, например:
Лично мне вышеприведенный код кажется сомнительным: все браузеры, кроме IE, посчитают, что CSS-файлы закомментированы и вообще к ним не обратятся. Поэтому я бы советовал оставить комментарии только для первого файла и переместить его вызов в конец, чтобы он переопределял общие стилевые правила.
Преимущества data:URL
Недостатки data:URL
Встроенные изображения не поддерживаются в Internet Explorer 5–7, хотя сообщается, что версия 8 их поддерживает. Текстовое base64-представление данных также занимает больше, чем бинарное изображение. В наших тестах base64-данные были на 39–45% больше бинарного аналога, но gzip-сжатие позволяет уменьшить разницу до 89%. Предварительная оптимизация изображений перед base64-кодированием позволяет уменьшить их размер пропорционально.
Также существует ряд ограничений на размер встроенных изображений. От браузеров требуется поддерживать только URL длиной до 1024 байтов, в соответствие с вышеупомянутой спецификацией RFC. Однако, браузеры более либеральны к пользователям в том, что они принимают. Например, Opera ограничивает data:URL до примерно 4100 символов. Firefox поддерживает data:URL вплоть до 100Кб. В итоге, эта техника подходит больше для небольших по размеру изображений. Краткий список минусов:
Примеры data:URL
Ниже приведено несколько примеров, которые вы можете проверить в своем браузере. Все они отражают вышеприведенный код.
Дополнительные соображения по оптимизации
Также возможно автоматическое кодирование изображений, которые выводятся в base64, автоматически при изменении этих изображений (для этого потребуется простой скрипт, который проверяет, обновились ли соответствующие файлы, если обновились, то перезаписывает их представление в CSS-файле, заодно и меняет хеш-строку для подключения этого файла в HTML, чтобы избежать кеширования.
Для включения небольших графиков прямо в HTML-код прекрасно подойдут условные комментарии, когда для ряда браузеров изображение выводится в base64, а для остальные в виде IE подключается через условные комментарии. Если использовать связку относительное позиционирование родителя абсолютное позиционирование дочернего элемента, то IE будет просто выводить картинку из внешнего файла поверх непонятного (для него) объекта. Например, так:
Хочу подчеркнуть, что решение об использовании data:URL должно приниматься на основе статистики использования браузеров для просмотра сайта (для webo.in доля IE составляет меньше 20%, что позволяет использовать более прогрессивные методы для оптимизации скорости загрузки).
Заключение
С релизом Internet Explorer 8 data:URI должны стать реальной альтернативой существующим методам вывода изображений. Вы можете вставить небольшие изображения прямо в тело страницы с помощью data:URL для экономии числа HTTP-запросов. data:URL является удобным способом для создания автономных веб-страниц, которым не требуются никакие внешние объекты для полного своего отображения.
Полное руководство по HTML-атрибутам data-*

Общие сведения
HTML-элементы могут иметь атрибуты, которые используются для решения самых разных задач — от предоставления данных ассистивным технологиям, до стилизации элементов.
При этом не рекомендуется создавать собственные атрибуты, или применять существующие атрибуты такими способами, на которые они не рассчитаны.
Это плохо по многим причинам. HTML-код оказывается неправильно сформированным. И хотя подобное может и не иметь реальных негативных последствий, это лишает разработчика тёплого чувства вызываемого тем, что он создаёт валидный HTML-код. Но главная причина того, что так поступать не следует, заключается в том, что HTML — это язык, который постоянно развивается. В результате, если некий атрибут сегодня в языке не применяется, это не значит, что в будущем ничего не изменится.
Синтаксис
Можно ли использовать атрибут, имеющий имя data?
Вот пример кода, в котором используется атрибут с именем data :
Атрибут с таким именем, вероятно, никому не повредит, но его применение не позволит пользоваться JavaScript-инструментами, которые мы рассмотрим ниже. В этом примере разработчик, фактически, создаёт некий собственный атрибут, что, как уже было сказано, делать не рекомендуется.
Чего не стоит делать с атрибутами data-*
Вот материал о том, как скрывать элементы веб-страниц.
Стилизация элементов с использованием атрибутов data-*
В CSS можно выбирать HTML-элементы, основываясь на атрибутах и их значениях.
Это может показаться интересным. Для стилизации в HTML/CSS используются, в основном, классы. И хотя классы — это замечательный инструмент (они отличаются средним уровнем специфичности, с ними можно работать с помощью удобных JavaScript-методов через свойство элементов classList ), элемент может либо иметь, либо не иметь некоего класса (то есть, класс в элементе либо «включен», либо «выключен»). При использовании атрибутов data-* в распоряжении разработчика оказываются и возможности классов («включено/выключено»), и возможность выбора элементов, основываясь на значении атрибута, которое он имеет на том же уровне специфичности.
Специфичность селекторов атрибутов
Специфичность селекторов атрибутов такая же, как у классов. Специфичность часто рассматривают как значение, состоящее из 4 частей:
А вот ещё один селектор:
Вот, чтобы было понятнее, иллюстрированная версия этих рассуждений.
1 тег, 1 класс и 1 атрибут
У селекторов атрибутов специфичность ниже, чем у идентификаторов ( ID ), но выше, чем у тегов (элементов). Их специфичность равна специфичности классов.
Значения атрибутов, нечувствительные к регистру
Если нужно, чтобы селекторы выбирали бы атрибуты, значения которых могут содержать строки, записанные с использованием разных комбинаций строчных и прописных букв, можно воспользоваться вариантом селектора, нечувствительным к регистру.
Вывод данных, хранящихся в атрибутах data-*
CSS позволяет извлекать значения атрибутов data-* и выводить их на странице.
Примеры использования атрибутов data-* для стилизации элементов
Вот соответствующий CSS-код:
А вот — фрагмент результирующей страницы.
Grid-контейнеры, настройка которых производится с помощью атрибутов data-*
Поэкспериментировать с этим примером можно на CodePen.
Работа с атрибутами data-* в JavaScript
К значениям атрибутов data-* можно обращаться, как и к значениям других атрибутов, пользуясь методом getAtribute для чтения данных, и методом setAttribute для записи.
Однако атрибуты data-* имеют и собственный особый API. Предположим, у нас есть элемент с несколькими атрибутами data-* (что совершенно нормально):
Если имеется ссылка на этот элемент, то читать и записывать значения его атрибутов можно так:
В JavaScript можно работать и со встроенными в элементы наборами данных:
А почему бы не записать в атрибут data-* JSON-данные? Ведь это всего лишь строки, которые можно отформатировать как валидные JSON-данные (учитывая кавычки и прочее). При необходимости эти данные можно извлечь из атрибута и распарсить.
Об использовании атрибутов data-* в JavaScript
Распространённый вариант реализации этого сценария направлен на организацию работы с базами данных. Предположим, у нас имеется кнопка Like :
Итоги
Уважаемые читатели! Как вы применяете HTML-атрибуты data-*?





