/ Scripts & jquery / Добавление кнопки more при узком меню

Добавление кнопки more при узком меню

21.03.2023

514

Если пункты меню не вмещаются в его заданную ширину, то их можно спрятать в кнопку more.

Вариант 1

Работает в целом неплохо. Но если именно придираться, то при изменении размера окна до первоначального, не все пункты возвращаются на место. Но плюсом этого варианта является отсутствие привязки к ширине пунктов меню.

Верстка

<div class="twelve columns filter-wrapper">
    <ul class="nav-bar-filter" id="nav-bar-filter">
        <li><a href="#">All</a></li>
        <li><a href="#">Small</a></li>
        <li><a href="#">Medium</a></li>
        <li><a href="#">Extra large</a></li>
        <li><a href="#">Text</a></li>
        <li><a href="#">Small-1</a></li>
        <li><a href="#">Medium-1</a></li>
        <li><a href="#">Extra large text</a></li>
        <li><a href="#">Large text</a></li>
        <li><a href="#">Another text</a></li>
        <li><a href="#">text</a></li>
    </ul>
    <ul id="more-nav">
        <li><b><a href="#">More &gt;</a></b>
            <ul class="subfilter"></ul>
        </li>
    </ul>
</div>

Стили

ul#more-nav, ul#nav-bar-filter {
    display: inline-block;
    vertical-align: top;
}
ul {
    list-style-type: none;
    padding: 0;
    margin: 0;
}
li {
    padding: 4px 8px 4px 8px;
    margin: 0;
}
#nav-bar-filter li {
    display: inline-block;
    font-weight: bold;
}
a {
    text-decoration: none;
    color: #666;
    font-size: 13px;
}
.filter-wrapper {
    width: 100%;
    background: #eee;
    padding: 5px 10px 5px 10px;
}
#more-nav {
    float: right;
}
.subfilter{
    padding-top: 10px;
	position: absolute;
}
.subfilter li {
    margin: 0 0 0 20px;
    padding: 5px 0 0 0;
}

Скрипт

jQuery(document).ready(function ($) {
    var menu = $("#nav-bar-filter"),
        subMenu = $(".subfilter"),
        more = $("#more-nav"),
        parent = $(".filter-wrapper"),
        ww = $(window).width(),
        smw = more.outerWidth();

    menu.children("li").each(function () {
        var w = $(this).outerWidth();
        if (w > smw) smw = w + 20;
        return smw
    });
    more.css('width', smw);

    function contract() {
        var w = 0,
            outerWidth = parent.width() - smw - 50;
        for (i = 0; i < menu.children("li").size(); i++) {
            w += menu.children("li").eq(i).outerWidth();
            if (w > outerWidth) {
                menu.children("li").eq(i - 1).nextAll()
                    .detach()
                    .css('opacity', 0)
                    .prependTo(".subfilter")
                    .stop().animate({
                    'opacity': 1
                }, 300);
                break;
            }
        }
    }

    function expand() {
        var w = 0,
            outerWidth = parent.width() - smw - 20;
        menu.children("li").each(function () {
            w += $(this).outerWidth();
            return w;
        });
        for (i = 0; i < subMenu.children("li").size(); i++) {
            w += subMenu.children("li").eq(i).outerWidth();
            if (w > outerWidth) {
                var a = 0;
                while (a < i) {
                    subMenu.children("li").eq(a)
                        .css('opacity', 0)
                        .detach()
                        .appendTo("#nav-bar-filter")
                        .stop().animate({
                        'opacity': 1
                    }, 300);
                    a++;
                }
                break;
            }
        }
    }
    contract();

    $(window).on("resize", function (e) {
        ($(window).width() > ww) ? expand() : contract();
        ww = $(window).width();
    });

});

Вариант 2

В данном варианте идет привязка к ширине пунктов меню (в примере 120px). Но работает решение более стабильно.

Верстка

