Комбинирование псевдоэлементов CSS, «: после» и «: last-child»


122

Я хочу составлять «грамматически правильные» списки с помощью CSS. Вот что у меня есть на данный момент:

Эти <li>теги отображаются горизонтально с запятыми после них.

li { display: inline; list-style-type: none; }

li:after { content: ", "; }

Это работает, но я хочу, чтобы у «последнего ребенка» была точка вместо запятой. И, если возможно, я бы также хотел поставить «и» перед «последним ребенком». Списки, которые я создаю, генерируются динамически, поэтому я не могу просто дать класс «последним потомкам». Вы не можете комбинировать псевдоэлементы, но я хочу добиться именно этого эффекта.

li:last-child li:before { content: "and "; }

li:last-child li:after { content: "."; }

Как мне заставить это работать?


4
вам действительно не следует использовать css для этого.
Funky Dude

2
Я должен немного согласиться с Funky Dude. Было бы лучше сделать это в HTML (или коде, если это больше, чем простой HTML). CSS предназначен для форматирования :)
Zyphrax

16
Я ... лично склонен утверждать, что в списке форматирование - это тонкость, а не необходимость. В этом случае использование CSS позволяет выполнять более простые добавления или удаления из списка, чем использование HTML или кодирования на стороне сервера. Но я иногда такой странный, и, честно говоря, ymmv, и т.д ... =)
Дэвид говорит восстановить Монику

9
И +1 за использование оксфордской запятой! :)
Brandon Rhodes

5
+1 за «+1 за оксфордскую запятую». Никогда об этом не слышал (я не родной). Но быстрый поиск в вики говорит, что это естественно, потому что он не используется на многих языках. Забавно, что можно узнать о проблемах CSS при
поиске в

Ответы:


168

Это работает :) (надеюсь, мультибраузерность, Firefox нравится)

li { display: inline; list-style-type: none; }
li:after { content: ", "; }
li:last-child:before { content: "and "; }
li:last-child:after { content: "."; }
<html>
  <body>
    <ul>
      <li>One</li>
      <li>Two</li>
      <li>Three</li>
    </ul>
  </body>
</html>


2
Аналогичная проблема возникает в случае, когда вы разделяете пункты меню вертикальной чертой. То же решение работает. Но последний атрибут содержимого должен быть установлен в {content: none;}, чтобы исключить последний символ вертикальной черты.
aridlehoover

2
Порядок тоже важен. li:last-child:afterработает, но li:after:last-childне работает.
Ричард Айотт

1
Имейте в виду, что :last-childэто не относится к спецификации CSS3, поэтому не поддерживается IE8 и предыдущими версиями.
Cthulhu

23

Мне это нравится для элементов списка в элементах <menu>. Рассмотрим следующую разметку:

<menu>
  <li><a href="/member/profile">Profile</a></li>
  <li><a href="/member/options">Options</a></li>
  <li><a href="/member/logout">Logout</a></li>
</menu>

Я оформляю его с помощью следующего CSS:

menu > li {
  display: inline;
}

menu > li::after {
  content: ' | ';
}

menu > li:last-child::after {
  content: '';
}

Это отобразит:

Profile | Options | Logout

И это возможно из-за того, что Мартин Аткинс объяснил в своем комментарии.

Обратите внимание, что в CSS 2 вы бы использовали :after, not ::after. Если вы используете CSS 3, используйте ::after(два полустолбца), потому что ::afterэто псевдоэлемент (один полустолбец предназначен для псевдоклассов).


16

Старый тред, тем не менее, кому-то это может пригодиться:

li:not(:last-child)::after { content: ","; }
li:last-child::after { content: "."; }

Это должно работать в CSS3 и [непроверенном] CSS2.


11

Вы можете комбинировать псевдоэлементы! Извините, ребята, я сам понял это вскоре после публикации вопроса. Возможно, он используется реже из-за проблем с совместимостью.

li:last-child:before { content: "and "; }

li:last-child:after { content: "."; }

Это прекрасно работает. CSS - это просто потрясающе.


12
Это немного «угол блохолов» А, но «последний ребенок» на самом деле является псевдо- класса , в то время как «до» и «после» псевдо-элементов. Разница в том, что псевдокласс - это дополнительное ограничение для существующего элемента, в то время как псевдоэлемент - это фактически совершенно новый элемент в дереве представления, который был сгенерирован в CSS, а не в HTML. Вы можете комбинировать их по этой причине: last-childэто модификатор для li, а затем после того, как вы выбрали все liэлементы, которые являются последними дочерними элементами, вы затем выбираете (и неявно создаете) новый элемент до и после каждого.
Мартин Аткинс

Я знаю, что вы, вероятно, давно забыли этот конкретный поток, но, поскольку вы упомянули, что ваши списки были переменной длины, стоит отметить, что в большинстве случаев список с ровно двумя элементами не будет правильным с запятой на английском языке. Другими словами, если вы хотели «хлеба с маслом». а не «хлеб и масло». - тогда большинство решений, представленных здесь, будут неполными. Я придумал способ обойти это и опубликовал его ниже в качестве ответа, на случай, если это поможет кому-то, все еще смотрящему так далеко в ветке.
Мэтт Вагнер

