css last-child не работает при добавлении div разных классов

У меня есть HTML-код, который выглядит так:

<div class="SomeContainer">
    <div class="MyClass"></div>
    <div class="MyClass"></div>
    <div class="MyClass"></div>
    <div class="MyOtherClass"></div>
</div>

И я использую следующий CSS

.MyClass{...}
.MyClass:last-child{box-shadow:0px 5px 10px black;}

Я ошибочно предположил, что last-child работает с последним дочерним элементом определенного класса, но на самом деле он работает с последним дочерним элементом контейнера, если он принадлежит к тому же классу.

Есть какой-нибудь удобный способ? Я знаю, что могу добавить оболочку вокруг MyClass div и добавить CSS для тени в оболочку, но мне было интересно, есть ли лучший способ сделать это.

Спасибо.


person frenchie    schedule 22.11.2012    source источник


Ответы (2)


Поскольку вы уже пробовали использовать селекторы CSS3, то это правильный псевдокласс для использования

.MyClass:last-of-type

Согласно спецификации CSS3 (по крайней мере, насколько я понимаю) это должно работать, но кажется, что это не так. По крайней мере, не в последних версиях браузеров Chrome (v23) и Firefox (v17).

ВНИМАНИЕ: приведенная выше информация не работает и может вводить в заблуждение, что существует чистое решение этой проблемы с помощью CSS... Потому что в CSS3 его нет. CSS4, с другой стороны, будет иметь дополнительный псевдокласс :nth-last-match(n), который, скорее всего, покроет именно этот сценарий. Но пока рано говорить о том, что не все селекторы CSS3 реализованы в браузерах.

Дополнительное расследование

Вот JSFiddle, который показывает, как на самом деле работает этот селектор псевдокласса:

  1. получить все элементы, удовлетворяющие селектору CSS (без псевдо)
  2. получить их различные типы элементов HTML (теги)
  3. выбрать все родственные элементы одного типа (тега) для каждой группы типов (тегов)
  4. Сократите каждую группу типов (тегов) до последнего элемента в группе
  5. Удовлетворяет ли этот оставшийся элемент (каждой группы) селектору (без псевдо)?
  6. Если true, тогда применяйте стиль, в противном случае не применяйте

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

Кажется, это работает одинаково в Chrome и Firefox. И если мы внимательно прочитаем спецификацию, там действительно сказано

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

Если бы он сказал, что это последний брат, который удовлетворил селектор, то мое верхнее решение сработало бы. Итак, давайте проверим мои шаги.

Выполните шаги, используя ваш HTML

  1. получает первые 3 элемента
  2. только один тип: div
  3. четыре элемента (включая последний)
  4. сократить до последнего
  5. удовлетворяет? Нет
  6. не задавать стиль

Еще пара примеров в моей скрипке

Чтобы проверить поведение селектора псевдокласса, я добавил два дополнительных примера. Вот HTML:

<!-- First -->
<div class="SomeContainer">
    <div class="MyClass">Content</div>
    <div class="MyClass">Content</div> 
    <p class="MyClass">Content</p>
    <p class="MyClass">Content</p>
</div>

<!-- Second -->
<div class="SomeContainer">
    <div class="MyClass">Content</div>
    <div class="MyClass">Content</div>
    <div class="MyClass">Content</div>
    <p class="MyOtherClass">Content</p>
</div>

В первом два элемента удовлетворяют селектору (последний div и последний p).
Во втором один элемент удовлетворяет селектору (последний div)

Исход

Имея предоставленный вами HTML и предполагая, что может быть произвольное количество элементов с .MyClass, невозможно написать общий селектор в CSS3, который фактически нацеливался бы на последний элемент с определенным классом CSS.

Лучший способ — добавить дополнительный класс к элементам, которые представляют последний элемент с определенным классом, и написать селектор для этого.

person Robert Koritnik    schedule 22.11.2012
comment
Это должно работать, но я решил просто добавить класс, определяющий мою тень программно, поскольку я также генерирую HTML таким образом; это цикл, который создает div MyClass и в конце просто добавляет класс, который делает тень. Это работает нормально. - person frenchie; 22.11.2012
comment
@frenchie: на первый взгляд должно быть да. Но я исследовал еще дальше и тщательно проверил спецификацию, и это не так. Я добавил объяснение, как на самом деле работает этот псевдокласс. - person Robert Koritnik; 22.11.2012
comment
@BoltClock: Вы ошибаетесь, когда говорите, что мои шаги недействительны. Ваш пример доказывает, что они верны. Я не говорю, что рендереры браузера действительно работают в соответствии с моими шагами. Нет. Я просто хотел объяснить, как применяется этот селектор. В вашем примере, когда вы добавили дополнительный div, этот элемент добавляется на моем шаге 3, а когда группа уменьшается на шаге 4, ваш добавленный элемент остается тем, который остался. И это не удовлетворяет селектору (без псевдо), так что это не специально стилизовано. Мои шаги все еще работают. - person Robert Koritnik; 22.11.2012
comment
@BoltClock: Не беспокойтесь. Я просто думаю, можно ли его каким-то образом объединить с :not(), чтобы фактически получить последний из его селектора, но я думаю, что это тоже невозможно... Должен быть селектор :last-of-selector, который удовлетворял бы этому требованию. - person Robert Koritnik; 22.11.2012
comment
@Robert Koritnik: Ну, в Selectors 4 есть :nth-last-match(1 of selector), который совпадает с братьями и сестрами (аналогично :nth-last-child(1) или :nth-last-of-type(1)). Выглядит многообещающе! Но синтаксис довольно неудобный: :nth-last-match(1 of .MyClass). - person BoltClock; 22.11.2012
comment
@BoltClock: Хорошо. Тогда мы можем также ожидать, что псевдокласс :last-match будет иметь такой же набор связанных псевдоклассов, как и в CSS3... Даже несмотря на то, что его еще нет в предложении CSS4... Если нет, мы просто будем использовать :nth-last-match(1)... Спасибо за информация. - person Robert Koritnik; 22.11.2012
comment
Да, мне интересно, почему они не включили это. Возможно, они подумали, что не стоит тратить время на его включение в спецификацию, пока не будет подтверждено, что люди заинтересованы в его реализации. - person BoltClock; 22.11.2012
comment
@BoltClock: я думаю, что спецификация подразумевает использование .MyClass:nth-last-match(1), а не :nth-last-match(1 of .MyClass), как вы говорите. Было бы легче понять, если бы они добавили пример, как с другими селекторами, и, поскольку нет подобного псевдокласса, мы можем интерпретировать этот селектора так, как мы хотим. :) - person Robert Koritnik; 22.11.2012

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


.SomeContainer > div, .SomeContainer > span { width: 20px; height: 20px; background: red}
.SomeContainer > div:last-of-type {background: green}
.SomeContainer > span:last-child {box-shadow:0px 5px 10px black; background: blue; display: block}
<div class="SomeContainer">
    <div class="MyClass"></div>
    <div class="MyClass"></div>
    <div class="MyClass"></div>
    <span class="MyOtherClass"></span>
</div>
person Lincoln B    schedule 22.11.2012
comment
Это не то, что нужно ОП. Они хотят выбрать последний div с классом MyClass, а не последний дочерний... - person Robert Koritnik; 22.11.2012
comment
Именно, тип в :last-of-type относится к типу элемента или имени его тега. Все остальное не имеет значения. - person BoltClock; 22.11.2012