<div class="responsive-menu">
    <ul id="menu">
        <li>Option One</li>
        <li>Option Two</li>
        <li>Option Three</li>
        <li>Option Four</li>
        <li>Option Five</li>
        <li>Option Six</li>
    </ul>
    <ol>
        <li>
            More
            <ul id="submenu"></ul>
        </li>
    </ol>
</div>

Стили

.responsive-menu {
    position: relative;
    background-color: #ccc;
    height: 32px; overflow: visible;
}
.responsive-menu ul#menu, ol {
    height: 32px; max-width: 80%;
    overflow: hidden;
}
.responsive-menu ul#menu > li, ol > li {
    display: block; float: left; 
    height: 32px; width: 120px;
    padding: 4px 8px;
	white-space: nowrap;
}
.responsive-menu ol {
    position: absolute;
    right: 0; top: 0;
    overflow: visible;
}
.responsive-menu ol > li { min-width: 120px; }

.responsive-menu ol ul {
    position: absolute;
    top: 100%;
    right: 0;
}

.responsive-menu ol li ul > li {
    list-style: none; 
    background-color: #f7f7f7;
    border: 1px solid #eee;
    padding: 4px 8px;
}

Скрипт

var elemWidth, fitCount, fixedWidth = 120,  
    $menu = jQuery("ul#menu"), $collectedSet;

collect();
jQuery(window).resize(collect);

function collect() {
    elemWidth = $menu.width();
    fitCount = Math.floor(elemWidth / fixedWidth) - 1;
    $collectedSet = $menu.children(":gt(" + fitCount + ")");
    jQuery("#submenu").empty().append($collectedSet.clone());    
}

Можно добавить условие чтобы пункт More исчезал если в нем нет спрятанных пунктов. Для этого в функцию collect() нужно добавить условие:

if( jQuery('#submenu').is(':empty') ) {
	jQuery(".responsive-menu ol").hide();
} else {
	jQuery(".responsive-menu ol").show();
}

Вариант 3

Это комплексное решение по добавлению кнопки more, а также адаптация под мобильную версию (с реализацией подпунктов меню).

Верстка меню wordpress

<div id="top_menu">
	<nav id="top_menu_main">
	
		<div id="flvmenu">
			<?php wp_nav_menu( [
				'theme_location'  => 'header-menu',
				'container'       => ''
			] ); ?>			
		</div>
		<div class="menu-clear-left"></div>
		
	</nav>
</div>

Стили

#flvmenu {
    display: block;
    margin: 0 auto;
    max-width: 1130px;
    position: relative;
}

#flvmenu > ul > li > a, #flvmenu > ul > li > ul > li > a, #flvmenu > ul > li > ul > li > ul > li > a, #flvmenu > ul > li > ul > li > ul > li > ul > li > a {
    text-decoration: none;
    display: block;
    cursor: pointer;
}

#flvmenu > ul > li {
    display: inline-block;
    position: relative;
    margin-right: -4px;
}

#flvmenu > ul > li > ul {
    display: none;
    position: absolute;
    top: 100%;
    z-index: 1000;
}

#flvmenu > ul > li > ul > li > ul {
    display: none;
    position: absolute;
    top: 0;
    left: 100%;
    z-index: 1000;
}

#flvmenu > ul > li:last-child > ul > li > ul {
    display: none;
    position: absolute;
    top: 0;
    left: -100%;
    z-index: 1000;
}

#flvmenu > ul > li:last-child > ul > li > ul > li > ul {
    display: none;
    position: absolute;
    top: 0;
    left: -100%;
    z-index: 1001;
}

#flvmenu > ul > li ul li {
    display: block;
    position: relative;
}

#flvmenu > ul > li:hover > ul {
    display: block;
}

#flvmenu > ul > li > ul > li:hover > ul {
    display: block;
}

#flvmenu > ul > li > ul > li > ul > li:hover > ul {
    display: block;
}

#flvmenu > ul > #fllast {
    display: none;
    font-weight: 500;
}

