ТЗ. На сайте требуется сделать плавающее вертикальное меню (чтобы при скроллинге страницы меню всегда было навиду). Задача усложняется тем, что вертикальное меню идёт не от самого верха — разбиение на колонки начинается после шапки и горизонтального меню. Следовательно, вертикальное меню должно плавать только тогда, когда его верхняя граница скрывается за верхним краем области просмотра браузера.

плавающее боковое меню

Реализация плавающего вертикального меню

Для реализации плавания меню я буду использовать JavaScript и его высшее воплощение — jQuery. Исторически так сложилось, что для данного сайта я использую jQuery версии 1.2.6, потому можно использовать мой пример на фреймворке моей версии и выше. Подключаем jQuery:

<html>
<head>
...
<script src="js/jquery-1.2.6.js" type="text/javascript"></script>
</head>

Примерно так выглядит HTML-код самого меню (за исключением технических моментов, не касающихся данной темы):

<div id="lmenu">
<ul>
<li><a href="page-1.html''>Страница 1</a>
<li><a href="page-1.html''>Страница 2</a>
<li><a href="page-1.html''>Страница 3</a>
...
</ul>
</div>

Ключевым моментом здесь является присвоение слою меню идентификатора «lmenu» — можно поименовать любым другим уникальным именем и далее обращаться к элементу по этому имени. Немного о стилях. Чтобы иметь возможность изменять положение по вертикали слою меню, ему надо задать абсолютное позиционирование. При этом надо учеть, что абсолютно позиционированные элементы не участвуют в разметке страницы (элементы могут накладываться друг на друга, если не задать дополнительные отступы). Вот мои стили для меню и контентной части (которая располагается справа от меню):

#lmenu {
        position:absolute;
        top: 357px;
	width: 250px;
}
DIV.content {
	margin: 10px 10px 0 0;
	float: right;
	width: 675px;
}

Значение «top: 357px;» было определено заранее. При помощи JavaScript. Для этого в страницу был вставлен следующий JS-код:

<script type = "text/javascript">
  $(document).ready(function () {
    alert ($('#lmenu').css('top'));
  }
</script>

Этот скрипт отобразил в модальном окне свойство «top» моего меню — то значение, которое было принято при разметке страницы браузером изначально, без явного указания. Это число нам ещё пригодится. Теперь всё готово к тому, чтобы написать основной код, обеспечивающий эффект плавания меню.

<script type = "text/javascript">
// какая часть окна проскроллена - начальное значение
var scroll_top = 0;
// этот код будет выполнен сразу после загрузки документа:
$(document).ready(function(){
  // отступ меню от верхнего края страницы
  var lmenu_top = parseInt ($('#lmenu').css('top'));
  // смещение меню по вертикали - начальное значение
  var offset_lmenu = 0;
  // этот код будет выполнен при скроллинге страницы:
  $(window).scroll(function () {
    // какая часть окна проскроллена (в пикселях)
    scroll_top = $(document).scrollTop();
    // меняем положение меню, если это нужно
    if (scroll_top > lmenu_top || offset_lmenu > 0) {
      // новое значение смещения меню
      offset_lmenu = scroll_top - lmenu_top;
      // перетаскиваем меню
      $('#lmenu').animate({top:lmenu_top+offset_lmenu},{duration:300,queue:false});
    }
  });
});
</script>

Ключевую роль здесь играет функция $('#lmenu').animate () — она анимировано изменяет свойство «top» нашего меню. {duration:300,queue:false} — это время выполнения эффекта в миллисекундах. Задержку можно указать просто числом, но тогда меню при скроллинге дёргается.

Далее решено было добавить к меню кнопку «вверх» — так, чтобы эта кнопка появлялась тогда, когда меню начинает плыть вниз, и пропадала, когда меню доплывает до верхней части границы. К меню добавляем ещё один пункт:

<li id="scroll_on_top"><input type="button" value="Вверх" onClick="scrollit()">

При помощи стилей делаем этот пункт изначально невидимым:

#scroll_on_top {
	display: none;
}

Описываем функцию, которая будет выполняться при нажатии кнопки «Вверх»:

<script type = "text/javascript">
function scrollit () {
  for (i=scroll_top; i>200; i=i-200) { self.scroll(1,i) }
  self.scroll(1,0)
}
</script>

Здесь используется ещё не упомянутая переменная «scroll_top» — её значение будем получать во время скроллинга по странице:

<script type = "text/javascript">
  $(window).scroll(function () {
    scroll_top = $(document).scrollTop();
  }
</script>

При нажатии на кнопку «Вверх» запускается цикл, в котором значение проскролленности страницы уменьшается от текущего значения до нуля при помощи функции self.scroll (1,i). Для того, чтобы показать и скрыть кнопку «Вверх» в нужный момент используются следующие инструкции соответственно:

$('#scroll_on_top').css('display','list-item');
$('#scroll_on_top').css('display','none');
</pre>
Собираем всё вышеописанное в кучу. Теперь без комментариев, чтобы не загружать код:
<pre lang="javascript" line="1" escaped="true"><script type = "text/javascript">
var scroll_top = 0;
$(document).ready(function(){
  var lmenu_top = parseInt ($('#lmenu').css('top'));
  var offset_lmenu = 0;
  $(window).scroll(function () {
    scroll_top = $(document).scrollTop();
    if (scroll_top > lmenu_top || offset_lmenu > 0) {
      if (offset_lmenu == 0) { $('#scroll_on_top').css('display','list-item'); }
      offset_lmenu = scroll_top - lmenu_top;
      if (offset_lmenu < 0) {
        offset_lmenu = 0;
        $('#scroll_on_top').css('display','none');
      }
      $('#lmenu').animate({top:lmenu_top+offset_lmenu},{duration:300,queue:false});
    }
  });
});
function scrollit () {
  for (i=scroll_top; i>200; i=i-200) { self.scroll(1,i) }
  self.scroll(1,0)
}
</script>

Сайт, для которого всё это делалось, сгорел в атмосфере, потому рабочий пример сейчас я вам даже не покажу. 🙂

Запись опубликована 12 декабря 2009 года. Пост окончен, но в рубрике «Web-кодинг» есть не менее интересные посты:

Подписка на RSS канал блога RSS подписка (как это?) поможет вам не пропустить ничего интересного на этом блоге.