-ms-filter порождающий баги. Будьте бдительны

от автора

CSS -ms-filter bug

Привет, %username%.

В данной публикации будет рассмотрен безобидный, на первый взгляд, код который может вызвать недоумение — меню типа dropdown не будет работать в IE 7-8 из-за использования градиентного фона у контейнера.

В CSS есть хорошая функция — linear-gradient(). Благодаря ей мы имеем возможность создавать весьма сложные градиенты для применения в веб-разработке. Но вот браузер Internet Explorer, до девятой версии включительно, не выполняет данную функцию в связи с отсутствием ее поддержки на уровне обозревателя и, вместо нее, имеет собственную реализацию в виде CSS свойства и особого значения для него. Выглядит запись приблизительно так:

div {       filter: progid:DXImageTransform.Microsoft.Gradient(params);       -ms-filter: "progid: DXImageTransform.Microsoft.Gradient(params); } 

Свойство -ms-filter — запись согласно новой спецификации Microsoft.
Подробнее о градиентном фильтре для IE можно прочесть на htmlbook: http://htmlbook.ru/css/filter/gradient

Вроде бы ничего нового и занятного, не так ли? Но, как и в подавляющем большинстве костылей для IE, корректной работы данной реализации ждать стоит не в ста процентах случаев.

Описание и воспроизведение ошибки

Фильтр для создания градиента, как и все реализации не поддерживаемых CSS правил в старых IE, обрабатывается при помощи JavaScript, а лишний JS сулит ошибками.

Не скажу что баг критический, но и не из разряда надуманных. Для воспроизведения нам понадобится классическое выпадающее меню реализованное на чистом HTML и CSS с использованием селектора дочерних элементов.

Я набросал простейшее меню для примера:

HTML

<!DOCTYPE html> <html lang="en"> <head> 	<meta charset="utf-8" /> 	<title>-ms-filter bug in IE 7-8</title> 	<meta name="description" content="A bug occurs in IE 7-8 when using the -ms-filter and CSS dropdown menu." /> 	<meta name="keywords" content="ms filter, css filter, bug, microsoft, habrahabr demo" /> 	<meta name="author" content="BR0kEN, Firstvector.org" />  	<link rel="stylesheet" href="menu.css" /> 	<!--[if lt IE 10]><link rel="stylesheet" href="ie.css" /><![endif]--> 	<!--[if lt IE 8]><link rel="stylesheet" href="ie7.css" /><![endif]--> </head> <body role="document"> 	<ul class="nav wrap clr"> 		<li class="active"><a href="">Home</a></li> 		<li><a href="">Currency</a></li> 		<li><a href="">Macroeconomic analysis</a> 			<ul class="sub-menu"> 				<li><a href="">Dean's FX</a></li> 				<li><a href="">Economic exposure</a></li> 				<li><a href="">Market pulse</a></li> 				<li><a href="">Central bank watch</a></li> 			</ul> 		</li> 		<li><a href="">Technical analysis</a> 			<ul class="sub-menu"> 				<li><a href="">Forex</a> 					<ul class="sub-menu"> 						<li><a href="">USD</a></li> 						<li><a href="">GBP</a></li> 						<li><a href="">EUR</a></li> 						<li><a href="">AUD</a></li> 					</ul> 				</li> 			</ul> 		</li> 		<li><a href="">Forex news</a></li> 		<li><a href="">Economic calendar</a></li> 		<li><a href="">Education</a></li> 	</ul> </body> </html> 
menu.css

/* Base */ body { 	font-size:16px; 	font-family:Arial, Verdana; 	background:#f5f5f5; } a { 	text-decoration:none; 	-webkit-transition:all linear .3s; 	-moz-transition:all linear .3s; 	transition:all linear .3s; } ul { 	padding:0; 	width:1024px; 	margin:0 auto; 	list-style:none; } .clr:before, .clr:after { 	content:''; 	display:table; } .clr:after { 	clear:both; }  /* Menu */ .nav { 	background:#4f4f4f; 	background:-moz-linear-gradient(top,#4f4f4f 0%,#494949 21%,#343434 67%,#292929 100%); 	background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#4f4f4f),color-stop(21%,#494949),color-stop(67%,#343434),color-stop(100%,#292929)); 	background:-webkit-linear-gradient(top,#4f4f4f 0%,#494949 21%,#343434 67%,#292929 100%); 	background:-o-linear-gradient(top,#4f4f4f 0%,#494949 21%,#343434 67%,#292929 100%); 	background:-ms-linear-gradient(top,#4f4f4f 0%,#494949 21%,#343434 67%,#292929 100%); 	background:linear-gradient(to bottom,#4f4f4f 0%,#494949 21%,#343434 67%,#292929 100%); 	border-bottom:1px solid #cbcbca; } .nav > li { 	float:left; } .nav > li, .nav > li > a { 	color:#fff; 	border-right:1px solid #dedede; } .nav li { 	position:relative; 	line-height:34px; } .nav > li:hover, .nav > .active { 	background:#635f5f; 	background:-moz-linear-gradient(top,#635f5f 0%,#5a5656 30%,#484545 70%,#3f3c3c 100%); 	background:-webkit-gradient(linear,left top,left bottom, color-stop(0%,#635f5f),color-stop(30%,#5a5656),color-stop(70%,#484545),color-stop(100%,#3f3c3c)); 	background:-webkit-linear-gradient(top,#635f5f 0%,#5a5656 30%,#484545 70%,#3f3c3c 100%); 	background:-o-linear-gradient(top,#635f5f 0%,#5a5656 30%,#484545 70%,#3f3c3c 100%); 	background:-ms-linear-gradient(top,#635f5f 0%,#5a5656 30%,#484545 70%,#3f3c3c 100%); 	background:linear-gradient(to bottom,#635f5f 0%,#5a5656 30%,#484545 70%,#3f3c3c 100%); } .nav a { 	display:block; 	color:#505050; 	padding:0 12px; 	font-size:16px; 	text-transform:capitalize; } .nav .sub-menu { 	display:none; 	position:absolute; 	z-index:9999; 	left:-2px; 	top:100%; 	width:230px; 	background:#fff; 	box-shadow:0 1px 5px rgba(0,0,0,.3); } .nav .sub-menu ul { 	top:40%; 	left:95%; } .nav li:hover > ul { 	display:block; } .nav .sub-menu li { 	border-bottom:1px dotted #ccc; } .nav .sub-menu li:hover > a { 	background:#e8e8e8; } 
ie.css

.nav { 	zoom:1; 	filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#4f4f4f',endColorstr='#292929',GradientType=0); } .nav > .active, .nav > li:hover { 	filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#635f5f',endColorstr='#3f3c3c',GradientType=0); } 
ie7.css

.nav .sub-menu { 	border:1px dotted #ccc; } .nav .sub-menu a { 	height:34px; } 

Демо: http://firstvector.org/examples/ms-filter/index.html.

Выше описаны основные стили для меню и они предназначены для всех обозревателей окромя IE. Далее, внутри первого условного комментария, идут стили предназначенные для IE девятой и более старых версий, внутри второго — для седьмой (вообще для всех версий ниже седьмой, но они нас не интересуют).

Так вот, как мы помним, уже начиная с IE9 функция-ms-linear-gradient() работать не будет и ей на замену придет свойство -ms-filter из файла ie.css.

Хронология событий

IE9 — все работает как надо.

Скриншот

IE8 — видим, что выпадающего меню нет.

Скриншот

Хотя, если присмотреться в выделенную область, можно заметить что меню отобразилось, правда поведение его таково, будто у одного из его родителей установлено overflow: hidden;. Но мы знаем что его нет и знаем в почему так получилось. Оставляем в файле ie.css следующее содержимое:

.nav { 	zoom:1; } 

и проверяем — все работает, но градиентами пришлось пожертвовать.

Скриншот

Возвращаем ie.css к изначальному виду и проверяем работоспособность в IE7 — не работает.

Скриншот

Ожидаемо, т.к. в восьмой версии, было также. Но, что интересно, дабы исправить ошибку в этой версии, потребуется удалить лишь градиент отображаемый при наведении на пункт. Приведем ie.css к виду:

.nav { 	zoom:1; 	filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#4f4f4f',endColorstr='#292929',GradientType=0); } .nav > .active { 	filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#635f5f',endColorstr='#3f3c3c',GradientType=0); } 

и проверим — вновь работает, но при hover-эффекте используется монотонный цвет.

Скриншот

Примечание: для воспроизведения данной ошибки нет разницы в том, как будет написано имя свойства: -ms-filter или просто filter, баг даст о себе знать в любом случае.

Итоги

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

p.s. Я не сомневаюсь в том, что помимо описанных ситуаций можно воспроизвести подобные на этой же почве, или наоборот — отыскать иные методы преодоления.

Спасибо за внимание.

ссылка на оригинал статьи http://habrahabr.ru/post/192408/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *