Баг с PNG-прозрачностью в IE6, но не тот, о котором вы подумали

Баг с PNG-прозрачностью в IE6, но не тот, о котором вы подумали

Уже долгое время на сайтах популярны различные вебдванольные стикеры, которые «клеятся на макет сверху», часто с помощью абсолютного позиционирования. При вёрстке, такие изображения лучше сохранять в формат PNG, чтобы оставить все тени и полупрозрачности, как на исходном макете. Да и GIF формат, часто не подходит из-за зазубренных краёв и отсутствия в нём полупрозрачности.

И конечно же, все мы знаем, что в IE6 есть проблема с отображением PNG — изображение появляется на сером фоне вместо прозрачного. Чтобы оно отображалось правильно, нужно применить фильтр AlphaImageLoader. Но не все знают, что если такое изображение поместить внутрь ссылки, она начинает работать «неправильно».

Проблема

Вместо долгих объяснений покажу на примере (открывать в IE6, под другие браузеры не заточен!).

Ничего странного не заметили?

Для тех кто не рассмотрел, показываю, как сейчас работает ссылка и как выглядит наведённый на неё курсор:

пример бага IE6 с PNG-прозрачностью в ссылках

Тоесть ссылка как бы «инвертируется»: прозрачные пиксели становятся кликабельными, а непрозрачные — нет. Причём, неважно, как вставлено изображение, картинкой или фоном.

Код из примера (XHTML):

<h2>Стикер вставлен фоном</h2>
<div id="one" style="filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='sticker.png', sizingMethod='scale');">
	<a href="#"></a>
</div>
<h2>Стикер вставлен картинкой</h2>
<div id="two" style="filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='sticker.png');">
	<a href="#"><img src="sticker.png" width="155" height="158" style="filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" alt="sticker" /></a>
</div>

В стилях просто прописываются ширина и высота блоков, а также ссылке в примере с фоном указываются блочные свойства (CSS):

body {
	text-align: center;
	background: #fff;
	font: normal 85%/1.5em tahoma, verdana, sans-serif;
}
img {
	vertical-align: top;
	border: none;
}
div {
	display: block;
	width: 155px;
	height: 158px;
	margin: 0 auto 20px auto;
}
#one a {
	display: block;
	width: 155px;
	height: 158px;
}

Простое указание через CSS cursor: pointer, чтобы исправить ситуацию, не работает.

Как победить

Решение необъяснимое, но оно работает. Подсмотрел в каком-то из западных блогов, но не помню ссылку, тут уж извините.

Чтобы исправить положение, для элементов, содержащих PNG-изображение (или к которым применён фильтр AlphaImageLoader) нужно присвоить CSS-стиль position: static, а всем дочерним элементам по отношению к нему (в моём примере это ссылки) — position: relative.

Вот «исправленный» пример (XHTML):

<h2>Стикер вставлен фоном</h2>
<div id="one" style="position: static; filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='sticker.png', sizingMethod='scale');">
	<a href="#" style="position: relative"></a>
</div>
<h2>Стикер вставлен картинкой</h2>
<div id="two" style="position: static; filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='sticker.png');">
	<a href="#" style="position: relative"><img src="sticker.png" width="155" height="158" style="position: relative; filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" alt="sticker" /></a>
</div>

Ну и страничка с примером.

Для наглядности, я писал стили в XHTML-коде, естественно их лучше вынести в отдельный стилевой лист.

Этот пример и описание проблемы я привёл для того, чтобы вы знали, с чем имеете дело, если встретитесь с этим багом. Есть путь проще для решения этой проблемы, но там используется JavaScript.

Светлый путь

Чтобы не заморачиваться написанием стилей для кроссбраузерности (а для примера выше придётся писать стили отдельно для IE6 и отдельно для «нормальных» браузеров), рекомендую использовать скрипт iepngfix. Как его подключать подробно написано здесь.

Этот скрипт сам исправит вид всех PNG-изображений на странице в IE6, достаточно только будет перечислить их в стилевом листе.

* * *

Сканер блогов:

Интересные онлайн генераторы для подбора цветовой палитры. Когда можно обойтись без !important в CSS?. 17 популярных JS/AJAX эффектов для сайта. Ну а для любителей исторических мест Беларуси — виртуальная прогулка из Гродно в Минск.

* * *

Понравилась статья?

Тогда помогите мне сделать её доступной для других, или будьте в курсе последних событий:

* * *

Статьи по теме:

Комментариев: 25

  1. Wasly, 08.09.2008 в 10:43

    «Валидатор, кстати, на фильтры не ругается.»

    XHTML-валидатор «не ругается», потому что в его функции не входит проверка CSS, а значит значение style он не проверяет.

    А вот CSS-валидатор такого безобразия не пропустит ;)

    Ответить

  2. rotor, 08.09.2008 в 10:57

    Согласен, затупил :) Зато, нечаянно, показал способ обходить валидатор для обманщиков ))

    Альтернативой останется iepngfix.htc или же условные комментарии.

    Ответить

  3. Wasly, 08.09.2008 в 12:00

    Ну, единственный корректный способ известен давно — используйте добавление фильтра через DOM.

    Код получается компактный.

    Обманывать валидатор нет смысла, так как кодер обманывает лишь себя самого, показывая остальным свой непрофессионализм ;)

    Ответить

  4. Сергей, 08.09.2008 в 12:21

    Цвет выглядит по разному изза альфаканала в png. IE его делает темнее, поэтому надо удалять этот канал прогой tweakpng-1.2.1

    а скрипт от www.tigir.com/alpha_png.htm

    позволяет использовать png в любом месте, даже как бекраунд таблицы

    Ответить

  5. rotor, 08.09.2008 в 12:49

    Сергей

    Пост не о том, как победить PNG-прозрачность в IE6.

    Ответить

  6. Wasly, 08.09.2008 в 13:16

    rotor

    Вы, кстати, совсем забыли в своем примере про неIE броузеры — не прописали background-image для div#one.

    А если его прописать... то тут-то и начинаются «танцы с бубном», так как для IE этот фон надо убрать, потом что AlphaImageLoader закачивает свою картинку, а для остальных броузеров оставить ;)

    Можно, конечно, условные комменты вставить, но лично я не сторонник «костылей» :)

    Спасибо за статью — для себя хоть сделал готовое решение по теме, раньше чё-то ленился :)

    Ответить

  7. rotor, 08.09.2008 в 13:30

    Не за что, рад что кому-то помогло.

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

    Танцы с бубном с background-image для PNG в IE6 знакомы :)

    Ответить

  8. Wasly, 09.09.2008 в 11:56

    Вплыл забавный баг:

    Результат работы AlphaImageLoader не выводится на печать.

    Так что золотое правило работает и в этом случае:

    Не нужно эмулировать то, что в броузере не реализовано.

    Пока IE6 широко распространен, не следует использовать png с прозрачностью в дизайне веб-страниц.

    Ответить

  9. rotor, 09.09.2008 в 12:06

    Серьёзно? Никогда не пробовал печатать такой документ.

    Реализовать то, что не реализовано в IE6 с помощью фильтра — это идея и решение спецов из Microsoft. Опять они что-то не досмотрели.

    >Пока IE6 широко распространен, не следует использовать png с прозрачностью в дизайне веб-страниц.

    Мне в печатной версии важен текст, а не графика, поэтому всё-таки думаю, что png можно использовать. Конечно же сначала всё проверив несколько раз.

    Ответить

  10. Wasly, 09.09.2008 в 12:52

    «Мне в печатной версии важен текст, а не графика,...»

    А логотип, к примеру?

    Привлекательность прозрачности PNG в её полупрозрачности :)

    Если фон страницы отличный от белого, то GIF с прозрачностью в шаблоне для печати уже нельзя использовать.

    Еще свежо воспоминание, когда мне приходилось адаптировать темы vB-форума (иконки и кнопки), только потому что сменился цвен фона страницы — этот Action для Фотошопа до сих пор бережно храню :)

    Ответить

  11. Octane, 09.09.2008 в 13:00

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

    Ответить

  12. rotor, 09.09.2008 в 13:37

    Логотип — это функциональный элемент, который, не стесняясь, можно вставлять на сайт картинкой. И не скрывать при печати стилями.

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

    Ответить

  13. Wasly, 09.09.2008 в 14:06

    «...отделить полупрозрачные пикселы в отдельное изображение...»

    Проблема в том, что полупрозрачность PNG НЕ распечатать из-под IE6. Он выводит на печать такие PNG как и отображает — то есть без прозрачности вообще ;)

    Ответить

  14. Romaldo, 07.11.2008 в 21:10

    Есть фон из полупрозрачного png, на нем форма, в IE не ставиться курсор в и не возможно ничего вписать. Кто-нибудь сталкивался с такой проблемой?

    Ответить

  15. rotor, 08.11.2008 в 16:48

    C проблемой не сталкивался, можно живой пример?

    Ответить

  16. Romaldo, 13.11.2008 в 20:37

    проблема решилась выше описанным способом присвоением позиционирования статик и релатив. но вот еще одна проблема. блок див имеет абсолютное позиционирование и тоже фон его задан через AlphaImageLoader для IE. в этом блоке не отображается например, список UL, а тег P спокойно отбражается. кажется для абсалютного позиционирования эту прблему не решить. А страницу без полупрозрачной графики никак ни сверстать, потому что фон BODY градиентный.

    Ответить

  17. rotor, 13.11.2008 в 22:29

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

    Но что-то советовать, не видя перед глазами пример, сложно.

    Ответить

  18. Евгений, 24.12.2008 в 9:14

    При переносе решения с AlphaImageLoader в CSS — перестает работать, т.е. картинка вовсе не подгружаете. Сталкивались с этим?

    По поводу скрипта IEPNGFix по опыту знаю, что решение работает, но, к сожалению, медленно. Поэтому ищу другие пути.

    Ответить

  19. rotor, 24.12.2008 в 12:50

    Должен работать, возможно проблема в пути к изображению.

    Есть неплохая подборка методов решения бага с PNG в IE6 здесь. Может быть найдёте для себя более быстрое решение.

    Ответить

  20. Евгений, 25.12.2008 в 3:47

    Да, Rotor, Вы правы оказались насчет путей. Оказывается при примененении AlphaImageLoader в CSS нужно указывать АБСОЛЮТНЫЕ пути. Такой нюанс. Спасибо, за прекрасную статью.

    Кстати, у Ваешго блога прекрасный дизайн. На данный момент вошел в мои персональные TOP-10 ))

    Ответить

  21. Александер Линл, 05.03.2009 в 14:45

    Я тут немного по-другому решил эту проблему... Вернее, решал другую проблему, а получилось что решил именно эту :)

    Получается так, что слой с сылкой накладывается на слой с прозрачностью... и там где есть картинка — ссылка остаётся :)

    вот что на странице:

    и вот кто в КСС

    #logo{

    width:216px;

    height:150px;

    display:block;

    position:absolute;

    left:50%;

    margin:50px 0px 0px 175px;

    filter:progid:DXImageTransform.Microsoft.AlphaImageLoader (src='imgs/logo.png',mask='imgs/pole.png',sizingMethod='crop');

    }

    #baseurl{

    position:absolute;

    width:216px;

    height:80px;

    display:block;

    border:1px solid white;

    left:50%;

    margin:50px 0px 0px 175px;

    }

    Ответить

  22. Александер Линл, 05.03.2009 в 14:47

    тыги в предыдущем сообщении вырезались... сделаю так

    {div id="logo" }{/div}

    {a id="baseurl" href="#"}{/a}

    Ответить

  23. Руслан, 29.10.2009 в 0:16

    Автор, спасибо за решение проблемы — здорово выручил!!!

    Ответить

  24. Артём, 19.02.2010 в 18:38

    Спасибо, очень помогло, уже не знал, как фиксить, спасло только это!

    Ответить

  25. @ SharUpOff, 05.11.2011 в 0:34

    Спасибо, решение помогло!

    стили отдельно для IE6 и отдельно для «нормальных» браузеров

    Достаточно перед элементом css поставить символ «*»:

    *position : static;

    Тогда «нормальные» браузеры будут игнорировать данную строку.

    Ответить

Есть что сказать?