jQuery как сделать, чтобы пункты меню заполнили все пространство по-ширине?

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

Создадим простое горизонтальное меню, без отступов между элементами.
Все отступы и ширину самих пунктов мы будем рассчитывать с помощью jQuery функции, которую напишем чуть позже, т.е. меню изначально выглядит так:
hor_menu 

Вот html код меню:

<div id="wrapper">
    <ul class="nav">
    	<li><a href="#">Пункт №1</a></li>
    	<li><a href="#">Пункт №2</a></li>
    	<li><a href="#">Пункт №3</a></li>
    	<li><a href="#">Пункт №4</a></li>
    	<li><a href="#">Пункт №5</a></li>
    	<li><a href="#">Пункт №6</a></li>
    </ul>
</div>

CSS стили демо примера:

#wrapper {
    overflow: hidden;
    width: 900px;
    padding: 50px 30px;
    margin: 100px auto;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.5);
    background: #369;
}

.nav {
    display: block;
    margin: 0; padding: 0;
    list-style-type: none;
}

.nav li {
    float: left;
}

.nav li a {
    display: block;
    padding: 5px 0;
    font-family: Arial, Verdana, sans-serif;
    color: #dedede;
    text-decoration: none;
}
.nav li a:hover {
    color: #FFF;
    text-shadow: 1px 1px 3px rgba(0,0,0,0.55);
}

Создание jQuery функции по равномерному распределению пунктов меню

Для того чтобы распределить пункты меню от края до края, необходимо знать некоторые входные параметры.
Основной параметр - это ширина меню. Этот параметр мы будем задавать в качестве аргумента для нашей функции.

Логика расчетов:

  1. Узнать суммарную ширину всех пунктов меню.
  2. Узнать насколько ширина меню больше чем суммарная ширина всех пунктов, назовем эту разнице дельта.
  3. Теперь дельту, нужно равномерно распределить между пунктами меню в качестве отступов (padding-left), при этом у первого пункта меню он будет равен нулю.

На первый взгляд все просто, но тут есть несколько подводных камней в этой задаче.
1. Нужно узнать актуальную (не округленную) ширину каждого пункта меню
actual_width 

Узнать реальную ширину с дробной частью, можно следующим образом:

$(this)[0].getBoundingClientRect().width

2. После того как мы узнаем реальную ширину элемента мы ее округлим и тоже самое сделаем с отступами между элементами, чтобы быть уверенными, что у нас будет одинаковое значение ширины элементов и их отступов во всех браузерах.

Вот так выглядит весь код jQuery функции без комментариев:

$(document).ready(function(){
    $.fn.fullWideMenu = function(width) {
        var $menu      = $(this),
            $menuItems = $('>li', $menu),
            qty        = $menuItems.length,
            itemWidth  = 0,
            mWidth     = 0,
            delta      = 0,
            decimal    = 0,
            floatPart  = 0;
        $menuItems.each(function(){
           itemWidth = Math.ceil( $(this)[0].getBoundingClientRect().width );
           console.log($(this)[0].getBoundingClientRect().width+"  =  "+itemWidth);
           $(this).width( itemWidth );
           mWidth += itemWidth;
        });
        delta = (width - mWidth)/(qty - 1);
        decimal = delta % 1;

        delta = Math.floor( delta );
        floatPart = Math.floor( decimal*(qty - 1) );

        $menuItems.css({paddingLeft: delta+'px'});
        $menuItems.first().css({paddingLeft: 0});
        $menuItems.last().css({paddingLeft: (delta + floatPart)+'px'});
    }
    $('.nav').fullWideMenu(900);
});

Вот этот же код, но с комментариями:

$(document).ready(function(){
    //функция имеет параметр width - ширина меню
    $.fn.fullWideMenu = function(width) {
        var $menu      = $(this),           //запишем элемент которому применена наша функция
            $menuItems = $('>li', $menu),   //элементы меню
            qty        = $menuItems.length, //кол-во элементов меню
            itemWidth  = 0, //ширина пункта меню
            mWidth     = 0, //ширина всех пунктов меню
            delta      = 0, //отступ между меню
            decimal    = 0, //дробная часть отступа
            floatPart  = 0; //суммарная дробная часть отступа между всеми пунктами, округленная к ближайшему меньшему целому значению
        
        //обходим каждый пункт меню
        $menuItems.each(function(){
           itemWidth = Math.ceil( $(this)[0].getBoundingClientRect().width ); //узнаем реальную ширину пункта и округляем ее к ближайшему большему целому числу
           
           $(this).width( itemWidth ); //задаем округленную ширину текущему пункту
           mWidth += itemWidth; //подсчитываем суммарную ширину всех пунктов
        });

        delta = (width - mWidth)/(qty - 1); //узнаем значение отступа между пунктами меню
        decimal = delta % 1; //берем дробную часть у отступа

        delta = Math.floor( delta ); //округляем отступ к ближайшему меньшему целому числу
        floatPart = Math.floor( decimal*(qty - 1) ); //суммарное округленное значение дробных частей отступа между пунктами

        $menuItems.css({paddingLeft: delta+'px'}); //всем пунктам меню задаем отступ слева
        $menuItems.first().css({paddingLeft: 0}); //у первого пункта убираем его, т.к. отступ должен быть только между пунктами меню
        $menuItems.last().css({paddingLeft: (delta + floatPart)+'px'}); //последнему пункту к отступу суммируем дробную часть всех отступов
    }

    //применяем функцию к нашему меню со значение ширины = 900 пикселов
    $('.nav').fullWideMenu(900);
});

Вот что у нас получилось в после применения функции:
full_width_menu 

 

Если у вас остались вопросы, пишите их в комментариях к посту 😉

(2 голосов. Рейтинг: 5,00 из 5)
Загрузка...

Рубрика: Как сделать?

Комментарии (4)

| RSS комментария

  1. Виктор:

    Зачем так усложнять жизнь?

    nav1
    nav2
    nav3
    nav4
    nav5

    #space-around{
    display: flex;
    justify-content: space-around;
    }

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