Javascript-форум (https://javascript.ru/forum/)
-   Ваши сайты и скрипты (https://javascript.ru/forum/project/)
-   -   Бесконечноуровневое меню на CSS (https://javascript.ru/forum/project/52792-beskonechnourovnevoe-menyu-na-css.html)

ruslan_mart 07.01.2015 12:21

Бесконечноуровневое меню на CSS
 
В общем, дело было вечером... делать было нечего. Решил сделать простенькое меню с CSS3 эффектами.

Надеюсь, кому-нибудь пригодится. :)

Вот: http://learn.javascript.ru/play/80LxIb

<!DOCTYPE HTML>
<html>
  <head>
    <title>Многоуровневое/бесконечоуровневое меню на CSS (by Ruslan_xDD aka Black Shadow)</title>
    <style type="text/css">
      .menu {
          background: #252525;
          color: #AAA;
          font-family: verdana, arial, helvetica;
          font-size: 9pt;
          height: 30px;
          line-height: 30px;
      }
      .menu a {
          color: inherit;
          text-decoration: none;
      }
      .menu div {
          cursor: pointer;
          display: inline-block;
          padding: 0 15px;
      }
      .menu div, .menu li, .menu li.menu-sub:after, .menu ul {
          -webkit-transition: all 0.3s;
          -moz-transition: all 0.3s;
          -ms-transition: all 0.3s;
          -o-transition: all 0.3s;
          transition: all 0.3s;
      }
      .menu div:hover {
          background: #333;
          color: #DAAB5A;
          position: relative;
          text-shadow: 0 0 8px #FB954B;
      }
      .menu div:hover > ul, .menu li:hover > ul {
          opacity: 0.9;
          visibility: visible;
      }
      .menu li {
          padding: 0 15px;
      }
      .menu li:hover, .menu li.menu-selected {
          background: #222;
          color: #DAAB5A;
      }
      .menu li ul {
          left: 100%;
          margin: -30px 0 0;
      }
      .menu li.menu-group {
          border-top: 1px dashed #888;
          margin-top: 5px;
      }
      .menu li.menu-sub { /*Or CSS4 selector: .menu $li ul:after*/
          padding-right: 25px;
      }
      .menu li.menu-sub:after {
          border: 6px solid transparent;
          border-left-color: #888;
          content: '';
          margin-top: 8px;
          position: absolute;
          right: 0;
      }
      .menu li.menu-sub:hover:after {
          border-left-color: #DAAB5A;
      }
      .menu ul {
          background: #333;
          color: #BBB;
          list-style: none;
          margin: 0 0 0 -15px;
          opacity: 0;
          padding: 0;
          position: absolute;
          text-shadow: none;
          visibility: hidden;
          white-space: nowrap;
      }
    </style>
  </head>
  
  <body>
    <div class="menu">
      <div>Меню 1
        <ul>
          <li><a href="#">Меню 1.1</a></li>
          <li><a href="#">Меню 1.2</a></li>
          <li class="menu-sub">
            <a href="#">Меню 1.3</a>
            <ul>
              <li><a href="#">Меню 1.3.1</a></li>
              <li><a href="#">Меню 1.3.2</a></li>
              <li class="menu-sub">
                <a href="#">Меню 1.3.3</a>
                <ul>
                  <li><a href="#">Меню 1.3.3.1</a></li>
                  <li><a href="#">Меню 1.3.3.2</a></li>
                  <li class="menu-sub">
                    <a href="#">Меню 1.3.3.3</a>
                  	<ul>
                      <li><a href="#">Меню 1.3.3.3.1</a></li>
                      <li><a href="#">Меню 1.3.3.3.2</a></li>
                      <li><a href="#">Меню 1.3.3.3.3</a></li>
                    </ul>
                  </li>
                </ul>
              </li>
            </ul>
          </li>
        </ul>
      </div>
      <div>Меню 2
        <ul>
          <li><a href="#">Меню 2.1</a></li>
          <li class="menu-sub">
            <a href="#">Меню 2.2</a>
            <ul>
              <li><a href="#">Меню 2.2.1</a></li>
              <li><a href="#">Меню 2.2.2</a></li>
              <li><a href="#">Меню 2.2.3</a></li>
              <li><a href="#">Меню 2.2.4</a></li>
              <li><a href="#">Меню 2.2.5</a></li>
            </ul>
          </li>
          <li class="menu-sub">
            <a href="#">Меню 2.3</a>
            <ul>
              <li><a href="#">Меню 2.3.1</a></li>
              <li><a href="#">Меню 2.3.2</a></li>
              <li><a href="#">Меню 2.3.3</a></li>
              <li><a href="#">Меню 2.3.4</a></li>
              <li><a href="#">Меню 2.3.5</a></li>
            </ul>
          </li>
        </ul>
      </div>
      <div>Меню 3
        <!--Меню без ссылок-->
        <ul>
          <li>Меню 3.1</li>
          <li>Меню 3.2</li>
          <li>Меню 3.3</li>
          <li>Меню 3.4</li>
          <li onclick="alert('Hello world!')">Меню 3.5</li>
        </ul>
      </div>
      <div>Меню 4
        <ul>
          <li><a href="#">Меню 4.1</a></li>
          <li><a href="#">Меню 4.2</a></li>
          <li class="menu-group"><a href="#">Меню 4.3</a></li>
          <li><a href="#">Меню 4.4</a></li>
          <li class="menu-sub">
            <a href="#">Меню 4.5</a>
          	<ul>
              <li><a href="#">Меню 4.5.1</a></li>
              <li><a href="#">Меню 4.5.2</a></li>
              <li><a href="#">Меню 4.5.3</a></li>
            </ul>
          </li>
        </ul>
      </div>
      <div>Меню 5
        <ul>
          <li><a href="#">Меню 5.1</a></li>
          <li><a href="#">Меню 5.2</a></li>
          <li class="menu-selected"><a href="#">Меню 5.3</a></li>
        </ul>
      </div>
    </div>
  </body>
</html>


UPDATE 1.1:
Добавлена «стрелочка».
Чтобы в пункте меню показывалась «стрелочка» - необходимо для li этого пункта добавить класс: «menu-sub».
Для автоматической расстановки «стрелочек» используйте этот JavaScript код:
window.addEventListener('DOMContentLoaded', function() {
    [].forEach.call(document.querySelectorAll('.menu li > ul'), function(self) {
        self.parentNode.classList.add('menu-sub');
    });
}, false);


UPDATE 1.2:
Добавлена возможность для группировки элементов меню - это позволит отделить важные части элементов меню от других, маловажных элементов. Для группировки следует использовать класс «menu-group» для li элемента (см. основной пример выше > «Меню 4.3»).
Добавлена возможность пометки «активного элемента меню» с помощью класса «menu-selected», который необходимо применять li элементу нужно пункта (см. основной пример выше > «Меню 5.3»).
Для автоматического выделения «активного элемента меню» (ссылка в меню, которая соответствует текущей ссылке документа), используйте этот JavaScript код:
window.addEventListener('DOMContentLoaded', function() {
    var i, href = this.location.pathname,
        menuItems = document.querySelectorAll('.menu li > a');
    for(i=0; i<menuItems.length; i++) {
        if(menuItems[i].pathname == href) {
            menuItems[i].parentNode.classList.add('menu-selected');
            break;
        }
    }
});

Но если нужно ещё выделить всех родителей «активного элемента меню», то в это случае поможет следующий JavaScript код:
window.addEventListener('DOMContentLoaded', function() {
    var i, href = this.location.pathname,
        menuItems = document.querySelectorAll('.menu li > a'),
        menuSelected = function(self) {
            while(!self.parentNode.classList.contains('menu')) {
                if(self.tagName == 'LI') self.classList.add('menu-selected');
                self = self.parentNode;
            }
        };
    for(i=0; i<menuItems.length; i++) {
        if(menuItems[i].pathname == href) {
            menuSelected(menuItems[i].parentNode);
            break;
        }
    }
});



Tags: скрипт меню для сайта, меню на JavaScript, меню на CSS, многоуровневое меню, выпадающее меню

ruslan_mart 07.01.2015 16:42

Обновил скрипт. Добавил возможность указывать стрелочку на пункты меню с дочерним меню. Но так как обратиться к родителю можно только в CSS4 (он пока не поддерживается), поэтому, придётся вручную добавлять класс "menu-sub" на li с дочерним меню, иначе стрелочка отображаться не будет.

Но если хочется, чтобы класс добавлялся сам, то можно решить это с помощью JavaScript кода:

window.addEventListener('DOMContentLoaded', function() {
    [].forEach.call(document.querySelectorAll('.menu li > ul'), function(self) {
        self.parentNode.classList.add('menu-sub');
    });
}, false);


Скрипт в действии: http://learn.javascript.ru/play/RrSxf

Aetae 07.01.2015 20:13

Ruslan_xDD, на css стрелочку можно прифигачить с помощью
.menu a:not(:only-child)
или поиграть с first-child. Варианты есть всегда.)

ruslan_mart 07.01.2015 20:36

Aetae, ок, завтра что-нибудь по эксперементирую. :)

ruslan_mart 08.01.2015 07:41

UPDATE 1.2
См. первый пост.

Kiano 12.01.2015 20:59

Ruslan_xDD, спасибо!Очень полезно!


Часовой пояс GMT +3, время: 10:32.