Небольшой пример демонстрирующий эффект сворачивания однотипных блоков (например постов в блоге или виджетов в сайдбаре) с помощью jQuery.

HTML

<div class="post">
    <div class="title">
        <h3><a href="" title="">Заголовок</a></h3>
        <p>Автор, 12.02.2010</p>
    </div>
    <div class="entry">
        <!-- Контент -->
    </div>
</div>
 
<div class="post">
    <div class="title">
        <h3><a href="" title="">Заголовок</a></h3>
        <p>Автор, 12.02.2010</p>
    </div>
    <div class="entry">
        <!-- Контент -->
    </div>
</div>
 
…

В данном примере присутствуют несколько постов. Скрываться будет их контентная часть.

CSS

.post {
    padding:10px 20px;
    position:relative;
    background:#eee;
    margin-bottom:20px
}
.inactive {
    color:#bbb
}
.post .title {
    position:relative;
    height:1%
}
.post .title h3 {
    font-size:1.4em
}
.post .title h3 a {
    text-decoration:none;
    color:#000
}
.inactive .title h3 a {
    color:#bbb
}
.post .title p {
    font-size:0.7em;
    font-style:italic;
    font-weight:bold;
    margin:0
}
.post .title span {
    position:absolute;
    right:0;
    top:30%;
    cursor:pointer;
    width:14px;
    height:14px;
    background:url(trigger.gif) no-repeat left bottom;
    display:block;
    font-size:0
}
#content .inactive .title span {
    background-position:left top
}
#content .post .entry {
    padding:10px 0
}

Span будет служить переключателем для сворачивания и разворачивания блоков и будет добавлен с помощью javascript. Поэтому пользователи с отключенным javascript не увидят ничего не делающий элемент.

Javascript

$('.title').append('<span></span>');
$('.post span').each(function() {
   var trigger = $(this), state = false, el = trigger.parent().next('.entry');
   trigger.click(function(){
      state = !state;
      el.slideToggle();
      trigger.parent().parent().toggleClass('inactive');
   });
});

54 комментария к статье «jQuery: Сворачиваемые блоки»:

  1. Интересно. Сохранил в закладках. Как раз хотел подобное в админке сделать на одном проекте.

  2. Владимир:

    Спасибо за код. Какраз ищу что-то похожее для нового сайта. Аккордеон там не подходит ибо нужна возможность открывать несколько блоков одновременно.

    Вопрос. Кто-то может пояснить эту строчку:
    var trigger = $(this), state = false, el = trigger.parent().next(‘.entry’);

  3. ApxuMeD:

    А как сделать, чтобы блоки были изначально закрыты?

  4. роман:

    если свернуть 2 и более блоков, потом нажать развернуть, разворачиваются все!, это можно исправить?

    • Alex:

      Что-то я подобного поведения не заметил. В каком это браузере?

    • Владимир:

      Хром 5.0.307.7 полет нормальный.
      Под «разворачивается все» возможно имеется ввиду не работа скрипта, а перегрузка страницы – в начальном варианте все блоки какраз развернуты

      • Имелось ввиду не клик по плюсику, а:

        Заходим в пример, сворачиваем первый и второй блок, нажимаем на заголовок первого – разворачиваются оба – сделать разворот блока при клике на заголовок.

        При клике на плюсик – все работает как надо: разворачивается именно тот блок.

        • Alex:

          В заголовках ссылки просто для примера. Они ссылаются на эту же страницу и соответственно всё приходит в изначальный вид. В реальной ситуации каждая ссылка вела бы на соответствующий пост.

  5. роман:

    да действительно, опера все нормально, «недостаток» наблюдал через IE8

  6. ApxuMeD:

    протестил в ИЕ8, все ок

  7. красиво написан код, спасибо

  8. Владимир:

    Вынес сворачивание в отдельную функцию:

    function toggleBlock(el){
    el.slideToggle();
    el.parent().toggleClass('inactive');
    }

    Теперь можно использовать так:

    $(document).ready(function() {
    $('.title').append('');
    $('.post span').each(function() {
    var trigger = $(this);
    var el = trigger.parent().next('.entry');
    var title = trigger.parent().find('h3');
    //Клик по плюсу
    trigger.click(function(){
    toggleBlock(el);
    });
    //Клик по заголовку
    title.click(function(){
    toggleBlock(el);
    return false;
    });
    });
    //Свернуть первый блок
    toggleBlock($('.entry').eq(0));
    });

  9. asse:

    а можно сделать, чтобы позиция свернутый/развернутый блок запоминалась в кеше браузера или еще где-то.. чтобы при обновлении страницы или повторном посещении сайта, свернутые блоки оставались такими же свернутыми?

  10. asse, плагин jquery.cookie вам поможет

  11. asse:

    кто-нибудь может приветси код, как правильно внедрить этот плагин jquery.cookie в данный скрипт? заранее спасибо большое!

  12. Классный скрипт, будет эму применение !
    Спс !

  13. Спасибо за скрипт! радует, что прост в установке :) приткнул в один свой проектик :)

  14. Спасибо за отличную ссылку. Сильно не хватает «Свернуть/развернуть все».

  15. pder:

    даже в IE все нормально. Огромное спасибо, ретвитнул!!

  16. А как куки прикрутить? Просто я немного по другому это сделал с куками, но в IE не пашет((

  17. Вроде как что-то с ссылкой http://www.box.net/shared/3vybmba1xn ? Странно, но у меня она не показывается. Говорит 503 – в чем проблема?

  18. добрый день!
    использовал данный код на одном из своих сайтов. вставил все как описано, в итоге получился один неприятный глюк. при развороте блока в FF низ блока подпрыгивает после разворота, а в ИЕ подпрыгивает блок при сворачивании (становится ближе к вышестоящему). в Сафари и Хром все нормально вроде (по крайней мере визуально этих подпрыгиваний не видно). с чем это может быть связано, не подскажете?

  19. 2007:

    Доброго времени суток.
    Покажите, пожалуйста, как прописать установки по-умолчанию. Я имею ввиду все открытые блоки, всё закрыть или какойто один раскрывать…
    Спасибо.

  20. Garry:

    А как добавить скрытие по клику не только на картинке справа, но и на заголовке записи? Чтобы клик на заголовке не вел на страницу записи, а сворачивал блок…

    • Alex:

      Попробуйте так:
      $('.title').append('');
      $('.post span, .post h3').each(function() {
      var trigger = $(this), state = false, el = trigger.parent().next('.entry');
      trigger.click(function(){
      state = !state;
      el.slideToggle();
      trigger.parent().parent().toggleClass('inactive');
      return false;
      });
      });

  21. Garry:

    Сейчас, например, плюс и минут сохранены в одной гифке. А если заменить их на какие-то другие, и не хочу сохранять в один файл, а например, использовать expand.png и collapse.png?

    • Alex:

      Всё оформление через css. Пропишите у селектора#content .inactive .title span другое фоновое изображение и всё.

  22. Спасибо за статью. Пригодилось.
    Но нужно еще реализовать возможность раскрытия блока по наведению мышкой на блок(hover). И сворачивание обратно. Делаю меню. Помогите пожалуйста, что в скрипте дописать…

  23. Как переместить «плюсик» влево ???

  24. #content .post .title span{position:absolute;left:0;top:30%;…}

Оставь комментарий: