Как реализовать смещение чётных строк меню при переносе
Хочу добиться реализации динамического меню (кол-во элементов и их содержимое неизвестно), при котором каждая нечётная строчка меню должна иметь отступ от конца строки, а каждая чётная - от начала. Должно получиться, примерно, как на скриншоте:
Пробовал собрать подобное на flex-ах, но не знаю способа выбрать нужную строчку при переносе. Поскольку элементы переносятся в зависимости от размера, нельзя точно сказать, какой элемент списка будет находится в конце строки, а какой в начале (и, соответственно, нельзя выбрать по nth-child).
Реализация на flex-ax необязательна. Но, при этом, хотелось бы обойтись без использования JS.
И ещё несколько моментов:
- В последней строчке, элементы должны быть рядом друг с другом (а не как сейчас они размещены, по правилу space-beetween).
- элемент .more-menu должен всегда находится в конце строки, и смещаться согласно текущему номеру строки (на скриншоте, например, он находится на 5-ой строке и поэтому смещается от правого края).
- Также, при переносе, элемент .more-menu не должен быть единственным элементом на строке (хотя, наверно конкретно это без JS не реализовать).
- Меню должно следовать этому паттерну формирования в любом разрешении экрана.
Собственно, вопрос - как подобное можно реализовать средствами CSS ?
body {
margin: 0;
padding: 0;
}
ul {
list-style: none;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
font-size: 20px;
}
ul li {
margin-right: 28px;
}
ul li:nth-child(16n-8) {
color: red;
padding-right: 30px;
}
ul li:nth-child(16n-7) {
color: brown;
padding-left: 30px;
}
.more-menu {
padding-right: 30px;
}
<ul>
<li>item-1</li>
<li>item-2</li>
<li>item-3</li>
<li>item-4</li>
<li>item-5</li>
<li>item-6</li>
<li>item-7</li>
<li>item-8</li>
<li>item-9</li>
<li>item-10</li>
<li>item-11</li>
<li>item-12</li>
<li>item-13</li>
<li>item-14</li>
<li>item-15</li>
<li>item-16</li>
<li>item-17</li>
<li>item-18</li>
<li>item-19</li>
<li>item-20</li>
<li>item-21</li>
<li>item-22</li>
<li>item-23</li>
<li>item-24</li>
<li>item-25</li>
<li>item-26</li>
<li>item-27</li>
<li>item-28</li>
<li>item-29</li>
<li>item-30</li>
<li>item-31</li>
<li>item-32</li>
<li>item-33</li>
<li>item-34</li>
<li>item-35</li>
<li>item-36</li>
<li>item-37</li>
<li>item-38</li>
<li>item-39</li>
<li>item-40</li>
<li>item-41</li>
<li>item-42</li>
<li>item-43</li>
<li>item-44</li>
<li>item-45</li>
<li>item-46</li>
<li>item-47</li>
<li>item-48</li>
<li>item-49</li>
<li>item-50</li>
<li class="more-menu">....</li>
</ul>
Ответы (1 шт):
Решение на js.
const formatNav = () => {
const containerWidth = $(".nav")[0].offsetWidth;
const list = $(".nav li");
list.removeClass("even");
let isEvenLine = false;
let currentWidthLine = 0;
list.map((i, el) => {
const elWidth = el.offsetWidth;
if (elWidth + currentWidthLine < containerWidth) {
currentWidthLine += elWidth;
} else {
isEvenLine = !isEvenLine;
currentWidthLine = elWidth;
}
isEvenLine ? $(el).addClass("even") : null;
});
};
formatNav();
$(window).resize(() => {
waitForFinalEvent(
() => {
//reset navigation
formatNav();
},
500,
Math.random().toString(36).substr(2, 9)
);
});
//A function that delays the execution of an event for a short period of time
const waitForFinalEvent = (() => {
let timers = {};
return function(callback, ms, uniqueId) {
if (!uniqueId) {
uniqueId = "Don't call this twice without a uniqueId";
}
if (timers[uniqueId]) {
clearTimeout(timers[uniqueId]);
}
timers[uniqueId] = setTimeout(callback, ms);
};
})();
body {
margin: 0;
padding: 0;
}
.container {
padding: 0 15px;
}
.nav {
width: 100%;
padding: 0;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
box-sizing: border-box;
overflow: hidden;
}
.nav li {
padding-right: 40px;
padding-bottom: 13px;
list-style: none;
transition: all 0.3s;
}
.nav li.even {
transform: translateX(35px);
color: brown;
}
.nav li.more-menu.even {
transform: translate(35px, -20%);
}
.nav .more-menu {
margin-left: auto;
transform: translateY(-20%);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<ul class="nav">
<li>item-1</li>
<li>item-2</li>
<li>item-3</li>
<li>item-4</li>
<li>item-5</li>
<li>item-6</li>
<li>item-7</li>
<li>item-8</li>
<li>item-9</li>
<li>item-10</li>
<li>item-11</li>
<li>item-12</li>
<li>item-13</li>
<li>item-14</li>
<li>item-15</li>
<li>item-16</li>
<li>item-17</li>
<li>item-18</li>
<li>item-19</li>
<li>item-20</li>
<li>item-21</li>
<li>item-22</li>
<li>item-23</li>
<li>item-24</li>
<li>item-25</li>
<li>item-26</li>
<li>item-27</li>
<li>item-28</li>
<li>item-29</li>
<li>item-30</li>
<li>item-31</li>
<li>item-32</li>
<li>item-33</li>
<li>item-34</li>
<li>item-35</li>
<li>item-36</li>
<li>item-37</li>
<li>item-38</li>
<li>item-39</li>
<li>item-40</li>
<li>item-41</li>
<li>item-42</li>
<li>item-43</li>
<li>item-44</li>
<li>item-45</li>
<li>item-46</li>
<li>item-47</li>
<li>item-48</li>
<li>item-49</li>
<li>item-50</li>
<li class="more-menu">....</li>
</ul>
</div>
