Отзывчивый разделитель для горизонтального списка

Этот вопрос расширяется с помощью Сепараторы для навигации, спрашивая, как можно удалить разделители при разрыве строк из-за размера видового экрана.

Широкий просмотр
->       Item 1 | Item 2 | Item 3 | Item 4 | Item 5       <-
Small Viewport
->  Item 1 | Item 2 | Item 3  <-
->      Item 4 | Item 5       <-

Вот скрипка, показывающая, как труба остается на разрыве линии:

Fiddle.

Меня интересует только css-решение, но javascript является приемлемым, если он предоставляет единственно возможное решение.

Ответ 1

Вы можете использовать тот факт, что конечное и конечное пробелы автоматически сбрасываются: https://jsfiddle.net/vnudrsh6/7/

nav {
  text-align: center;
  padding-right: 1em; /* = li::[email protected] */
}
ul {
  display: inline;
  margin: 0;
  padding: 0;
}
li {
  display: inline;
  /* white-space: nowrap should be moved to child A because IE fails to wrap resulting list completely */
}
li::before {
  content: ' ';
  /*
  this content is important only for Crome in case the HTML will be minified with no whitespaces between </li><li>
  */
}
li::after {
  content: ' ';
  white-space: normal;
  word-spacing: 1em; /* = [email protected]ght - this actually makes width */
  background-image: radial-gradient(circle, black, black 7%, transparent 15%, transparent 35%, black 45%, black 48%, transparent 55%);
  background-size: 1em 1em;
  background-repeat: no-repeat;
  background-position: center center;
  opacity: 0.5;
}
/*
no need to unset content of li:last-child, because it will be the trailing whitespace so it will collapse
*/
a {
  white-space: nowrap; /* here */
  display: inline-block; /* to allow padding */
  padding: 1em;
  text-decoration: none;
  color: black;
  transition-property: background-color;
  transition-duration: 500ms;
}
a:hover {
  background-color: #ccc;
}
<nav>
  <ul>
    <li><a href="#">Item 1</a></li><li><a href="#">Item 2</a></li><li><a href="#">Item 3</a></li><li><a href="#">Item 4</a></li><li><a href="#">Item 5</a></li><li><a href="#">Item 6</a></li><li><a href="#">Item 7</a></li><li><a href="#">Item 8</a></li><li><a href="#">Item 9</a></li><li><a href="#">Item 10</a></li><li><a href="#">Item 11</a></li><li><a href="#">Item 12</a></li><li><a href="#">Item 13</a></li><li><a href="#">Item 14</a></li><li><a href="#">Item 15</a></li><li><a href="#">Item 16</a></li><li><a href="#">Item 17</a></li><li><a href="#">Item 18</a></li><li><a href="#">Item 19</a></li><li><a href="#">Item 20</a></li>
  </ul>
</nav>
<p>(Content)</p>

Ответ 2

Другое решение из того же CSS: последний элемент в строке кажется, что он будет работать здесь.

HTML:

<div>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
</ul>
</div>

CSS

div {overflow: hidden; margin: 1em; }
div ul { list-style: none; padding: 0; margin-left: -4px; }
div ul li { display: inline; white-space: nowrap; }
div ul li:before { content: " | "; }

(Fiddle)

Ответ 3

Если у вас есть статическая ширина вашего элемента, вы можете вычислить на медиа-экране. Если не использовать script

body {
  text-align: center;
}

ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

li {
  display: inline-block;

  &:not(:last-child):after {
  content: ' |';  
  }
}
@media screen and (max-width: 265px) {
  li {
  display: inline-block;

  &:not(:last-child):after {
  content: '';  
  }
}

}

Ответ 4

Хороший вопрос. Для жизни меня я не могу думать о водонепроницаемом решении только для CSS, которого я боюсь...

Я изменил старое решение аналогичного вопроса, которое было опубликовано некоторое время назад: CSS: последний элемент в строке. Как ни странно, я искал решение другой проблемы, которую у меня было некоторое время назад, и наткнулся на нее - с тех пор был отмечен!

Здесь сценарий с моими обновлениями: https://jsfiddle.net/u2zyt3vw/1/

HTML:

<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li>Item 4</li>
  <li>Item 5</li>
</ul>

CSS

body {
  text-align: center;
}

ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

li {
  display: inline-block;

  &:not(:last-child):after {
    content: ' |'

  }

}
li.remove:after {
  content: none;
}

JQuery

$(window).on("resize", function () {
    var lastElement = false;
    $("ul > li").each(function() {
        if (lastElement && lastElement.offset().top != $(this).offset().top) {
            lastElement.addClass("remove");
        }
        lastElement = $(this);
    }).last().addClass("remove");
}).resize();

ПРИМЕЧАНИЕ. В настоящее время он работает лучше всего onload, изменение размера вызывает несколько проблем, даже если я использую toggleClass(). Поэтому продолжайте нажимать "Запуск" при каждом изменении размера представления. Я поработаю над этим и вернусь к вам.

Ответ 5

Моя реализация с JavaScript: https://jsfiddle.net/u2zyt3vw/5/

Нажмите "Выполнить" снова после изменения размера окна.

Вы также можете добавить прослушиватели событий, такие как onresize. Здесь JS:

var listItems = document.getElementsByTagName("li");
var listItemsWidth = [];
var listItemsDistance = [];

for (let i = 0; i < listItems.length; i++) {
  listItemsWidth[i] = listItems[i].offsetWidth;
  listItemsDistance[i] = listItems[i].getBoundingClientRect().right;
}

for (let i = 0; i < listItems.length; i++) {
  if (listItemsDistance[i] == Math.max.apply(null, listItemsDistance)) {
    listItems[i].classList -= "notLast";
  } else {
    listItems[i].classList = "notLast";
  }
}

Я добавил класс notLast ко всем вашим элементам и тому, что содержит псевдоэлемент :after с каналом. Этот script удаляет этот класс из тех, которые ближе к правому краю контейнера.

Я также испортил псевдоэлемент :after и сделал его position:absolute; по темным причинам.