.minmenu {
    display: none;
}

#flvmenu > ul > li ul li {
    width: 210px;
}

#flvmenu > ul > li > .flarr {
    top: 16px;
    right: 0px;
}

#flvmenu > ul > li ul li .flarr {
    top: 8px;
    right: 0px;
}

#flvmenu > ul > li .flarr {
    padding: 0;
}

#flvmenu > ul > li > a.flarr:after {
    content: "\f107";
    font-family: FontAwesome;
    display: inline-block;
    margin-left: -24px;
    margin-right: 10px;
}

#flvmenu > ul > li ul li a.flarr:after {
    content: "\f105";
    font-family: FontAwesome;
    position: absolute;
    display: inline-block;
    top: 15px;
    right: 15px;
}

#flvmenu > ul > li ul li:hover a.flarr {
    color: #fff;
}

#flvmenu > ul > li ul li:hover>a {
    color: #fff;
}

#flvmenu > ul > li ul li.root-item-selected>a {
    color: #fff;
}

@media (max-width: 768px) {
    .minmenu {
        display: block;
        cursor: pointer;
    }

    .minmenu i {
        padding-left: 25px;
        line-height: 45px;
        font-size: 24px;
        color: #fff;
    }

    .minmenu a {
        padding-left: 10px;
        padding-right: 10px;
        line-height: 45px;
        font-size: 20px;
        color: #fff;
    }

    #flvmenu > ul {
        position: relative;
        left: 0;
        top: 100%;
        z-index: 999;
    }

    #flvmenu > ul li {
        width: 100%;
    }

    #flvmenu > ul > li > ul, #flvmenu > ul > li > ul > li > ul {
        display: block;
        position: relative;
        overflow-y: hidden;
        width: auto;
        left: 0;
    }

    #flvmenu > ul > li > ul > li, #flvmenu > ul > li > ul > li > ul > li {
        width: auto;
    }

    #flvmenu > ul {
        background-color: #48a216;
        width: 100%;
    }

    #flvmenu > ul li ul {
        background-color: #48a216;
    }

    #flvmenu > ul li a {
        color: #fff !important;
        display: block;
    }

    #flvmenu > ul > li {
        display: block;
    }

    #flvmenu > ul > li > ul > li a {
        padding-left: 40px;
    }

    #flvmenu > ul > li > ul > li > ul > li a {
        padding-left: 35px;
    }

    #flvmenu > ul > li > a.flarr:after, #flvmenu > ul > li ul li a.flarr:after {
        content: "";
    }

    #flvmenu > ul > li .flarr, #flvmenu > ul > li ul li a.flarr {
        position: absolute;
        top: 0;
        padding: 15px;
    }
}

div.menu-clear-left {
    clear: left;
}
оптимизировать эти стили

Скрипт

var minwidth = 769,
    flgmini = !1;

function CheckLis() {
    var l,
        e,
        i,
        t = 0,
        u = window.innerWidth;
    if (u > minwidth) {
        e = jQuery("#fllast").width();
        var s = jQuery("#fllast > ul > li").length;
        for (
            0 == s && (e = 0),
                l = jQuery("#flvmenu").width(),
                jQuery("#flvmenu > ul > li").last().before(jQuery("#fllast > ul > li")),
                jQuery("#flvmenu > ul > li:not(#fllast)").each(function () {
                    t += this.clientWidth;
                }),
                i = jQuery("#flvmenu > ul > li:not(#fllast)"),
                1 == s && t <= l && (e = 0);
            t + e > l;

        )
            (t -= i.last().width()), i.last().prependTo("#fllast > ul"), i.splice(-1, 1), 0 == s && (e = jQuery("#fllast").width());
        jQuery("#fllast").css("display", "none"),
            jQuery("#fllast > ul > li").length > 0 && jQuery("#fllast").css("display", "inline-block"),
            jQuery(".flarr").html(""),
            jQuery("#flvmenu > ul > li ul").css("height", "auto"),
            jQuery("#flvmenu > ul").css("display", "block"),
            SetAlignBl(u),
            flgmini && ((flgmini = !1), CheckLis());
    } else
        flgmini ||
            (jQuery("#flvmenu > ul > li").last().before(jQuery("#fllast > ul > li")),
            jQuery("#fllast").css("display", "none"),
            jQuery("#flvmenu > ul > li ul").css("height", "0").css("right", "auto").css("left", "auto"),
            jQuery(".flarr").html("<i class='fa fa-plus'></i>"),
            jQuery("#flvmenu > ul").css("display", "none"),
            (flgmini = !0));
}

