Ars Longa, Vita Brevis

Реализация кросс-браузерного горизонтального меню на чистом CSS 3 без использования JavaScript

Ранее я уже говорил о причинах, побудивших меня сделать меню на чистом CSS без использования JavaScript. Борясь с IE6, у меня получилась красивая версия вертикального меню — его реализация оказалась проще. Теперь обещанное горизонтальное меню.

Требования, которые я поставил:

  1. Нельзя использовать JavaScript;
  2. Полученный код (CSS и XHTML) должен успешно проходить валидацию.

Разметка для тестового примера была взята из этой статьи (которая и сподвигла меня на написание своего меню). В предыдущей статье код пришлось немного переработать (а всё из-за необходимости поддерживать IE6), и именно эту переработанную версию кода мы будем использовать.

[-]
View Code HTML
<ul id="menu">
    <li>
        <a href="#">Renaissance<!--[if IE 7]><!--></a><!--<![endif]-->
        <!--[if lte IE 6]><table><tbody><tr><td><![endif]-->
        <ul>
            <li><a href="#">Brunelleschi</a></li>
            <li><a href="#">Alberti</a></li>
            <li><a href="#">Palladio</a></li>
            <li><a href="#">Michelangelo</a></li>
            <li><a href="#">Bramante</a></li>
        </ul>
        <!--[if lte IE 6]></td></tr></tbody></table></a><![endif]-->
    </li>

    <li>
        <a href="#">Art Nouveau<!--[if IE 7]><!--></a><!--<![endif]-->
        <!--[if lte IE 6]><table><tbody><tr><td><![endif]-->
        <ul>
            <li><a href="#">Mackintosh</a></li>
            <li><a href="#">Guimard</a></li>
            <li><a href="#">Horta</a></li>
            <li><a href="#">van de Velde</a></li>
        </ul>
        <!--[if lte IE 6]></td></tr></tbody></table></a><![endif]-->
    </li>

    <li class="on">
        <a href="#">Modern<!--[if IE 7]><!--></a><!--<![endif]-->
        <!--[if lte IE 6]><table><tbody><tr><td><![endif]-->
        <ul>
            <li><a href="#">Sullivan</a></li>
            <li><a href="#">Le Corbusier</a></li>
            <li><a href="#">Mies</a></li>
            <li><a href="#">Gropius</a></li>
            <li><a href="#">Yamasaki</a></li>
        </ul>
        <!--[if lte IE 6]></td></tr></tbody></table></a><![endif]-->
    </li>

    <li>
        <a href="#">Postmodern<!--[if IE 7]><!--></a><!--<![endif]-->
        <!--[if lte IE 6]><table><tbody><tr><td><![endif]-->
        <ul>
            <li><a href="#">Venturi</a></li>
            <li><a href="#">Eisenman</a></li>
            <li><a href="#">Stern</a></li>
            <li><a href="#">Graves</a></li>
            <li><a href="#">Gehry</a></li>
        </ul>
        <!--[if lte IE 6]></td></tr></tbody></table></a><![endif]-->
    </li>

    <li>
        <a href="#">Digital<!--[if IE 7]><!--></a><!--<![endif]-->
        <!--[if lte IE 6]><table><tbody><tr><td><![endif]-->
        <ul>
            <li><a href="#">Xenakis</a></li>
            <li><a href="#">Lynn</a></li>
            <li><a href="#">Diller+Scofidio</a></li>
            <li><a href="#">Zellner</a></li>
            <li><a href="#">Hadid</a></li>
        </ul>
        <!--[if lte IE 6]></td></tr></tbody></table></a><![endif]-->
    </li>
</ul>

Таблица стилей для браузеров, поддерживающих CSS 2.1:

[-]
View Code CSS
#menu, #menu li, #menu ul {
    list-style: none;
    margin: 0;
    padding: 0;
}

#menu {
    display: block;
    width: 100%;
    position: relative;
}

#menu li {
    float: left;
    height: 2em;
    line-height: 2em;
}

#menu li a {
    float: left;
    border: 1px solid red;
    vertical-align: middle;
    padding: 0 .5em;
    width: 100px;
}

#menu li ul {
    display: none;
    position: absolute;
    top: 2em;
    left: 0;
    margin-top: 1px;
    width: 100%;
    background: #FFF;
    height: auto;
}

#menu li.on ul, #menu li:hover ul {
    display: block;
    z-index: 10;
}

#menu li:hover ul {
    z-index: 100;
}

#menu li li a {
    display: block;
    border: 1px solid red;
    vertical-align: middle;
    padding: 0 .5em;
}

Презентационные стили:

[-]
View Code CSS
#menu > li + li {
    margin-left: -1px;
}

#menu li ul li + li {
    margin-left: -1px;
}

#menu li a {
    outline: 0;
    text-decoration: none;
}

#menu li.on {
    background: yellow;
}

#menu li:hover a, #menu li a:hover, #menu li a:hover a {
    background: #EEE;
}

#menu li ul li:hover, #menu li ul li a:hover {
    background: #EAFBFC;
}

Более детально это всё объяснено в предыдущей статье.

Теперь будем лечить IE6. У меня этот процесс занял несколько часов, но результат стоил того — оно работает!!!

[-]
View Code CSS
* html #menu {
    overflow-x: hidden; /* Скрыть побочный эффект следующего исправления */
}

* html #menu li ul {
    display: block;
    z-index: 1;
    margin-top: 2px;
    overflow: visible;
    /* Это исправляет неверное определение ширины - абсолютное значение width: 100% без этих строк было бы равно ширине родительского <a> */
    padding-right: 1000em;
    margin-right: -1000em;
}

* html #menu li.on a table,
* html #menu li a:hover table
{
    visibility: visible;
}

* html #menu li.on a table ul {
    z-index: -1; /* Ключевое исправление - без него меню правильно работать не будет. Предназначено для исправления последствий многочисленных багов в реализации z-index. Благодаря этому исправлению, все li a:hover table, находящиеся перед li.on table, будут нормально отображаться (не будут перекрываться li.on table) */
}

* html #menu li a:hover table ul {
    z-index: 100;
}

* html #menu li a:hover {
    position: static;
}

/* У таблицы теперь статическая позиция. Абсолютное/относительное позиционирование вносит ужасный бедлам в и без того глючную реализацию z-index в IE6. */
* html #menu table {
    border-collapse: collapse;
    visibility: hidden;
}

Замечания по реализации:

  1. Из-за плохой поддержки z-index Ишаком возможны проблемы с border-top/bottom у крайних правых элементов меню;
  2. Из-за того, что пришлось использовать overflow-x, CSS не валидируется в рамках спецификации CSS 2.1 (но проходит валидацию CSS 3).

Тестовая страница лежит здесь.

Связанные записи

Комментарии к статье "Кросс-браузерное всплывающее гибридное меню на CSS без использования JavaScript" (5) »

  1. [March 23, 2008 06:50] Tigress:

    А почему не Sliding doors with a drop line?

    #1
  2. [March 23, 2008 07:00] Vladimir:

    На самом деле все просто: во-первых, у меня используется на несколько списков меньше (Stu Nicholls использует 2n списков, я — n+1).
    Во-вторых, в отличие от sliding doors, в данном случае не обязательно точно знать ширину каждого элемента меню. У меня это реализовано гораздо проще :-)
    В-третьих, собственный код всегда гораздо понятнее.

    #2
  3. [March 23, 2008 08:07] Максим Покровский:

    Весьма нестандартный подход. Конечно, для IE6 теряется весь семантичный смысл, но для него, вообще, много чего теряется…

    #3
  4. [March 23, 2008 09:29] Vladimir:

    Надеюсь, и IE6 скоро потеряется… :-) Довели бы в Micro$oft IE8 до ума, получился бы очень даже неплохой браузер. А IE7 и так уже вытесняет шестого Ишака.

    #4
  5. [April 1, 2008 09:46] Размещение блока неизвестного размера в центре страницы при помощи CSS | Ars Longs, Vita Brevis:

    [...] Максим Покровский на Кросс-браузерное всплывающее гибридное меню на CSS без JavaScript [...]

    #5

RSS feed for comments on this post. TrackBack URL

Оставить комментарий к записи "Кросс-браузерное всплывающее гибридное меню на CSS без использования JavaScript"

Изображения должны быть включены!

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Оставляя комментарий, Вы выражаете своё согласие с Правилами комментирования.

Subscribe without commenting