Как создать селектор в css

CSS — Урок 3. Правила и селекторы CSS

CSS, как и любой язык, имеет свой синтаксис. В нем нет ни элементов, ни параметров, ни тегов. В нем есть правила. Правило состоит из селектора и блока объявления стилей, заключенного в фигурные скобки:

Сам блок объявления стилей состоит из свойств и их значений, разделенных точкой с запятой:

Давайте попробуем на практике. Откройте html-страницу и css-страницу, созданные в прошлом уроке. Давайте зададим нашей странице голубой фон. Как вы помните, за это отвечает тег <body>, значит идем на страницу style.css и пишем следующий код:

Снова обновите страницу в браузере и убедитесь, что все так, как и задумывалось.

Думаю, принцип уже понятен: мы указываем селектор, т.е. элемент, к которому применяется стиль, а в фигурных скобках — его свойства и их значения. Свойствам и значениям будут посвящены отдельные уроки, пока же мы рассматриваем общий принцип составления таблицы стилей.

Селекторы CSS

Селекторы по идентификатору

В нашем примере в качестве селекторов использовались элементы страницы: body, h1, h2. Но что делать, если в нашей html-странице есть несколько одинаковых элементов (например, параграфов), и мы хотим, чтобы текст всех параграфов был черным, а одного из них — розовым цветом. Тогда нам понадобится указать уникальный идентификатор для этого параграфа и создать для него стиль.

В HTML идентификатор элемента задается при помощи параметра id, в качестве значения которого указывается уникальное имя. Например:

CSS-селектор :not. Полезные примеры

В спецификации и блогах про селектор :not обычно приводят какие-то искусственные примеры, которые хоть и объясняют синтаксис и принцип действия, но не несут никакой идеи о том, как получить пользу от нового селектора.

Ну окей, думаю я, в моей практике не встречались такие ситуации. Обходились мы ведь как-то раньше без :not . Приходилось немного переписать структуру селекторов или обнулить пару значений.

Пример 1. Элемент без класса

Селектор :not может быть крайне полезен, когда нам нужно застилить контент сгенерированный пользователем (нет возможности расставить в нем классы), или когда у нас контента очень много и расставлять в нем классы слишком трудоёмко.

Например, мы хотим на сайте сделать красивые буллиты для ненумерованных списков ul li . Мы пишем код:

В результате, наши красивые буллиты появляются не только в контенте, но и, например, в навигации, где тоже используются ul li .

Мы ограничиваем область действия селектора:

Навигацию мы спасли, но ненужные буллиты всё еще вылазят на слайдерах, списках новостей и других конструкциях внутри .content , где тоже используются ul li .

Далее у нас варианты:

1) обнулить мешающие стили в слайдерах и других местах. Но это противоречит «DRY » и является одним из признаков «вонючего» кода. К тому же не решает проблему раз и навсегда: добавите, например, аккордеон и списки в нем снова придется обнулять.

2) пойти от обратного и ставить класс всем спискам, которые нужно стилизовать:

Это добавляет лишней работы по расстановке классов в контенте. Иногда имеет смысл, но лишнюю работу никто не любит.

3) стилизовать только те ul li , у которых нет никаких классов вообще:

Победа! Нам не нужно делать дополнительную работу по расстановке классов в контенте. А на слайдерах, аккордеонах и прочих конструкциях, которые не должны выглядеть как списки, но используют их в своей разметке, в 99% случаев уже будут свои классы, и наши стили их не затронут.

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

Пример 2. Изменение внешнего вида всех элементов, кроме наведенного

Такой эффект можно реализовать без :not путем перезаписи значений. И это будет работать в бо́льшем количестве браузеров.

Но если придется обнулять слишком много свойств, то есть смысл использовать :not .

Пример 3. Меню с разделителями между элементами

Меню с разделителями между элементами

Как и в предыдущем примере, желаемого можно добиться несколькими способами.

Через перезапись свойств. Но тут два правила вместо одного, что не есть «DRY ».

Через :nth-last-child() . Одно правило, но тяжело читается.

Через :not() — самая короткая и понятная запись.

Пример 4. Debug css

Удобно для отладки и самоконтроля искать/подсвечивать картинки без alt, label без for и другие ошибки.

Пример 5. Поля форм

Раньше текстовых полей форм было не много. Достаточно было написать:

С появлением новых типов полей в HTML5 этот список увеличился:

Вместо перечисления 14 типов инпутов можно исключить 8 из них:

Ладно, этот пример не очень красив, и я рекомендую всё же первый вариант с перечислением, он работает с IE8+, а второй вариант с IE9+.

Поддержка

Следует заметить, что согласно спецификации в скобках селектора :not() может стоять только простой селектор и в скобках нельзя использовать сам селектор :not() . Если нужно исключить несколько элементов, :not() можно повторить несолько раз, как в примере 5.

