В этот раз мы сделаем нечто более востребованное, нежели эффект зебры. Мы реализуем панель типа аккордеон. Использовать ее в дальнейшем можно по разному - выпадающее вертикальное меню, оформление страницы "вопрос-ответ" и т.д. Тут полет фантазии не ограничен.
Разметку можно выполнить по разному. В этот раз реализуем вариант на основе списков. Вот что у нас должно получиться в итоге:
При клике по пунктам Новости и О нас должны будут открываться подпункты этих категорий. При повторном клике по названиям категорий подпункты должны прятаться.
Вспоминаем основы (добрый день html и css) и набросаем, ставшую классикой, разметку для выпадающих меню из четырех пунктов, два из которых будут иметь вложенные списки:
<ul> <li><a href="#">Главная</a></li> <li><a href="#">Новости</a> <ul> <li><a href="#">Хроника</a></li> <li><a href="#">Политика</a></li> <li><a href="#">Спорт</a></li> <li><a href="#">За рубежом</a></li> </ul> </li> <li><a href="#">О компании</a> <ul> <li><a href="#">Отзывы</a></li> <li><a href="#">События</a></li> </ul> </li> <li><a href="#">Связь с нами</a></li> </ul>
С помощью css придадим менюшке приличный внешний вид. что бы оно выглядело, как на картинке:
ul { margin:20px; width:200px; list-style:none; } li a { padding:5px 10px; display:block; font-size:14px; font-weight:bold; color:#000; text-decoration:none; background:#e4e7ea; border-bottom:1px solid #d4d9df } ul ul { margin:0; display:none; } ul ul a { padding-left:20px; font-size:12px; color:#8b8b8b; background:#ededed; }
Глянем в браузере на результат. Все выглядит как нужно, вот только если пощелкать по ссылкам, увы, ничего не происходит - меню не работает (под категории не открываются). Исправлять этот недочет будем, как нетрудно догадаться, с помощью jQuery.
Используем click(), next() и toggle():
$(function () { $('ul li a').click(function() { $(this).next().toggle(500); }); });
Тут все просто, отбираем в набор ссылки, которые находятся внутри элемента li, ожидаем пока по ним кликнут и с помощью метода toggle() делаем видимым соседний со ссылкой элемент. По коду это элемент вложенный ul, который является родителем для подменю и имеет в css стиль display:none. Метод toggle() присвоит ему значение display:block и элемент станет видимым. Повторный клик по той же ссылке вернет элементу ul его начальное значение. Для более плавного появления/исчезновения субменю, методу toggle() можно передать параметр в миллисекундах, за который он будет отображать/прятать элемент.
Посмотрим на результаты проделанной работы. При клике на ссылках "Новости" и "О нас" подменю появляется, если оно было скрыто при повторном клике прячется. Только вот не очень то мне нравится его появление... Метод toggle() использует методы hide() и show(), которые, на мой взгляд, не подходят к данной ситуации (впрочем, может кому то и понравится).
Давайте изменим js так, что бы субменю открывались в виде слайдера. Перепишем код, используя методы click(), next(), animate() и toggle():
$(function () { $('ul li a').click(function() { $(this).next().animate({'height':'toggle'}, 500); }); });
В данном случае мы реализовали метод toggle() через метод animate(), применив его только к высоте срытых элементов. Посмотрим что получилось. Так, пожалуй, все стало смотреться значительно лучше - можно сказать, мы добились того, чего хотели. Но увы, это всего лишь иллюзия.
Представьте, что меню расположено не в самом верху страницы, а где нибудь в центре экрана (этого легко добиться, если установить в css верхний отступ для body 200 - 300px). Теперь, если проскролить страницу к самому низу и кликнуть по любому пункту меню, то будет наблюдаться резкий скачек вверх. Это происходит каждый раз, когда мы кликаем на "пустую" (никуда не ведущую) ссылку. Казалось бы - исправить недочет просто. Запретим переход по ссылкам и будет нам счастье. Благо в jQuery это можно сделать двумя способами - либо просто написать return false;, либо использовать функцию, отменяющую события по умолчанию preventDefault();.
$(function () {
$('ul li a').click(function() {
$(this).next().animate({'height':'toggle'}, 500);
return false;
});
});
//или
$(function () {
$('ul li a').click(function(event) {
$(this).next().animate({'height':'toggle'}, 500);
event.preventDefault();
});
});
Отлично - страница перестала скакать. Но теперь, если в подменю задать ссылке реальный путь, то никакого перехода не будет - мы же запретили это действие. Придется изобретать что то другое. Самое первое, что по идее приходит в голову, запретить переход только для тех ссылок, которые являются ссылками верхнего уровня и имеют вложенные пункты. Что ж, давайте попробуем - создадим переменную в которой будем хранить элемент, являющийся следующим для текущей ссылки и условие, в котором будем проверять, если этот элемент ul и он видимый, то запрещаем переход.
И еще одна маленькая деталь. Если пользователь быстро кликнет по пункту меню несколько раз, то анимация отработает для каждого клика. В этом случае меню покажется и спрячется столько раз, сколько было сделано щелчков. Что бы избавится от этого нежелательного действия, воспользуемся методом stop().
$(function () {
$('ul li a').click(function() {
var checkElement = $(this).next();
checkElement.stop().animate({'height':'toggle'}, 500);
if((checkElement.is('ul')) && (checkElement.is(':visible'))) {
return false;
}
});
});
//или
$(function () {
$('ul li a').click(function(event) {
var checkElement = $(this).next();
checkElement.stop().animate({'height':'toggle'}, 500);
if((checkElement.is('ul')) && (checkElement.is(':visible'))) {
event.preventDefault();
}
});
});
Проверяем полученный результат. Все замечательно - меню не прыгает (первая и последняя ссылки не в счет - у них же нет вложенных пунктов, а значит они не будут пустыми в рабочем проекте). Внутренние ссылки на клик реагируют. В общем, все работает как и задумывалось.
Можно придумать еще много способов реализации данной задачи, используя различные методы - важно, что бы был достигнут нужный эффект и при этом остались удовлетворенными желания заказчика.
Однако, не всегда стоит острая необходимость использовать конструкцию ul li. В следующей статье рассмотрим возможность реализации аккордеона без использования списков (что, кстати, избавляет нас от некоторых проблем, свойственных для разметки, рассмотренной в этой статье).
Исходный код окончательного варианта можно скачать по ссылке ниже.