Журнал Начинающего Программиста 25, 2010-10-24 15:53
Здравствуйте,
Помните что:
Правильно заданный вопрос значительно ускорит и упростит решение проблемы.
Ролловер-меню
средствами CSS
Вот такое симпатичное меню мы сейчас станем делать. Если вы уже
пытались что-то подобное изобразить в визуальном редакторе, то
заметили, что там все построено на заковыристом Java-скрипте и выглядит
просто устрашающе. Мы же используем всего парочку картинок-заготовок,
обычный немаркированный список и немножко css. :)
Для начала нарисуем две картинки:
Это две части одной закладки меню. Правая делается такой длины, чтобы
при выбранном размере шрифта, на картинке помещалось самое длинное
слово из всего списка разделов. Ну, например,
"супермегакулфорумблинваще!". Каждая из картинок состоит из двух
частей, одна под другой. Верхняя часть — исходное состояние, нижняя —
при наведении мышки. Принцип довольно простой и изячный: в листе стилей
мы зададим разным состояниям различные координаты отображения. То есть,
картинка загружается вся целиком, но на странице мы изначально видим
только верхнюю чать. Когда мы подводим к кнопке мыша, то как бы
"выскакивает" нижняя часть.
Такой подход гораздо лучше, чем раздельные картинки, как при
классическом ролловере. Особенно когда разделов немало — все картинки
не успевают загрузиться сразу и выглядит это весьма некрасиво. А тут у
нас всего две маленькие картиночки, и причем на все меню разом,
независимо от количества разделов. Очень удобно.
Небольшое замечание: высота обоих картинок — число четное. Это понятно
— верхняя и нижняя половинки должны быть одного размера.
Наше меню мы обозвали тэгом tabs, хотя можно было бы и menu. Это не
столь важно. Лишь бы название было осмысленным, чтобы самому потом не
заплутать в коде. В листе стилей запишем следующий код:
#tabs li.active span { float: left; background:
url(images/tabright.gif) no-repeat right top; padding: 4px 20px 5px 10px; background-position: 100% -42px; }
Здесь мы сразу задали блоку меню ширину в 860 пикселей, высоту в 39px,
автовыравнивание по центру монитора, синий фон, семейство шрифтов, и
очистку с обоих сторон, чтобы ни справа, ни слева больше ничего лишнего
не повылезало.
Дальше задали списку ul поля и запретили отображение маркеров. Поэтому
список у нас и называется немаркированным.
Далее мы указали пунктам списка li расположение "в линию", иначе
по-умолчанию браузеры всегда располагают их в столбик.
А вот следующие два правила весьма интересны. В обоих указаны стили для
отображения ссылок a, но во втором появилось странное слово span. Зачем
это? Дело в том, что нам нужно привязать наши изображения кнопок к
тэгам в виде фона. В данном случае тэг у нас один — <a>.
Привязывать фон можно только к стартовому тэгу. К </a> уже ничего
не привяжешь. Поэтому мы и ввели дополнительный тэг span. Его еще
называют нейтральным, потому как он может быть использован везде и сам
по себе не несет какой либо значимой нагрузки, как например тэг ссылки
или абзаца.
Таким образом, мы привязали первую картинку (как фон) к тэгу a, а
вторую к span. Причем для первой указали расположение слева вверху и
запретили ей повторяться, а второй — справа вверху, и тоже без повтора.
Поля тоже заданы не абы как. Сначала мы показали левой картинке
отступить от левого края на 4 пиксела, то есть как раз на ширину
картинки. Если этого не сделать, то правая картинка, которая заведомо
шире, просто "съест" левую, потому что названия разделов у нас все-таки
не очень длинные. Что касается полей для правой картинки, то мы их
задали такими, чтобы справа от имени раздела оставалось столько же
пространства, сколько и слева (а иначе браузер "подожмет" слово под
обрез). Вобщем экспериментируйте и увидите. :)
Для ссылок задали белый цвет. А для активных — оранжевый на белом.
Следующие два правила как раз приказывают нашим картинкам спрятать верх
и показать низ при наведении на них мышкой. Для левой картинки мы
указали позицию в 0% (то есть крайнее левое положение) и минус 42
пикселя. Помните про четный размер высоты картинки? Мы просто "отняли"
у нее верхнюю часть. А так как картинка изначально загружена на
страницу полностью, то она и покажет нам нижнюю часть. Для правой
картинки мы указали, соответственно, 100% позицию (крайнюю справа) и
тоже -42 пиксела.
Возникает вопрос: почему мы сразу не видим на странице целые картинки?
А потому, что в самом начале для нашего блока менюшек мы задали высоту
всего в 39 пикселей (можно и 42, но так как браузеры по разному считают
отступы, то мы чуток перестраховались).
Все просто! :)
Два других правила мы написали для активного раздела. Это тоже понятно
— активный раздел не должен быть ссылкой, но должен ясно показывать,
что он в данный момент активен. То есть выглядеть так, словно на ссылку
навели мышку. Тут мы тоже указываем картинкам хитро выглядывать нижней
частью, но пристегнули их уже не к тэгам ссылок, а к тэгам строк списка
— li.
Не забываем везде указывать обтекание слева — (float: left;). Иначе
глюки неизбежны.
Вот вроде бы и все. Но IE все-таки браузер с характером, и наше
красивое меню, как-то некрасиво искажает. :( В данном уроке не видно,
но вот на собранной целиком странице получалась эдакая щелка между меню
и основным блоком. Это как раз происходит потому, что IE (в отличие от
других браузеров) по-своему высчитывает размеры полей и отступов. На
такое безобразие хитрые верстальщики придумали не менее хитрый болт,
называемый хаком. То есть спецом для IE в листе стилей делается
приписка (зачастую с указанием версии IE): "...сему поганцу показывать
мою гениальную менюху вот так: (и тут дополнительное правило)...".
Такой хак можно вписать в основной лист стилей, а можно пристегнуть
отдельным листом, дав на него соответствующую ссылку. Мы так и
поступим, и пристегнем к странице еще один css, обозвав его просто
ie.css. В нем мы запишем следующее:
#tabs a span { padding: 4px 20px 4px 10px; }
#tabs li.active span { padding: 4px 20px 4px 10px; }
Как видите, в отличие от основного листа, здесь мы указали нижнее поле
на один пиксель меньше (4 вместо 5). Вот и вся трабла.
Ну и наконец код самой страницы (тут только меню, все остальные,
положенные для страницы тэги, опущены):