CSS: последний тип не работает в сочетании с: not

У меня есть что-то, что ведет себя так же, как предоставленный фрагмент. У меня есть список элементов, когда при выборе одного из них я хочу, чтобы он отображался в верхней части списка, что я могу легко сделать с помощью упорядочения по гибкому порядку. За один раз можно выбрать только один. Но поскольку каждый элемент списка имеет границы, последний элемент не должен иметь границы. Простое использование li:last-of-type отлично работает в большинстве случаев, за исключением тех случаев, когда выбран последний элемент списка.

Я пробовал несколько селекторов, которые должны выбрать последний элемент списка в неупорядоченном списке, который не имеет данного класса, но селектор last-of-type, похоже, не ведет себя правильно.

В случае, если в коде не ясно, селектор, к которому я обращаюсь, равен .selection li:not(.selected):last-of-type. И проблема заключается в двойной границе внизу списка. Это должна быть единая граница, исходящая из неупорядоченного элемента списка.

.selection ul {
  display: flex;
  flex-direction: column;
  border: .15rem solid #666;
}

.selection li {
  order: 2;
  border-bottom: .15rem dashed #666;
}

.selection li.selected {
  order: 1;
}

/** This selector should work in my mind, but it doesn't **/
.selection li:not(.selected):last-of-type {
  border-bottom: none;
}

/** Non-important styles to put it into context **/
ul { list-style: none; padding: 0; width: 25%; margin: 2rem auto; }
li { padding: 1rem 2rem; background-color: #ebebeb; }
li:hover { background-color: #ccc; }
a { color: inherit; text-decoration: none; }
<div class="selection">
  <ul>
    <li><a href="">1</a></li>
    <li><a href="">2</a></li>
    <li class="selected">3</li>
  </ul>
</div>

Ответ 1

Рассмотрим этот альтернативный подход:

  • Полностью избавиться от селектора :not
  • Дайте ul рамку только слева, справа и сверху
  • Примените нижнюю границу только к li

ul {
    display: flex;
    flex-direction: column;
    border-top: .15rem solid #666;
    border-left: .15rem solid #666;
    border-right: .15rem solid #666;
}

li { border-bottom: .15rem solid #666; }

Пересмотренный Codepen


Вот почему ваш селектор не работает:

.selection li:not(.selected):last-of-type { border-bottom: none; }

Мне кажется, что вы говорите, что хотите сопоставить последний элемент li, если у него нет класса selected.

Но это не так, как работает last-of-type. Если li является родным братом, селектор будет соответствовать ему, независимо от class. Селектор соответствует элементам DOM. Это означает, что даже если вы применили display: none к li, селектор по-прежнему будет соответствовать ему.

6.6.5.9. :last-of-type псевдокласс

Псевдокласс класса :last-of-typeпредставляет собой элемент, который является последним родственным его типом в списке дочерних элементов его родительского элемента.

<суб > Источник: https://drafts.csswg.org/selectors-3/#last-of-type-pseudo

Подробнее: Как заставить селектор nth-child пропустить скрытые div

Ответ 2

Вместо того, чтобы удалять border-bottom из последнего невыбранного элемента (что сложно или невозможно в CSS), проще всего установить border-top для каждого элемента и удалить лишний элемент из объекта визуально над другими, который... .selected!
Ваше ограничение:

другая граница элементов моего списка, чем на общей внешней границе

разрешено с помощью этого решения.

Обновлено перо

.selection ul {
  display: flex;
  flex-direction: column;
  border: .15rem solid #666;
}

.selection li {
  order: 2;
  border-top: .15rem dashed #666;
  background: lightblue;
}

.selection li.selected {
  order: 1;
  border-top: none;
  background: tomato;
}

/** Non-important styles to put it into context **/
ul { list-style: none; padding: 0; width: 25%; margin: 2rem auto; }
li { padding: 1rem 2rem; background-color: #ebebeb; }
li:hover { background-color: #ccc; }
a { color: inherit; text-decoration: none; }
<div class="selection">
  <ul>
    <li><a href="">1</a></li>
    <li><a href="">2</a></li>
    <li class="selected">3</li>
  </ul>
</div>

Ответ 3

Рассмотрим это скорее как взломать, чем ответ.

Просто чтобы показать, что это может быть каким-то образом сделано в CSS

выбран желтый элемент.

.selection ul {
  display: flex;
  flex-direction: column;
  border: .15rem solid #666;
}

.selection li {
  order: 2;
  border-bottom: .15rem dashed #666;
}

div.selection li.selected {
  order: 1;
  background-color: yellow;
}

.selection li:nth-last-child(2) {
  order: 3;
}

.selection li:not(.selected):nth-last-child(2) {
  border-bottom: none;
}

.selection li.selected:nth-last-child(2) ~ li {
  border-bottom: none;
}


/** Non-important styles to put it into context **/
ul { list-style: none; padding: 0; width: 25%; margin: 2rem auto; }
li { padding: 1rem 2rem; background-color: #ebebeb; }
li:hover { background-color: #ccc; }
a { color: inherit; text-decoration: none; }
.selection {display: inline-block; width: 160px;}
<div class="selection">
  <ul>
    <li><a href="">1</a></li>
    <li><a href="">3</a></li>
    <li class="selected">2</li>
  </ul>
</div>
<div class="selection">
  <ul>
    <li><a href="">1</a></li>
    <li><a href="">3</a></li>
    <li><a href="">2</a></li>
  </ul>
</div>
<div class="selection">
  <ul>
    <li><a href="">1</a></li>
    <li class="selected"><a href="">3</a></li>
    <li><a href="">2</a></li>
  </ul>
</div>