6

Кстати, в CSS 3

:после

следует использовать вот так

::после

Из https://developer.mozilla.org/de/docs/Web/CSS/::after :

Обозначение :: after было введено в CSS 3, чтобы установить различие между псевдоклассами и псевдоэлементами. Браузеры также принимают обозначение: после введенного в CSS 2.

Так и должно быть:

li { display: inline; list-style-type: none; }
li::after { content: ", "; }
li:last-child::before { content: "and "; }
li:last-child::after { content: "."; }

3
Каждый браузер, поддерживающий ::синтаксис CSS3 с двойным двоеточием, также поддерживает только :синтаксис, но IE 8 поддерживает только одинарное двоеточие, поэтому на данный момент рекомендуется просто использовать одинарное двоеточие для лучшей поддержки браузера. ::это новый формат с отступом, позволяющим отличать псевдоконтент от псевдоселекторов. Если вам не нужна поддержка IE 8, используйте двойное двоеточие. Из этой статьи
JohnnyQ

2
IE 8 больше не является проигрывателем с точки зрения стандартов браузеров. Не поддерживается Microsoft и не поддерживает HTML5 или CSS3 (псевдоэлементы, преобразования и т. Д.). Раньше я много работал над обратной совместимостью до года назад, вернувшись к IE6 / IE7 (через Modernizr.) Мы прошли долгий путь, и если вы намерены, чтобы ваш сайт представлял свою онлайн-идентичность в долгосрочной перспективе - не становясь недальновидным решением - тогда просто подумайте о доходе, который вы могли бы получить от кого-то, кто использует IE8. Нада. Даже пожилые люди, опоздавшие на 20 лет, сейчас используют планшеты и ноутбуки 2-в-1.
Стивен Вентимилья

2

Добавил еще один ответ на этот вопрос, потому что мне нужно было именно то, о чем просил @derek, и я уже продвинулся немного дальше, прежде чем увидел здесь ответы. В частности, мне был нужен CSS, который также мог бы учитывать случай с двумя элементами списка, где запятая НЕЛЬЗЯ. Например, некоторые авторские подписи, которые я хотел создать, будут выглядеть следующим образом:

Один автор: By Adam Smith.

Два автора: By Adam Smith and Jane Doe.

Три автора: By Adam Smith, Jane Doe, and Frank Underwood.

Решения, уже приведенные здесь, работают для одного автора и для трех или более авторов, но не учитывают случай двух авторов, когда стиль «Оксфордская запятая» (также известный как стиль «Гарвардская запятая» в некоторых частях) не применяется. - т.е. перед союзом не должно быть запятой.

После полудня возни я пришел к следующему:

<html>
 <head>
  <style type="text/css">
    .byline-list {
      list-style: none;
      padding: 0;
      margin: 0;
    }
    .byline-list > li {
      display: inline;
      padding: 0;
      margin: 0;
    }
    .byline-list > li::before {
      content: ", ";
    }
    .byline-list > li:last-child::before {
      content: ", and ";
    }
    .byline-list > li:first-child + li:last-child::before {
      content: " and ";
    }
    .byline-list > li:first-child::before {
      content: "By ";
    }
    .byline-list > li:last-child::after {
      content: ".";
    }
  </style>
 </head>
 <body>
  <ul class="byline-list">
   <li>Adam Smith</li>
  </ul>
  <ul class="byline-list">
   <li>Adam Smith</li><li>Jane Doe</li>
  </ul>
  <ul class="byline-list">
   <li>Adam Smith</li><li>Jane Doe</li><li>Frank Underwood</li>
  </ul>
 </body>
</html>

Он отображает подписи в том виде, в котором они указаны выше.

В конце концов, мне также пришлось избавиться от любых пробелов между liэлементами, чтобы обойти досаду: в противном случае свойство inline-block оставило бы пробел перед каждой запятой. Вероятно, есть альтернативный достойный взлом, но это не является предметом этого вопроса, поэтому я оставлю это кому-нибудь, чтобы ответить.

Скрипка здесь: http://jsfiddle.net/5REP2/


2

Чтобы иметь что-то вроде One, two и three, вы должны добавить еще один стиль css

li:nth-last-child(2):after {
    content: ' ';
}

Это удалит запятую из второго последнего элемента.

Полный код

li {
  display: inline;
  list-style-type: none;
}

li:after {
  content: ", ";
}

li:nth-last-child(2):after {
  content: '';
}

li:last-child:before {
  content: " and ";
}

li:last-child:after {
  content: ".";
}
<html>

<body>
  <ul>
    <li>One</li>
    <li>Two</li>
    <li>Three</li>
  </ul>
</body>

</html>


0

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

Итак, изменение с:

  • Элемент списка 1
  • Элемент списка 2
  • Элемент списка 3

чтобы:

Элемент списка 1; Пункт списка 2; Пункт списка 3.


Он пытается сделать это с помощью CSS. Ваш метод - это жестко запрограммированный HTML. Этот метод обычно используется для отображения навигации.
Sparatan117
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.