Последний элемент среди соседей можно выбрать селектором псевдо-класса :last-child
.
.item { display: block; }
.item:last-child { font-weight: bold; }
Разметка:
<div>
<div class="item item_rank_1">Object “A”</div>
<div class="item item_rank_1">Object “B”</div>
<div class="item item_rank_0">Object “C”</div>
</div>
Но, если с помощью медиа-запроса скрыть часть элементов списка, то получить последний видимый элемент уже так просто не выйдет.
@media (max-width: 600px) {
.item_rank_0 { display: none; }
}
Казалось бы можно использовать селектор .item_rank_1:last-child
, но это так не работает. Псевдо-класс :last-child
позволяет найти только одного последнего ребёнка своего родителя.
Но мы уже живём в мире HTML5, где можно грабить корованы и придумывать свои собственные теги (оригинал ). По этому вместо того, чтобы отличаться классами, элементы будут отличаются названиями тегов.
<div>
<item-rank-1 class="item">Object “A”</item-rank-1>
<item-rank-1 class="item">Object “B”</item-rank-1>
<item-rank-0 class="item">Object “C”</item-rank-0>
</div>
Да, так тоже можно, если очень хочется.
Теперь в медиа-запросе можно использовать селектор :last-of-type
для того, чтобы получить последний элемент группы, которая не была скрыта.
@media (max-width: 600px) {
item-rank-0.item { display: none; }
item-rank-1:last-of-type { font-weight: bold; }
}
Таким способом можно создавать любые теги и они будут прекрасно поддаваться оформлению через CSS. Для IE < 9 нужно будет их предварительно создать с помощью JavaScript так как делаем это для новых HTML5 элементов.
Комбинируя названия тегов с правилами их видимости, вполне можно подобрать такие селекторы, которые будут выбирать последний видимый элемент.
PS: Не забудьте, что вес тега меньше, чем вес класса при определении специфичности селектора. Так же в названии тега обязательно должен быть символ -
, чтобы парсер мог отличить обычные элементы от ваших собственных.
Коментарии к заметке
Правильно ли я понял, что суть проблемы сводится к тому, что нужно определенным образом стилизовать последний элемент у родителя, однако он является экстраразметкой (то есть последний элемент, отображаемый для пользователя, не является реально последним в коде)?
Антон, совершенно верно.
А не проще ли вместо кастомных тегов использовать span для экстраразметки? ;)
Хм, можно просто нужные классы в нужных местах расставить, если на то пошло. Живём же мы без поддержки
:last-child
в IE8, например.Задумка в том, чтобы использовать «новые» возможности, которые уже есть прямо сейчас в актуальных версиях браузеров.
Интересный хак, конечно может помочь решить специфичную задачу, но с кастомными тегами тяжелей работать из за необходимости фаллбеков и отсутствия семантики тоже не особо радует.
Еще беспокоит использование модификатор в название тега, а общем подходе работы с кастомными тегами, я бы выбрал в данном случае имя item, ибо так логичней, а модификатор добавлял бы классом, это проще чем при модификации менять название тега.
Круто, но, ИМХО, очень хрупко и сильносвязанно. Почему, например, не так: http://codepen.io/davidmz/pen/mAeoG
Давид, так у тебя же получаются позиции вообще захардкодены. Для применения селекторов псевдо-классов
:nth-child()
нужно знать точные позиции. А если этот список генерируется автоматически, то идея ломается.Я для пробы это способа «в бою» реализовал его в облаке тегов в шапке старницы. При достаточно узком окне они не помещаются в отведённое им место. По этому часть приходится скрывать медиа-запросом. А выбор последнего элемента нужен для того, чтобы не ставить после него запятую.
Роберт, согласен, что этот метод не для широкого применения. А проблем с кастомными тегами нет. Сейчас же работают
<article>
,<section>
и т.п. во всех браузерах и в IE с включенным JavaScript. Тут всё происходит по тому же сценарию. Фолбеки, скорее всего, понадобятся только для CSS3 селекторов, у которых нет поддержки в конкретной версии браузера (читай IE < 8).Так тут идея в том, что мы используем разные названия тегов, чтобы потом применять к ним селектор псевдо-класса
:last-of-type
. Когда теги будут называться одинаково, то никакого профита не получим. Они ничем не будут отличаться от штатных<div>
или<span>
. Это, конечно, взрыв мозга название делать модификатором. По этому и хочется обсудить жизнеспособность идеи.С семантикой, действительно, не всё так просто. Ей тут не откуда взяться. Тут в комментариях к соседней статье тоже немного рассуждали с SelenIT на эту тему. Мне кажется, что добавить семантику для машины есть куча других более эффективных способов: атрибуты role и aria-*, microdata, RDFa и т.п.
Для автогенерации я что-то такое делал: http://codepen.io/davidmz/pen/HaiJs (адаптировал для случая с запятыми).
Я имею в виду, что можно использовать div вместо item-rank-1 и span вместо item-rank-0. Вот так: http://jsfiddle.net/bXaWj/5/
Ах вот оно зачем. Значит, дело не в экстра-разметке. Но как тогда определяется количество тегов, которые останутся видимыми при любой ширине? Если это число постоянно, то можно действительно просто класс вписать в нужный элемент.
Идея веб-компонентов на кастомных тегах крута, но, насколько я понимаю, с точки зрения самого стандарта HTML5 это пока именно грабёж корованов:). Custom Elements (по ссылке из статьи на html5rocks) — всего лишь первый опубликованный черновик, поэтому кастомные теги воспринимаются как обычные HTMLUnknownElement-ы, и валидатор смотрит на них неодобрительно. Да и по прямому назначению кастомные элементы нуждаются в мощной огневой JS-поддержке, так что использовать их для pure-CSS-решения, по-моему, не совсем по их идеологии. Хотя, судя по той статье, шансов на быстрое внедрение у них-таки побольше, чем у
:nth-last-match()
из селекторов 4-го уровня… Но я бы применял такое только в динамически генерируемых интерфейсах, для перестраховки.Но для частной задачи расстановки запятых, имхо, это всё же из пушки по воробьям. Лично я не вижу особой проблемы добавлять запятую не после, а перед всеми элементами, кроме первого, что бескостыльно поддерживается даже в IE8 — устраняя сабжевую проблему в корне (при условии, что первый эл-т остается видимым всегда).
Ого, сам цитировал, но последнее насчет запятых ускользнуло от меня во время прочтения =) Разве в облаках тегов вообще ставятся запятые? Ну или еще более радикальный вопрос: облака тегов разве все еще считаются уместными элементом интерфейса? ;)
Теги имеют разные «модификаторы» и скрываются исходя из значения этого модификатора. Для АНБ–подхода (или БЭМ, если хотите) модификаторы будут указываться в значении класса. В моём случае модификатором будет служить название тега.
Какие нужно скрывать модификаторы подбирается, как обычно, на глаз.
Антон, зависит от дизайна. С точки зрения грамматики это перечисление. Ведь так? Я считаю, что запятые нужны. Могу ошибаться.
Почему бы и нет?! Дело вкуса.
SelenIT, тем не менее, это не помешало Яндексу рекомендовать использовать на страницах вообще никем не поддерживающийся тег <noindex> много лет назад. Валидаторы помогают разработчикам находить свои ошибки. Когда страница выглядит и работает как нужно, то на предупреждения валидатора можно закрыть глаза.
Не вижу проблемы. Они поддаются оформлению без плясок с JavaScript уже сейчас. Чтобы узлы в DOM были экземплярами нужного класса, нужно ровным счётом сделать вызов одного метода с параметрами. Раз мы уже пишем JS для работы с этими элементами, то почему бы их не зарегистрировать? В любом другом случае, специальная регистрация кастомных элементов, если я правильно понимаю, не требуется.
Тег
<noindex>
как раз не предполагал какого-либо оформления в браузере. Он был машиночитаемым аналогом обычного коммента а-ля<!-- лишняя информация -->
(на который его, по сути, в итоге и заменили). Понятно, что ископаемые браузеры типа Fx3, которые очень вольно трактовали кастомные теги приtext/html
(не позволяя им содержать блочных эл-тов и т.п.), сейчас в глубокой маргинальности, а всё новое использует предсказуемый алгоритм парсинга из HTML5… но с еще более предсказуемыми стандартными элементами оно как-то спокойнее. Мало ли, как к нашей самодеятельности отнесутся всякие скринридеры и пр. «вспомогалки». Всё-таки, если у какой-то технологии проблемы с валидной разметкой, то это явно проблема той технологии, в случае же невалидной доказать это намного труднее..:)Я смотрю на это с другой стороны: «раз уж мы пишем компонент с функциональностью на JS под определенный спектр платформ, почему бы не использовать в нем инструменты, заведомо работающие в этих платформах и упрощающие жизнь» (напр., избавляющие от необходимости борьбы с дефолтными стилями для списков и дефолтным действием для ссылок). Для таких компонентов (заведомо попадающих только в надежные руки правильных браузеров, а не в шаловливые ручки поисковиков и пр. ботов:) кастомные теги — золотая находка. Но статической разметке, отдаваемой всему белу свету без разбора, имхо, лучше опираться на что-то более «материальное». К тому же конкретно у облака тегов (в отличие от крошек;) как раз есть явная семантика перечисления (т.е. однородного списка ), и какой-то софт (те же вспомогательные технологии) вполне может по крайней мере попытаться учесть и семантику тегов…
Думаю, что с ними будет всё хорошо. Я проверял своё облако тегов в Voice Over и в JAWS — всё хорошо зачитывает, хотя там и без кастомных тегов такого накручено.
В худшем случае вспомогательная технология выбросит незнакомые теги во время разбора супа (например, HTML Tidy делает именно так), но оставит их контент не тронутым. Наверное, это не смертельно.
Всем не угодишь. Конкретно в крошках я намерено избавился от всякой семантики и даже текстового контента , чтобы скрыть его от поисковиков. Это был интересный эксперимент и всё получилось даже лучше, чем я ожидал.
Меня, в основном, напрягал риск, что левый софт построит совсем неприличное DOM-дерево (напр. запутается в открытии и неявном закрытии незнакомых оберток и блочных вставок, если таковые есть, и получит безумную лестницу вложенности). Если внутри только ссылки и
<span>
-ы, наверное, риск и вправду стремится к нулю. В общем, практически убедили:)И спасибо за интересный и поучительный эксперимент по скрытию контента от поисковиков с сохранением доступности!
SelenIT, на доброе здоровье.
На этот счёт код можно валидировать в IE6. Если в нём суп из тегов будет правильно представлен, то значит и другие парсеры, с большой вероятностью, разберут его аналогично.
Вот здесь решительно не соглашусь. Как раз у старых IE парсер был очень своеобразный, ни на что не похожий, хоть порой в этой странности и была некая логика (напр., при попытке вставить заголовок или что-то похожее между элементами списка они запихивали это что-то внутрь последнего элемента, игнорируя даже явный закрывающий тег — зато итоговое дерево получалось более-менее корректным). Меня больше беспокоили аналоги старых Огнехвостов, там с закрывающими неизвестными тегами случались интересные накладки (особенно если среди участников действа оказывались неявно закрывающиеся элементы). Но для второстепенной информации, которая даже от поисковиков скрыта, пожалуй, действительно можно этим особо не заморачиваться.
SelenIT, поставил сейчас себе Firefox 3.0 + Firebug 1.4
Документ разобрался без ошибок. Все кастомные теги оказались на своих местах и
document.getElementsByTagName()
их правильно находит.Попутно подтвердилась теория о том, что незнакомые элементы получают
display: inline
как и в случае с тегами<article>
,<section>
и т.п.