function Setmini() {
    jQuery(".flarr").click(function () {
        var l = document.documentElement.clientWidth;
        if (minwidth > l) {
            var e = this.parentElement.getElementsByTagName("ul")[0];
            "0px" == e.style.height ? (jQuery(this).html("<i class='fa fa-minus'></i>"), (e.style.height = "auto")) : (jQuery(this).html("<i class='fa fa-plus'></i>"), (e.style.height = "0px"));
        }
    }),
        jQuery(".minmenu").click(function () {
            "block" == jQuery("#flvmenu > ul").css("display") ? jQuery("#flvmenu > ul").css("display", "none") : jQuery("#flvmenu > ul").css("display", "block");
        });
}

function SetAlignBl(l) {
    jQuery("#flvmenu > ul > li > ul").each(function () {
        jQuery(this).css("left", "0"), jQuery(this).css("right", "auto");
        var e = this.firstElementChild,
            i = 0;
        null != e && (i = jQuery(e).width()), getLeftSet(this) + i > l && (jQuery(this).css("left", "auto"), jQuery(this).css("right", "0"));
    }),
        jQuery("#flvmenu > ul > li > ul > li > ul").each(function () {
            jQuery(this).css("left", "100%"), jQuery(this).css("right", "auto");
            var e = this.firstElementChild,
                i = 0;
            null != e && (i = jQuery(e).width()), getLeftSet(this) + jQuery(this.parentElement).width() + i > l && jQuery(this).css("left", "-100%");
        });
}

function getLeftSet(l) {
    for (var e = 0; l; ) (e += parseFloat(l.offsetLeft)), (l = l.parentElement);
    return Math.round(e);
}

(window.onresize = CheckLis),
jQuery(document).ready(function () {
        jQuery("#flvmenu > ul").append("<li id='fllast'><a>. . .</a><ul></ul></li>"),
            jQuery("#flvmenu").prepend("<div class='minmenu'><i class='fa fa-bars'></i><a>&#1052;&#1045;&#1053;&#1070;</a></div>"),
            jQuery("#flvmenu > ul li ul").before("<a class='flarr'></a>"),
            CheckLis(),
            Setmini();
});

Поделиться в соц. сетях:

  • Похожие записи
  • Комментарии
  • Вложения
Вертикальное многоуровневое меню

Вертикальное многоуровневое меню

Создадим вертикальное многоуровневое меню. За основу берем верстку стандартного меню WordPress. Условно у меню будет id menu. Стили:

Шапка при прокрутке вверх

Шапка при прокрутке вверх

Делаем шапку, которая скрывается при прокрутке вниз и появляется при прокрутке вверх. Верстка и стили header нужно добавить class=»nav-down». Особенность стилей в том, что header должен быть fixed, a body Читать далее »

Манипуляции с меню

Манипуляции с меню

Проводим различные эксперименты и манипуляции с меню. Добавить пункт функцией Добавляем произвольный пункт меню при помощи функции (!данный пример будет работать только с установленным плагином woocommerce) В данном случае добавляется Читать далее »

Добавить комментарий

Пока нет комментариев. Будь первым!

Добавление кнопки more при узком меню
Вкладка видеообзор
Рекомендации для васВкладка видеообзорOpttour.ru
Спасибо! Наш менеджер свяжется с Вами в течении 5 минут.