Если очень нужны CSS3-селекторы в браузерах, которые их не поддерживают, можно использовать полифил selectivizr.

Количественные CSS селекторы

Вам когда-нибудь хотелось прямо в CSS коде посчитать, в меню 4 элемента или 10? Для четырех задать им ширину по 25%, а если набралось десять — прижать их друг к другу и уменьшить отступы?
Как выяснилось, CSS умеет работать с разным количеством элементов, позволяя избавиться от головных болей и лишнего кода на js.

Динамичный контент

Респонсив дизайн обычно ассоцируется с одной переменной — пространством. Когда мы тестируем респонсив сетки, мы берем какой-то объем контента и смотрим, сколько места он займет, как это выглядит и куда он влазит, а куда нет. То есть, контент считается константой, а пространство — переменной.

Media query являются основой респонсив дизайна, так как позволяют размечать границы, переходя которые одна сетка меняется на другую. Однако, на расстановку элементов и пространство вокруг них может влиять не только размер экрана, но и собственно сам контент.

Точно так же, как посетители сайта могут пользоваться множеством устройств с разными размерами экранов, ваши контент-менеджеры и редакторы могут добавлять или удалять контент. У них даже для этого целые CMS есть. Именно поэтому дизайны страниц в фотошопе потеряли свою актуальность — в них всегда фиксированная ширина экрана и всегда фиксированный контент.

В этой статье я опишу технику создания CSS, лишенного проблем с количеством (подсчётом) элементов. Достигается это за счёт специально оформленных селекторов. Я буду применять их в контесте решения классической проблемы: как разделить вёрстку элементов в горизонтальном меню сайта, когда в нём мало и много элементов. Например, как добиться того, что при 6 и более пунктах меню элементы имели стиль display: inline-block, а при меньшем количестве — display: table-cell.

Я не буду использовать шаблонизацию или js, мне даже не понадобятся прописывать классы у элементов меню. Техника использования только CSS селекторов соответствует принципу разделения интересов, согласно которому, контент (HTML) и отображение (CSS) имеют ясно обозначенные роли. Разметка — это работа CSS и, по возможности, одного только CSS.

Демо доступно на CodePen и еще будет упоминаться по ходу статьи.

Чтобы упростить понимание, я буду использовать картинки с кальмарами вместо HTML тегов. Зеленые кальмары будут за элементы, которые попадают под конкретный селектор, красные — за те, которые не попадают, а серые будут значить, что элемента не существует.

CSS не даёт явного «подсчитывающего API», но мы можем решить эту проблему в обход, комбинируя селекторы нужным образом.

Считаем до одного

Селектор :only-child срабатывает на элементах, которых всегда одна штука. По сути, это позволяет нам «применить стили ко всем дочерним элементам конкретного элемента, если суммарно их ровно 1». Это единственный простой селектор, который можно описать как «подсчитывающий» (кроме, конечно, похожего на него :only-of-type).

В описанном ниже примере я использую :only-of-type, чтобы применить стили ко всем кнопкам, которые являются единственными чилдами-кнопками среди их соседей.

Важно понимать, что очередность строк здесь имеет ключевое значение. Кроме этого, полезно видеть этот код с точки зрения селекта «меньше-чем-два»:

Аналогично, мы теперь можем сделать селект «больше-чем-один», используя отрицание.

N элементов

Применять стили, основываясь на «больше-чем-один» и «меньше-чем-два» это ловкий трюк, но нам нужен более гибкий инструмент, позволяющий оперировать с любым числом. Мы хотим использовать селекты “больше или равно N” для любого N. Кроме этого, хочется иметь селект «ровно 745» или «суммарно ровно 6».

Для этого у нас есть селектор :nth-last-child(n), в который мы параметром передаем любое число. Он позволяет отсчитать столько-то элементов назад от конца списка. Например, :nth-last-child(6) выберет элемент, который является шестым с конца среди своих соседних элементов.

Всё становится интереснее, когда мы совмещаем :nth-last-child(6) и :first-child, в результате получая все элементы, которые являются шестыми с конца и при этом первыми с начала.

Если такой элемент существует, это будет значить, что у нас ровно 6 элементов. Таким образом, я написал CSS код, который может сказать, сколько элементов я вижу перед собой.

Осталось теперь воспользоваться этим одновременно «шестым с конца и первым с начала» элементом, чтобы еще и поселектать все остальные 5 элементов. Для этого я воспользуюсь общим соседним комбинатором.

Если вы не знакомы с этим комбинатором, то объясняю,

li в селекте li:nth-last-child(6):first-child

li значит «любой li, который идёт после li:nth-last-child(6):first-child». В нашем случае, элементы будут иметь зеленый цвет шрифта, если их ровно 6 штук.

Больше или равно 6

Селектать фиксированное количество, будь то 6, 19 или 653 — не очень-то полезно, так как подобная необходимость очень редка. Это как в media queries — не очень удобно использовать фиксрованную ширину вместо min-width или max-width:

В навигационном меню я хочу переключать стили с границей, основанной на количестве элементов, например, поменять нужные стили, если у меня 6 и больше элементов (а не ровно шесть).

Вопрос в том, как сделать такой селектор? и это вопрос смещений.

Параметр n+6

Селектор :nth-child() может принимать параметром не только число, но и формулу “n + [число]”. Например, :nth-child(n+6) будет применён ко всем элементам, начиная с шестого.


Хоть этот селектор и является мощным инструментом сам по себе, он не позволяет оперировать с количеством. Он применится не тогда, когда у нас больше шести элементов, а просто к элементам, у которых номер больше пяти.

Чтобы обойти эту проблему, нам нужно создать такой селект, который выделит все элементы, кроме последних пяти. Используя обратный к :nth-child(n+6) селект :nth-last-child(n+6) мы сможем выделить все элементы «от с шестого с конца и до самого первого с начала».

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

Если же в списке шесть или больше элементов, нам остаётся прибавить к селекту оставшиеся пять элементов. Это легко — если элементов больше шести, то срабатывает условие nth-last-child(n+6), и комбинируя его с "

" мы сможем поселектать все нужные нам элементы.

Такая вот короткая запись и является решением нашей проблемы:

Разумеется, тут может быть любое положительное целое число, даже 653,279.

Меньше или N

Как и в предыдущем примере с :only-of-type, селектор можно использовать в обе стороны, и как «больше или равно N» и как «меньше или равно N». Какой вариант вы будете использовать? Зависит от того, какую сетку вы будете считать основной.
В случае «Меньше или N» мы берем n с минусом и добавляем условие :first-child.

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

nth-child против nth-of-type

Заметьте, что в предыдущих примерах я использовал :nth-child() и :nth-last-child(), а не :nth-of-type() с :nth-last-of-type(). Так как я селектал теги <li> и правильными потомками <ul> могут быть только они, :last-child() и :last-of-type() оказываются одинаково результативны.

Обе группы селектов :nth-child() и :nth-of-type() имеют свои преимущества, исходя из того, чего вы хотите добиться. Так как :nth-child() не привязан к конкретному тегу, описанную выше технику можно применять к смешанным дочерним элементам:

(Обратите внимание, чтобы не привязываться к тегам, я использую универсальный селектор. :last-child(n+3)

*. В этом случае, он обозначает «любой элемент любого тега, следующий за :last-child(n+3).»

С другой стороны, преимущество :nth-last-of-type() в том, что вы можете селектать элементы с одним тегом среди множества других соседних. Например, можно посчитать количество тегов <p>, несмотря на то, что они в одной куче с <div> и <blockquote>.

Поддержка браузерами

Все используемые в статье селекторы CSS2.1 и CSS3 поддерживаются в Internet Explorer 9 и выше, а так же все современные мобильные и десктопные браузеры.

Internet Explorer 8 неплохо поддерживает большинство селектов, но задуматься о полифилле на js не помешает. В качестве альтернативы, можно расставить специальные классы для старых версий IE и приписать их к своим селекторам. В случае с навигационным меню, код будет выглядеть примерно так:

В реальном мире

Предположим, наше навигационное меню принадлежит сайту с CMS. В зависимости от того, кто его наполняет и использует, в меню будет разное количество элементов. Кто-то старается не усложнять и ему хватает «Home» и «About», а кто-то хочет запихать в меню всё, что есть у него на сайте.

Создавая стили, учитывающие разные сетки для разного количества элементов в меню, мы делаем вёрстку более стройной и подходящей для самых разных форматов — какой бы ни был контент, у нас всё учтено.

Поздравляю, теперь в вашем CSS арсенале есть умение оперировать количеством элементов.

Контент-независимый дизайн

Респонсив дизайн решает одну важную проблему: он позволяет комфортно расположить один и тот же контент на множестве разных устройств. Было бы неприемлемо видеть разный контент только потому, что у тебя экран неправильного размера. Так же и неприемлемо диктовать дизайнеру, под сколько пунктов меню должен быть заточен сайт. «Не рисуй так, у нас вся сетка поедет, если будет столько элементов».

Какую форму примет контент и сколько его будет в конкретный момент времени — никто не знает. И мы не можем всегда полагаться на скрипты или обрезание текста, это неправильно. Правильно — быть независимым от количества контента и создавать для этого нужные механизмы и инструменты. Количественные селекторы это просто одна из идей для этого.

Веб дизайн это всегда изменчивость, гибкость и неопределенность. В нём скорее не знаешь, чем знаешь. Он уникален тем, что представляет с собой вид визуального дизайна, который не определяет формы, а предвидит, какие формы может что-то принять. Для кого-то это неприемлемо и непонятно, но для вас и меня это вызов и удовольствие.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *