Xiper

PIE для скрытых или динамических элементов

Автор: Александр Головко и Андрей Косяк Дата публикации:

Появление скрипта CSS3 PIE значительно упростило реализацию так полюбившихся дизайнерам скругленных углов и различного рода теней. Ведь теперь IE6-8 тоже могут вести себя так, как будто они понимают целый ряд CSS3-свойств.

И пускай это только эмуляция, за которой скрывается достаточно сложное (и, порой, капризное) действо с участием VML-объекта, для простого верстальщика важно, что сделать, например, скругление можно в несколько строк CSS.

Но, конечно, в реальной жизни все так радужно не бывает. Помимо прочих трудностей (перечень которых можно почитать в списке по ссылке, приведенной выше), есть еще одна серьезная проблема.

Проблема PIE и скрытых элементов

Пускай у нас есть какой-то элемент и всплывающая подсказка к нему. Причем подсказку попробуем красиво оформить — добавим скругление и теньку.

<div id="pic">
	<img src="pic/pic.png" width="69" height="69" alt="тут нарисована морковь">
	<div class="hint">Морковка</div>
</div>

Добавляем стили:

#pic {
	color: #fff;
	position: relative; /* относительно этого блока позицонируем подсказку */
	float: left;
}
.hint {
	/* оформляем подсказку */
	background: #880E00;
	padding: 5px 15px 6px 15px;
	position: absolute;
	top: 20px;
	left: 70px;
	/* Наводим красоту: */
	-moz-border-radius: 10px;
	-webkit-border-radius: 10px;
	border-radius: 10px;
	-webkit-box-shadow: 0 0 10px #969696;
    -moz-box-shadow: 0 0 10px #969696;
    box-shadow: 0 0 10px #969696;
	behavior: url(js/pie.htc); /* это правило лучше вынести в отдельный ie6-8 CSS */
}

На этом этапе все будет просто замечательно (если ты, конечно, не забудешь подключить скрипт PIE). Даже IE6 отобразит закругленную подсказку с тенькой.

А теперь давай добавим динамики. Самый простой вариант — мгновенное отображение подсказки. Использую свой любимый jQuery:

jQuery(document).ready(function(){
jQuery("#pic").hover(
  function () {
    jQuery(".hint").css("display","block");
  }, 
  function () {
    jQuery(".hint").css("display","none");
  }
);
});

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

.hint {
	display: none;
}

Вот собственно и все. Приплыли. PIE больше работать не будет. Да-да, в IE6-8 подсказка будет обычным прямоугольником:

баг у скрытого блока

Проблема на лицо. Если блок изначально скрыт (display: none) или вообще отсутствует в коде (вставляется позже, динамически), PIE для него не сработает.

Решение

Конечно, можно попытаться обмануть скрипт и вместо скрытия блока просто вынести его куда-нибудь за пределы какого-нибудь родителя с overflow: hidden. Однако такой трюк для динамически генерируемого блока не пройдет.

В качестве универсального решения предлагается подключать нужным блокам PIE «на лету».

Для этого определим специальные функции:

var	ie = jQuery.browser.msie,
		ieV = jQuery.browser.version,
		ie6 = ie&&(ieV == 6),
		ltie7 = ie&&(ieV <= 7),
		ltie8 = ie&&(ieV <= 8);
function setPie(selectors){jQuery(selectors).css("behavior", "url(js/pie.htc)")};
function unsetPie(selectors){jQuery(selectors).css("behavior", "none")};
function resetPie(selectors){
			unsetPie(selectors);
			setPie(selectors);
		};

Теперь в нужный момент PIE можно установить (или сбросить, во избежание глюков):

jQuery("#pic").hover(
  function () {
    jQuery(".hint").css("display","block");
	ltie8 ? resetPie(".hint") : false;
  }
...

Демо-пример — PIE в скрытом блоке.

Проверено в:

  • IE 6-8
  • Firefox 3.6+
  • Opera 11
  • Safari
  • Chrome

Примечание для самых внимательных

В коде демо-примера есть малопонятная на первый взгляд строка:

p {
	behavior: url(js/pie.htc);
}

Что это и как оно туда попало?

Дело в том, что при первом вызове функции resetPie произойдет загрузка pie.htc, а это почти 34Кб. Время загрузки может оказаться очень даже заметным — самый первый раз, при наведении на рисунок в IE6-8, подсказка сначала появится без CSS3-наворотов, которые «догонят» ее несколько позже.

В больших проектах этой неприятности несложно избежать. Если какой-либо статичный элемент уже использует PIE, то библиотека, конечно, уже будет загружена и глюка не произойдет. На простенькой страничке демо-примера мне пришлось искусственно загрузить PIE, подцепив его на «левый» элемент — абзац. Этот трюк чем-то сродни предварительной загрузке изображений.

Вывод

Теперь PIE можно смело применять для оформления скрытых или динамически генерирующихся блоков.

По теме: