Танцы с бубном для блондинок, или о tabbed menus и хитрой работе с графикой

    Собственно, перепал мне не так давно небольшой заказец. Вроде и несложный — а потанцевать с бубном немного пришлось. А всё из-за того, что заказчик оказался немного «падкой на дизайн блондинкой» (образно говоря), и требовал строгого соответствия конечного результата макету. Требовал попиксельно, и его совершенно не волновали такие вопросы, как валидность, семантичность и всё такое. «Хоть таблицами сверстай, а сделай». И сегодня речь пойдёт о том, как в таких условиях сделать весьма хитровыделанно нарисованное меню табами. Как и за свой код не устыдиться, и не пасть в грязь лицом перед заказчиком, вот в чём вопрос?

    Собственно, вот фрагмент эскиза, отвечающий за то самое меню:
    image

    А вот как оно должно выглядеть, когда выбран другой пункт:
    image

    Неудобно, правда? Мало того, что не получится создать единый background для пунктов меню (из-за этого несчастного градиента и не только), а придётся назначать стили каждому пункту индивидуально (пришлось взять с заказчика честное пионерское слово, что структура меню впредь останется неизменной), так ещё и приходится думать о том, как правильно отобразить «нахлёсты» на другие пункты до и после активного. Но нет ничего невозможного, и для реализации подобной вещи никаких таблиц нам не понадобится, и «костылей» будет минимум. Вся суть — в хитрой работе с графикой.

    Но перед тем, как стилизовать меню, нам нужно позаботиться о блоке под ним. Задаём ему однопиксельный border (тот самый, который мы видим под неактивными пунктами) и бэкграунд в виде «уголка» в левом верхнем углу. Мы не будем думать о том, как этот «уголок» отображать или нет в самом меню — пусть он лежит и кушать не просит в блоке под ним, а в случае необходимости мы его просто закроем.

    Теперь для каждого пункта меню мы должны нарезать по две картинки — соответственно, неактивный и активный пункт меню. А для всех пунктов меню, кроме первого, мы должны ещё предусмотреть вариант «неактивный-после-активного», у которого слева отсутствует нижняя кромка. Собственно, вот первый пункт меню в неактивном виде:
    image

    А вот он же, но активный:
    image

    Обратите внимание — подложка для активного пункта чуть больше по высоте — это нам нужно как раз для того, чтобы закрывать «уголок» внизу.

    С другими же пунктами — всё чуть сложнее. Разберём на примере второго пункта меню. Неактивный пункт делается по тому же принципу, как и первый:
    image

    «Неактивный-после-активного» отличается от него только отсутствием нижнего бордера слева:
    image

    А для активного пункта меню мы должны предусмотреть «захлёст» слева, чуть «оттяпав» от предыдущего пункта:
    image

    Теперь, нарезав графику, принимаемся за код. Учитывая, что реализовано это меню в конечном итоге на Drupal с помощью модуля menu-attributes (или как его там), а соответственно, это накладывает свою специфику, то стилизовать мы будем не тэг li, а вложенные в него ссылки. Сам HTML-код за вычетом CMSного мусора у нас вот такой:

    <div id="topnav">
    <ul class="menu"><li class="leaf first active-trail "><a href="#" id="apartments" title="Жилые квартиры">Квартиры</a></li>
    <li class="leaf"><a href="#" id="houses" title="Частные дома, коттеджи, дачные постройки">Дома и дачи</a></li>
    <li class="leaf"><a href="#" id="ground" title="Участки под индивидуальное строительство">Земельные участки</a></li>
    <li class="leaf last"><a href="#" id="business" title="Склады, офисы и т.п.">Промышленная недвижимость</a></li>
    </ul>
    </div>


    Как видите, практически ничего лишнего, и не нарушена семантика. Все «гламурности» и «рюшечки» мы сделаем в CSS. У нас будет два файла стилей — под нормальные браузеры и под ослика IE (надеюсь, мне не надо вас учить, как подключать этот файл через условные комментарии). Сразу оговорю, что под «осликом IE» имею в виду седьмую версию — ибо ввиду массового распространения Висты и третьего сервиспака под WinXP шестой уже сдаёт свои позиции… so screw this nightmare. :) В любом случае, даже в шестом «ослике» вёрстка не поедет, и из функционала меню не сработает разве что реализованный на селекторах «неактивный-после-активного». Так что пофигу. Поехали!

    Сначала разберёмся с позиционированием и высотой самого блока. Пристальный глаз уже наверняка заметил — нужно схлестнуть нижний бордер картинок и верхний бордер блока под меню. А для этого мы нижний блок чуть подтянем, попутно (сенькс за багрепорты в комментах) сдвинув линки на 1 пиксель влево:

    div#topnav ul.menu {
    list-style-type: none;
    margin: 0 0 -1px 0;
    line-height: 44px;
    font-size: 0; /* это чтобы переводы строки между пунктами не отображались как пробелы */
    padding-left:1px
    }
    div#topnav ul.menu li {
    display: inline;
    }
    div#topnav ul.menu a {
    font-size: 14px;
    padding: 15px 24px 15px 15px;
    height: 25px;
    margin-left:-1px;
    }


    Сразу же — поправляемя всю эту кухню в таблице для IE (ибо есть свои нюансы отображения)

    div#topnav ul.menu {
    position: relative;
    top: 3px;
    list-style-type: none;
    margin: 0px;
    line-height: 44px;
    font-size: 0;
    padding-left: 1px;
    }
    div#topnav ul.menu li {
    display: inline;
    }
    div#topnav ul.menu a {
    font-size: 14px;
    margin: 0 0 0 -1px;
    padding: 15px 24px 15px 15px;
    height: 25px;
    }


    Теперь прописываем бэкграунды и размеры для активных и неактивных пунктов меню. Алгоритм такой: для первого пункта увеличиваем высоту, если пункт активен (закрываем уголок). Прочие пункты, если активны, сдвигаем на 6 пикселей влево (помним про нахлёсты).

    div#topnav ul.menu li a#apartments {
    width: 80px;
    background: url('images/menu-1-inactive.gif') top left no-repeat;
    }
    div#topnav ul.menu li a#houses {
    width: 94px;
    background: url('images/menu-2-inactive.gif') top left no-repeat;
    padding-right:26px;
    }
    div#topnav ul.menu li a#ground {
    width: 150px;
    background: url('images/menu-3-inactive.gif') top left no-repeat;
    padding-right:26px;
    }
    div#topnav ul.menu li a#business {
    width: 240px;
    padding: 15px 60px 15px 15px;
    background: url('images/menu-4-inactive.gif') top left no-repeat;
    }
    div#topnav ul.menu li.active-trail a#apartments {
    background: url('images/menu-1-active.gif') top left no-repeat;
    padding-bottom: 25px;
    }
    div#topnav ul.menu li.active-trail a#houses {
    width: 101px;
    margin-left: -6px;
    padding-left: 22px;
    background: url('images/menu-2-active.gif') top left no-repeat;
    }
    div#topnav ul.menu li.active-trail a#ground{
    width: 157px;
    margin-left: -6px;
    padding-left: 22px;
    background: url('images/menu-3-active.gif') top left no-repeat;
    }
    div#topnav ul.menu li.active-trail a#business {
    width: 247px;
    margin-left: -6px;
    padding-left: 22px;
    background: url('images/menu-4-active.gif') top left no-repeat;
    }


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

    /* this is not supported in IE 6, so screw IE6, we want some CSS2 beauty*/
    div#topnav ul.menu li.active-trail+li>a#houses{
    background: url('images/menu-2-inactive-after-active.gif') top left no-repeat;
    }
    div#topnav ul.menu li.active-trail+li>a#ground{
    background: url('images/menu-3-inactive-after-active.gif') top left no-repeat;
    }
    div#topnav ul.menu li.active-trail+li>a#business{
    background: url('images/menu-4-inactive-after-active.gif') top left no-repeat;
    }


    И вот, уже скриншот с реальной страницы в браузере:
    image

    Собственно, всё. И это с минимальными изменениями можно экстраполировать на любую похожую задачу. Главное — запомнить алгоритм. А если интересно — в соответствующем блоге расскажу про то, как всё это грамотно и логично реализовать на внутренней структуре Drupal Раз уж интересно — то вот как оно на Друпале реализуется: habrahabr.ru/blogs/drupal/52601 ;)
    Share post
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 99

      +13
      я часто задумываюсь, что кроме программирования хорошо бы подучить и основы верстки, но честно говоря — после этого топика мне кажется что мне это не дано.
      автор — вы молодец, а проделанная работа мне кажется чем-то сродни микрохирургии.

      ЗЫ имхо, не надо про Друпал, лучше еще про верстку!
        0
        Для полноты пример можно бы было выложить в Сети.
          +1
          у примера пока доменного имени нет, увы, и именно поэтому я не стала размещать линк в основном посте. Так же — 174.132.129.154/~ndn/
            –1
            Неплохо. Для Firefox к ссылкам добавьте outline: none;
              +2
              Нет! Outline необходим для работы с клавиатуры. Зачем намеренно ухудшать accessibility?
                +1
                В таком случае, accessibility можно сохранить с помощью a:focus. В посте указывалось, что клиент акцентировался на дизайне.
              0
              в опере в правой части макете несходится в паре мест
                0
                какая версия оперы?
                  0
                  Опера 10 alpha:

                  Опера 9.63:


                  Странности слева, у первого таба несовпадение цвета, на «Земельные участки» активный таб слишком далеко заехал.
                    0
                    В IE7 и Safari 3.2.2 тоже несовпадение цвета и проблема с «Земельные участки».
                    Сложно всё-таки заставить отрисовываться везде одинаково. Но думаю, поправимо.
                      +1
                      хм, проверяйте ещё раз — пофиксено (хотя в опере 9.63 под Линуксом у меня вниз ничего не уползает). Ох, чую, сурово придётся пост апдейтить, но, в любом случае, благодарю за багрепорты :)
                        0
                        В 9.63 под Win всё-равно уползло вниз.

                        А проблемы с третим табом пропали.
                      0
                      У меня — 9,63, и тоже справа не все в порядке.
                  0
                  ФФ 3.0.6, Линукс с родными шрифтами:
                  img413.imageshack.us/img413/4821/screenshot16.png

                  но это уже привычная картина на перегруженных графикой сайтах
                    0
                    о как. Уже второй человек в комментах жалуется на 3.0.6 — честно говоря, я не в курсе, неужели там чем-то кардинально отличается рендеринговый движок?
                      0
                      тем более, что не только на сабжевом сайте такое…
                0
                Ещё бы ссылочку на живой пример ;-)
                  0
                  см. выше — закинула
                  0
                  За выполненную работу +1 :). А с заказчиком я согласен кстате, задача ставится все таки не из того, как удобнее сделать — иначе вообще просто синие ссылки бы стояли :). Тут для заказчика главное чтобы это возможно было сделать, и за приемлемые сроки, тогда может требовать.
                    +3
                    Кунг-фу CSS настоящее.
                      +1
                      Фаталити, я бы сказал :))
                        0
                        Всё больше понимаю, что необходимо Хабру намного больше вводных статей :)
                        0
                        Mac OS X 10.4.11 Firefox 3.0.6 — всё ужасно. Все табы разъехались. Особенно последний («Версия для печати») — в Сафари посмотрел, как он должен быть на самом деле, — он в Сафари ниже всех табов, в Фаерфоксе этот таб на одном со всеми уровне.
                          0
                          Mac OS X 10.5.6 скриншоты комментом ниже. ФФ и WebKit.
                            0
                            oops — картинка — www.k2fx.com/share/ScreenSnapz.png — для меня тег, увы, здесь запрещен.
                              0
                              это как так? в FF3 всё тестировано. То ли лыжи не едут, то ли я чего-то не понимаю…
                                0
                                Ещё раз: Mac OS X 10.4.11 Firefox 3.0.6 — полная лажа, смотрите картинку — www.k2fx.com/share/ScreenSnapz.png

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

                                Так что или дальше с бубном танцуйте, или вернитесь назад в свой работе к тому месту, с которого пришлось браться за бубен. IMHO.
                          0
                          Не все так идеально, но в принципе хорошо.


                            0
                            по поводу 1 и 3 — сорри, так было нарисовано. По поводу 3 — что за браузер?
                              0
                              упс… по поводу п.2, в смысле :)
                                0
                                Mac OS X, Webkit, Safari, Firefox 3
                                  0
                                  значит, дело в рендеринге шрифтов. Я попробую разобраться. Сенькс за багрепорт.
                                    0
                                    хм, чуть поправила — лучше?
                                      0
                                      mac os x, safari — баг остался
                                0

                                В Chrome 2.0.164 \ Win7 появляются странные линии.
                                  0
                                  под W7 не тестировалось… в других осях в Хроме та же проблема?
                                    0
                                    XP, Chrome 2.0.164.0 — так же
                                      0
                                      сделала небольшой фикс — господа хромоюзеры, проверьте, плз. Если работает — проапдейчу пост.
                                        +1
                                          0
                                          про п.1 знаю, но так было в макете, и исправление этого бага будет сплошным пииии… пиксель-артом %) Хотя, раз оно уж вот так вот бросается в глаза — надо будет попробовать. С п.2 ещё поразбираюсь (просто у меня Линукс, под него нет Хрома — а browsershots почему-то иногда не выдаёт всей информации). В любом случае — благодарю за замечания :)
                                            0
                                            Пишите ещё, потестим :-)
                                              0
                                              по идее — fixed
                                                0
                                                chrome 1.0.154.48\Win7 линия в 4 пункте
                                      0
                                      xp xp2 chrome 1.0.154.48 аналогично
                                    +5
                                    я только добавлю, что все картинки стоило засунуть в один файл и использовать технику css спрайтов
                                      0
                                      окей, на будущее — учту. Почитала про это дело — действительно, интересная технология, благодарю за информацию.
                                      0
                                      Ещё бы ссылочку на живой пример ;-)
                                      • UFO just landed and posted this here
                                          +2
                                          Я подобное меню делал однажды гораздо проще — просто утягивал каждый пункт направо отрицательным полем. Но там тоже было извращение — то ли пришлось порядок пунктов менять, то ли каждому z-index выставлять руками.

                                          В вашем случае это сложнее, ибо захлёст перекрывает надпись.
                                            0
                                            Я также использовал z-index:; и отрицательный margin для реализации подобного меню: marow.ru/site/unora/

                                            Первоначально меню реагировало на наведение мыши, а надписи на тикетах были текстом, но заказчик очень попросил упростить макет)

                                            На мой взгляд, у автора топика неординарное мышление. Респект!
                                            +1
                                            > Сразу оговорю, что под «осликом IE» имею в виду седьмую версию — ибо ввиду > массового распространения Висты и третьего сервиспака под WinXP шестой уже > сдаёт свои позиции

                                            Ну это вы поторопились. Хоть глобально в рунете сейчас у IE6 только 15% (что тоже немало, кстати), но на обычных негиковских сайтах его доля запросто достигает 30%.
                                              0
                                              Всегда было интересно при скольких процентах популярности ИЕ6 вебмастера начнут отказываться от него?
                                                0
                                                не знаю как, я статистике такой не верю и в первую очередь проверяю все на ИЕ6

                                                так как по моим личным наблюдениям — доля эта гораздо больше 30ти.
                                                  0
                                                  все зависит от ресурса, у меня 40% — Опера, 34% — Ослик, из них 6 уже меньше, чем 7.
                                                  0
                                                  >при скольких процентах популярности ИЕ6 вебмастера начнут отказываться от него
                                                  Веб-мастера могут начать отказываться хоть сейчас. А вот заказчик сначала просчитает процент недополученной прибыли, и если этот процент будет заметен, он погонит такого «веб-мастера» куда подальше. И правильно сделает.
                                                    0
                                                    Веб-мастер тоже своего рода предприниматель и также может считать свою прибыль (в основном). Поэтому мой вопрос можно отнести и к заказчику и к исполнителю. В конечном счёте однажды от него откажутся все. Вот меня и интересует это «критическое» значение.
                                                      +1
                                                      О чем вы? В цивилизованном мире процент пользователей Оперы/Cафари/Хрома намного меньше процента пользователей ie6. Но ведь никому в голову не придет обсуждать нужно ли поддерживать ли эти броузер. И какова критическая планка.
                                                      См. цифры:
                                                      www.w3schools.com/browsers/browsers_stats.asp
                                                      www.thecounter.com/stats/2009/February/browser.php
                                                      www.w3counter.com/globalstats.php
                                                      en.wikipedia.org/wiki/Usage_share_of_web_browsers

                                                      Нет никакой планки. А если она есть то она определяется только требованиями бизнеса. Одна десятая процента оборота какого-нибудь интернет-магазина типа ебай-ком стоят того, чтобы трахаться с ie5 и не петюкать.
                                                        –1
                                                        Спасибо за ответ! Теперь мне совершенно ясно, ebay.com будет работать с пятёркой даже при его рейтинге равном 0.1% ))

                                                        Поясню свою мысль более наглядно.
                                                        Если во время юстиниановой чумы погибло несколько десятков человек, все это назвали эпидемией.
                                                        В настоящее время от чумы погибает около 2,5 тысяч, но при этом об эпидемии речи не идёт.

                                                        Майкрософт давно перестал поддерживать ие5, но реальное положение дел зависит не от гигантов, а от рядовых пользователей, которые и создают картинку рейтинга браузеров.

                                                        Даже если через 1000 лет ebay.com всё ещё будет поддерживать ие5, это ровным счётом ни на что не влияет. В мире ничего никогда не бывает на 100%. Это тоже понятно.
                                                        Я же хочу узнать сколь низким должен быть процент рейтинга этого недобраузера, чтобы веб-мастера (по крайней мере их большая часть) с чистой совестью отказалась от поддержки этого программного продукта.
                                                          0
                                                          Пардон:
                                                          «погибло несколько десятков ТЫСЯЧ человек»
                                                            –2
                                                            > этого недобраузера,
                                                            недобраузер он только для недоучек :)
                                                              0
                                                              Я рад за вас!
                                                                +1
                                                                Спасибо, но вы не расстраивайтесь. Таких как вы — полхабра.
                                                  –2
                                                  это делается с помощью 1 изображения и, возможно, jquery если надо :hover
                                                    –1
                                                    а вот font-size: 0 это ктуто, неужели работает?
                                                    +1
                                                    Занятно. А можно исходничек в PSD? Очень хочется самому поиграться :)
                                                      0
                                                      По идее главный минус в том, что ссылки при наведении никак не реагируют. Да и подчеркивание в таком меню считаю лишнимю

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

                                                      Не все продумали.
                                                        0
                                                        убирание подчеркивания при наведении имею ввиду
                                                        0
                                                        Спасибо.
                                                          +1
                                                          При попытке применить данные настройки к такому же списку, но без указания width каждого li элемента, получил список как будто с display:block. При этом display: inline ни при каких условиях работать как от него требовалось не собирался.

                                                          Немного поискав наткнулся на следующее решение — вместо display: inline использовать float: left,
                                                          т.е. будет вот так:

                                                          div#topnav ul.menu li {
                                                                float: left;
                                                          }
                                                          


                                                          Мою проблему такая замена решила полностью.

                                                          За статью спасибо.
                                                            0
                                                            тоже вариант. Благодарю за ценное дополнение!
                                                            0
                                                            сайт_дуры.JPG - image uploaded to Picamatic

                                                            chrome 1.0.154.48, все то же + все равно видны несовпадения цветов
                                                              +1
                                                              блин простите за название скрина))) все время привык сохранят скриншоты под дебильными но понятными мне названиями, не думал что пикаматик его сохранит, это название
                                                                +4
                                                                вы-то конечно очень умная как я считаю
                                                                  +1
                                                                  Никтобы не заметил, еслиб не написали. Наверное не заметил.
                                                                0
                                                                У меня Амайя смотрится ужасно.

                                                                p.s.
                                                                  +1
                                                                  p.s.
                                                                  Надо в ТЗ указывать в каких броузерах и в каких ОС должно работать.
                                                                  Подгонять под все броузеры мира не дело — потому что их воз и маленькая тележка.
                                                                    0
                                                                    у меня стояла задача на IE, FF и Оперу, но я попутно протестила ещё в Konqueror. Честно говоря, да, чую, пока я под всё подгоню — офигею, тот проект столько не стоит :) А что такое «Амайя»?
                                                                      0
                                                                      Амайя — это W3C браузер )
                                                                      www.w3.org/Amaya/
                                                                        0
                                                                        IE 7 — присмотритесь к промежутку между 1 и 2рой вкладкой.
                                                                        особенно несостыковка видна при открытой второй вкладке
                                                                          0
                                                                          fixed
                                                                            0
                                                                            не все, переключись на вкладку дома и дачи — баг в том же месте ;)
                                                                              0
                                                                              у меня нет IE. Вообще. Чтобы проверить в нём страницу, я пользуюсь сервисом browsershots :) Но на слово верю, щас ещё пиксель прибавлю :)
                                                                    +1
                                                                    Дизайнера приговорить к году кроссбраузерной, семантичной вёрстки!
                                                                      0
                                                                      увы, я не дизайнер :)
                                                                      0
                                                                      несовпадения цветов у PNG должны вылечиться после удаления всех чанков
                                                                      у меня на странице
                                                                      174.132.129.154/~ndn/business
                                                                      в IE7, Chrome, Fx3, Opera10 у земельныз участков правое загругление вправо немного уехали. Причем в Fx чуть меньше, чем в остальных
                                                                        0
                                                                        уже поправила
                                                                          0
                                                                          спасибо, но в Fx3 теперь на 1 пиксель ближе, чем должно быть. Наверное, придется хак использовать…
                                                                            0
                                                                            а вот это уже ИМХО не очень заметно — честно говоря, даже если не удастся сделать хак, то меня вряд ли побьют :)
                                                                              0
                                                                              да, но ведь заметят профессионалы типа Вадима :) а это, ИМХО, гораздо важнее :)
                                                                        0
                                                                        пара мелочей, не важных правда:
                                                                        вместо

                                                                        div#topnav ul.menu li a#apartments
                                                                        div#topnav ul.menu li.active-trail a#apartments

                                                                        (и аналогичных) можно, по идее, просто

                                                                        #apartments
                                                                        .active-trail #apartments

                                                                        и я бы еще вынес background: top left no-repeat; в какое-нибудь правило «повыше», а для отдельных ссылок менял бы только background-image.

                                                                        Хотя все это — уже дело вкуса, кому как нравится.
                                                                          +4
                                                                          А если меню фиксированное…
                                                                          Может, просто сделать 4 картинки и всё?
                                                                          И поверх текстовые ссылки?
                                                                            +1
                                                                            Действительно. Если на увеличение шрифта не расчитано, то не было смысла так извращаться. Я подобную проблему решил таблицами, не побрезговал.
                                                                              +1
                                                                              Тоже сразу так подумал, удивился, что никто не предложил раньше.
                                                                              Возможно, тут дело не столько в результате, сколько в вёрстке ради вёрстки.
                                                                                0
                                                                                пришлось бы всё равно извращаться, меняя бэкграунд в зависимости от текущей вкладки. А задача эта ни разу не банальная, учитывая, что вкладка должна быть активной и при выборе дочернего в ней элемента.
                                                                                0
                                                                                Опишите как Вы все это на Drupal натянули :-).
                                                                                Я сам частенько такими извращениями занимаюсь.
                                                                                0
                                                                                Жуть… При таком варианте нужен флеш «без вариантов». Тут уже не до семантики…
                                                                                PS: Но за код респект.

                                                                                Only users with full accounts can post comments. Log in, please.