Элементы плавной навигации различной ширины с равноудаленным интервалом

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

Я имел ограниченный успех, используя такие методы, как:

ul {display: table;width: 100%;}
li {display: table-cell;}
a {display: block;} 

а также используя

ul {text-align: justify}
li {inline-block }

но ни один из написанных мною кодов не справляется с элементами различной ширины. Интервал, кажется, не остается равным, поскольку размер nav изменен.

Мне нужно, чтобы навигация была плавной, первый и последний элементы должны находиться на одном уровне с краем содержащего ul, а элементы должны быть равноудалены друг от друга

2 ответа

Решение

Некоторое время я думал об этом и придумал два разумных подхода, оба из которых довольно хороши, но не совсем идеальны по пикселям. Один из них основан только на CSS, а второй - на jQuery (JavaScript).

Подход CSS - довольно хорошее приближение

Рассмотрим следующий HTML:

<ul class="nav ex1">
    <li class="first"><a href="#">Home</a></li>
    <li><a href="#">Collections</a></li>
    <li class="tight"><a href="#">About Us</a></li>
    <li><a href="#">Slocklists</a></li>
    <li class="tight"><a href="#">Trade Enquiries</a></li>
    <li><a href="#">Press</a></li>
    <li class="last"><a href="#">Contact Us</a></li>
</ul>

Я добавил несколько классов в качестве хуков для стиля.

CSS выглядит следующим образом:

.nav.ex1 {
    outline: 1px dashed blue;
    width: 100%;
    margin: 0;
    padding: 0;
    display: table;
}
.nav.ex1 li {
    display: table-cell;
    outline: 1px dotted gray;
    width: 20%;
    white-space: pre;
    text-align: center;
}
.nav.ex1 li.first {
    width: 1%;
}
.nav.ex1 li.last {
    width: 1%;
}
.nav.ex1 li.tight {
    width: 1%;
}

В примере 1 ul.nav родительский контейнер использует display: table а также width: 100%, Ребенок li элементы table-cell"S. я добавил white-space: pre чтобы некоторые ссылки не были разделены на две строки, и text-align: center держать текст по центру.

Хитрость заключается в том, чтобы заставить некоторые ячейки таблицы сжиматься, чтобы соответствовать тексту, и вы можете сделать это, установив width: 1% который ненулевой, но слишком маленький, чтобы вместить текст (если ваш экран не имеет ширину 10000 пикселей). Я сжимаю, чтобы соответствовать первой и последней ячейкам, что заставляет их выравниваться по левому и правому краям родительского контейнера. Затем я заставляю каждую другую ячейку таблицы сжиматься до нужного размера, добавляя .tight учебный класс.

Ячейки оставшейся таблицы будут иметь ширину 20%, что позволит равномерно распределять их между двумя ближайшими соседями. ОДНАКО, будут некоторые небольшие различия в расстоянии между ссылками в строке, поэтому я и называю это приближением.

JQuery Aided Solution

В Примере 2 разметка по существу такая же, а CSS:

.nav.ex2 {
    outline: 1px dashed blue;;
    margin: 0;
    padding: 0;
    display: block;
    overflow: auto;
    width: 100%;
}
.nav.ex2 li {
    float: left;
    display: block;
    outline: 1px dotted gray;
    width: auto;
}

В этом случае li элементы плавают влево и я использую width: auto,

Хитрость заключается в том, чтобы вычислить магическое значение левого поля и применить его ко всем li элементы, кроме первого.

Действие jQuery:

$(window).resize(function () {
    navResizer();
});

// On load, initially, make sure to set the size.
navResizer();

function navResizer() {
    var $li_w = 0;
    var $ul_w = $(".nav.ex2").innerWidth();

    $( ".nav.ex2 li" ).each(function( index ) {
        $li_w += $(this).innerWidth();
    });

    var li_margin = Math.floor(($ul_w-$li_w)/6);
    $(".nav.ex2 li").not(".first").css("margin-left",li_margin);
    $("p.note").text( "Widths: ul.nav: " + $ul_w + " all li: " + $li_w + " Left margin: " + li_margin);
}

По сути, действие вычисляет ширину ul.nav ($ul_w), а общая ширина всех li дочерние элементы ($li_w).

Левое поле рассчитывается по ($ul_w - $li_w)/6 где 6 - количество пробелов между 7 ссылками.

Ключевая строка кода: $(". Nav.ex2 li"). Not(". First"). Css("margin-left",li_margin);

я использую .not(".first") опустить первый li элемент, а затем .css установить левое поле.

Единственный небольшой дефект находится в крайнем правом углу, где ссылка не совсем правильно выровнена, но вы можете исправить это, добавив последний li направо.

По большей части, если бы ваши тексты ссылок были одинаковыми по длине, вам было бы трудно различить их. Оба подхода не совсем идеальны, но довольно хороши.

Скрипка: http://jsfiddle.net/audetwebdesign/xhSfs/

сноска
Я попробовал некоторые другие подходы, используя text-align: justify а также inline-block, но движок CSS не рассматривает встроенные блоки как обычные слова, поэтому не будет оправдывать строку встроенных блоков.

настройка left-margin Значение% не будет работать при некоторых значениях ширины окна, и крайняя правая ссылка не будет на краю, как хотелось бы.

Подход jQuery был опробован ранее, см.:
Равномерно расположенные навигационные ссылки, занимающие всю ширину ul в CSS3

Ты можешь использовать text-align: justify; и проигнорируйте последний выравниваемый по левому краю ряд. #last невидим и занимает последний ряд из-за padding-left: 100%;: http://jsfiddle.net/mwRbn/

если вы хотите выровнять текст меню по вертикали, используйте height в комбинации с line-height:

ul#nav { 
  text-align: justify;
  width: 100%;
  background: yellow;
  height: 2em;
  line-height: 2em;
}

http://jsfiddle.net/mwRbn/1/. Вам нужен взлом IE<8?

Другие вопросы по тегам