PNG и прозрачность
Проблема
IE 6 не отображает корректно прозрачность PNG-24 (альфа канал).
Вот так png-24 отображается «нормальными» браузерами |
Вот так отображает png ИЕ6 (прозрачные участки заливает серым фоном) |
Эта картинка в оригинале — тест на поддрежку прозрачности png.
Заметка: PNG-24 иммет ряд преимуществ перед GIF и PNG-8, где прозрачность в ие корректно отображается:
- PNG-24 может обеспечивать альфа-прозрачность (256 уровней прозрачности), в отличии от GIF и PNG, где всего два уровня — абсолютно прозрачно и абсолютно не прозрачно
- поддерживает миллионы цветов
Решения
- Применение фильтра AlphaImageLoader для фоновых рисунов
- Применение фильтра AlphaImageLoader для изображений (img)
- Метод 2 — замена фона прозрачным gif скриптом (behavior)
- Метод 3 — PNG прозрачность в IE6 с background-repeat и background-position (DD_belatedPNG)
- Метод 4 — PNG прозрачность в IE6 на jQuery
- Метод 5 — PNG прозрачность в IE6 на pie
Метод 1 — применение фильтра AlphaImageLoader
1.1. Для фонового изображения
CSS код:
.block { background-image: url(images/pngtest.png); /* для нормальных браузеров */ width: 173px; height: 173px; } * html .block { /* хак для ie6 */ background: none; /* убираем обычный background */ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='/images/pngtest.png'); /* png с прозрачностью для ие6 */ }
Параметр src указывает путь к файлу изображения. Фильтр может иметь дополнительный параметр sizingMethod, который указывает, если изображение не соответствует размерам элемента, в который оно загружается:
- crop — обрезать изображение, если оно больше размеров объекта родителя
- image — увеличить или уменьшить объект по размеру изображения (по умолчанию)
- scale — изменить масштаб изображения по размеру родителя
Пример:
* html .block {
background: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='pngtest.png', sizingMethod='crop');
}
Плюс — просто в реализации.
Минусы:
- требует хак для IE6
- не проходит валидацию
- замедляет работу браузера (об этом будет написано подробнее позже)
- некотрые трудности со слоями z-index
- нет возможности использовать background-repeat
- нет возможности использовать background-position
Возможные проблемы:
При использовании фильтра в ие6 не отображается фоновый рисунок
Этот баг возможен из-за неверно указанного пути к файлу. Чтобы картинка 100% находилась используем полный путь к файлу:
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='');
Второй вариант (более универсальный) — использовать тег <base> для составления корректных относительных адресов, а путь в фильтре относительный, начиная со слеша:
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='/images/pngtest.png');
При использовании фильтра в ие6 становятся не кликабильными вложенные элементы (ссылки, кнопки)
Пример — ссылка на фоне с AlphaImageLoader (демо для ие). HTML код:
<div><a href="">Название сайта</a></div>
CSS код:
div {
padding-top: 20px;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='pngtest.png');
width:200px;
height:200px;
}
Решения:
1. Иногда помогает, если прописать вложенным элементам свойство position: relative;
a { position: relative; }
2. Если применять AlphaImageLoader для элементов со свойствами position: absolute или position: relative, тогда для вложенных элементов предыдущий способ не помогает:
div {
padding-top: 20px;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='pngtest.png');
width:200px;
height:200px;
position: absolute;
top: 0;
left: 200px;
}
a { position: relative; }
Результат. Решение — выносить фоновый рисунок в отдельный div:
<div>
<a href="">Название сайта</a>
<div></div> <--фоновый рисунок-->
</div>
CSS код:
div {
padding-top: 20px;
position: absolute;
top: 0;
left: 200px;
width: 200px;
height: 200px;
}
div div {
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='pngtest.png');
width:200px;
height:200px;
position: absolute;
top: 0;
left: 0;
z-index: 1; /* явно указываем z слой */
}
a {
position: relative; /* чтобы иметь возможность задать z слой */
z-index: 2; /* задаем z слой больше, чем у блока с фоновым изображением */
}
В ссылках в IE6 не кликабильны прозрачные части изображений
При использовании прозрачных фоновых изображений для ссылок (например в логотипах), в ие6 нельзя кликнуть по прозрачному участку. HTML для логотипа этого примера:
<a href="/" class="testPNGLogo"></a>
CSS:
.testPNGLogo {
display: block; /* логотип - блок, чтобы задать четкие размеры */
width: 178px; /* задаем */
height: 36px; /* размеры логотипа */
margin: 20px;
background: url(pngLogo.png); /* рисунок ссылки (логотип) */
}
* html .testPNGLogo { /* показ логотипа для ие6 */
background: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='pngLogo.png');
}
Решение — не используем фон с прозрачностью непосредственно для тега a. HTML:
<a href="/" class="testPNGLogo"><span></span></a>
CSS:
.testPNGLogo { /* для ссылки не устанавливаем фон */
display: block;
width: 178px; /* размеры равны */
height: 36px; /* размеру логотипа */
margin: 20px;
}
.testPNGLogo span {
display: block; /* чтобы установить размеры строчному элементу */
width: 100%; /* заполянем всю площадь логотипа */
height: 100%;
background: url(pngLogo.png); /* рисунок задаем для вложенного элемента */
cursor: pointer; /* чтобы на всем логотипе был нужный указатель мыши */
}
* html .testPNGLogo span { /* png для ие6 */
background: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='pngLogo.png');
}
1.2. Применение AlphaImageLoader для картинок (img). HTML:
<img src="pngLogo.png" style="filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='pngLogo.png' width:expression(1); height:expression(1); " />
Пример.Плюс — работает. Минусы:
- виден кусочек основного рисунка —
- значительно замедляет работу браузера (альфа фильтр + 2 expression)
- замедляет отображение страницы, из-за не указынных явно размеров картинки. Если задать размер картинки, баг с куском основного рисунка увеличивается —
- не работают нормально ссылки на таких рисунках (некликабильны прозрачные участки)
Метод 2 — замена фона прозрачным gif скриптом (behavior)
Первоисточник.
Для этого воспользуемся механизмом behavior, не являющийся стандартом CSS, но позволяющий описать поведение стиля в зависимости от событий, которые происходят при отображении веб-страницы. Поддерживает IE5+. Необходимые действия:
- добавляем в свой проект файл (например сохраняем в корень) iepngfix.htc (3.2 Kb) - скрипт для замены серого фона на прозрачный
- сохраняем blank.gif (52 b) - прозрачный gif размером 1х1, которым будет заменен серый фон в IE
- изменяем в iepngfix.htc путь к файлу blank.gif на свой
- создаем класс .png { behavior: url(<путь к файлу>/iepngfix.htc); }
- применяем этот класс для png-изображений с альфа прозрачностью
CSS код:
.png {
behavior: url(iepngfix.htc);
}
HTML код:
<img src="pngLogo.png" class="png" width="178" height="36" />
Результат. Для избежания значительного замедления работы браузера, применяем этот метод только к картинка с прозрачностью. Для того чтобы замедления сказывались только для IE6 используем условные комментарии. Преимущества:
- компактный код
- ссылки на таких изображениях работают нормально
Недостатки:
- при загрузке страницы пользователь, до отработки скрипта, видит картинки с серым фоном
- замедляет работу браузера (IE)
- замедляет скорость загрузки страницы (IE)
- часто требует явного указания размера картинки (width и height)
- в «чистом» виде не позволяет реализовать background-repeat и background-position
- не проходит валидацию
Метод 3 — PNG прозрачность в IE6 с background-repeat и background-position (DD_belatedPNG)
Drew Diller предложил использовать скрипт, который позволяет использовать прозрачный png в ие6 «по настоящему»:
- позволяет использовать прозрачность в картинках (img)
- кликабильна вся область ссылок-картинок (включая прозрачные участки)
- позволяет использовать в фоновых изображениях свойства background-repeat и background-position
- нет проблем с z-слоями
- легкий скрипт
Чтобы заработало:
- подключаем скрипт DD_belatedPNG.js (5.4 Кb) к странице
- вызываем функцию DD_belatedPNG.fix, в качестве аргументов перечисляем классы элементов, в которых используется прозрачный png
<!--[if IE 6]>
<script src="js/DD_belatedPNG.js"></script>
<script>
DD_belatedPNG.fix('.png_bg, .png_img'); <!--перечисляем классы элементов-->
</script>
<![endif]-->
Пример использования с background-postion:
<html>
<head>
<title>Пример использования с background-postion</title>
<style type="text/css">
.div {
width: 173px; /* размеры */
height: 346px; /* блока */
background: url(test.png); /* фон с прозрачностью */
background-position: 0 100px; /* задаем позицию фону */
background-repeat: no-repeat; /*запрещаем повторение фона */
}
</style>
<!--[if IE 6]>
<script src="js/DD_belatedPNG.js"></script>
<script>
DD_belatedPNG.fix('.div'); <!--указываем нужные классы-->
</script>
<![endif]-->
</head>
<body>
<div class="div"></div>
</body>
</html>
Результат. Недостатки:
- не отрабатывает, если блок скрыт (display: none / visibility: hidden). В таком случае понадобится вызывать DD_belatedPNG.fix повтороно, после показа блока
- вообще, при использовании динамических эффектов нужно с DD_belatedPNG быть внимательным. Иногда проще и надежней использовать filter
- несколько замедляет скорость загрузку страницы
- update by Анрей Косяк: не сработает скрипт, если background будет указан с !important
Метод 4 — PNG прозрачность в IE6 на jQuery
Первоисточник. Применение:
- подключаем популярную библиотеку jQuery
- подключаем скрип jquery.pngFix.js (2.5 Kb)
- инициализируем скрипт при загрузке страницы
<html>
<head>
<style type="text/css">
.div {
width: 173px; /* размеры */
height: 173px; /* блока */
background: url(../images/ie6/pngtest.png); /* фон с прозрачностью */
}
</style>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="resources/jquery.pngFix.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$(document).pngFix();
});
</script>
</head>
<body>
<div class="div"></div>
</body>
Недостаки:
- при загрузке пользователь некотрое время видит картинки с серым фоном
- не работает background-position и background-repeat
- довольно тяжелый файл библиотеки
- увеличенное время на загрузку страницы (два дополнительных файла)
Метод 5 — PNG прозрачность в IE6 на pie
Еще один вариант научить IE6 прозрачности в png24 — использовать библиотеку PIE.
Примение:
- Качаем дистрибутив PIE.
- Добавляем файл PIE.htc в свой проект.
- Прописываем правила для нужных элементов:
.phgFix { background: url('i/address.png') no-repeat; -pie-background: url('i/address.png') no-repeat; behavior: url(PIE.htc); }
update by mrjek Или можно воспользоваться более универсальным вариантом:
.phgFix { background: url('i/address.png') no-repeat; -pie-png-fix: true; behavior: url(PIE.htc); }
Достоинства:
- позволяет использовать в фоновых изображениях свойства background-repeat и background-position
Недостатки:
- плагин относительно свежий, есть ряд особенностей и недоработок (подробнее см. статью CSS3 PIE — Progressive Internet Explorer).