Привет, %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 с использованием селектора дочерних элементов.
Я набросал простейшее меню для примера:
<!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>
/* 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; }
.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); }
.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/
Добавить комментарий