en.javascript.info/12-css-for-js/15-css-selectors/article.md
2015-02-27 13:21:58 +03:00

10 KiB
Raw Blame History

Знаете ли вы селекторы?

CSS3-селекторы -- фундаментально полезная вещь.

Даже если вы почему-то (старый IE?) не пользуетесь ими в CSS, есть много фреймворков для их кросс-браузерного использования CSS3 из JavaScript.

Поэтому эти селекторы необходимо знать. [cut]

Основные виды селекторов

Основных видов селекторов всего несколько:

  • `*` -- любые элементы.
  • `div` -- элементы с таким тегом.
  • `#id` -- элемент с данным `id`.
  • `.class` -- элементы с таким классом.
  • `[name="value"]` -- селекторы на атрибут (см. далее).
  • `:visited` -- "псевдоклассы", остальные разные условия на элемент (см. далее).

Селекторы можно комбинировать, записывая последовательно, без пробела:

  • `.c1.c2` -- элементы одновременно с двумя классами `c1` и `c2`
  • `a#id.c1.c2:visited` -- элемент `a` с данным `id`, классами `c1` и `c2`, и псевдоклассом `visited`

Отношения

В CSS3 предусмотрено четыре вида отношений между элементами.

Самые известные вы наверняка знаете:

  • `div p` -- элементы `p`, являющиеся потомками `div`.
  • `div > p` -- только непосредственные потомки

Есть и два более редких:

  • `div ~ p` -- правые соседи: все `p` на том же уровне вложенности, которые идут после `div`.
  • `div + p` -- первый правый сосед: `p` на том же уровне вложенности, который идёт сразу после `div` (если есть).

Посмотрим их на примере HTML:

<h3>Балтославянские языки</h3>

<ol id="languages">
  ...Вложенный OL/LI список языков...
</ol>

CSS-селекторы:

##languages li {
  color: brown;   /* потомки #languages, подходящие под селектор  LI */
}

##languages > li {
  color: black;   /* первый уровень детей #languages подходящих под LI */
}

##e-slavic { font-style: italic; }

*!*
##e-slavic ~ li {  /* правые соседи #e-slavic с селектором LI */
  color: red;
}
*/!*

##latvian { 
  font-style: italic;
}

##latvian * {      /* потомки #latvian, подходяще под * (т.е. любые) */
  font-style: normal;
}

*!*
##latvian + li {  /* первый правый сосед #latvian с селектором LI */
 color: green;
}
*/!*

Результат: [iframe src="relation" border="1" edit link]

Фильтр по месту среди соседей

При выборе элемента можно указать его место среди соседей.

Список псевдоклассов для этого:

  • `:first-child` -- первый потомок своего родителя.
  • `:last-child` -- последний потомок своего родителя.
  • `:only-child` -- единственный потомок своего родителя, соседних элементов нет.
  • `:nth-child(a)` -- потомок номер `a` своего родителя, например `:nth-child(2)` -- второй потомок. Нумерация начинается с `1`.
  • `:nth-child(an+b)` -- расширение предыдущего селектора через указание номера потомка формулой, где `a,b` -- константы, а под `n` подразумевается любое целое число.

    Этот псевдокласс будет фильтровать все элементы, которые попадают под формулу при каком-либо n. Например:

    • `:nth-child(2n)` даст элементы номер `2`, `4`, `6`..., то есть чётные.
    • `:nth-child(2n+1)` даст элементы номер `1`, `3`..., то есть нечётные.
    • `:nth-child(3n+2)` даст элементы номер `2`, `5`, `8` и так далее.

Пример использования для выделения в списке: [iframe src="nthchild" border="1" edit link]

/*+ hide="CSS к примеру выше" */
li:nth-child(2n) { /* чётные */
  background: #eee;
}

li:nth-child(3) {  /* 3-ий потомок */
  color: red;
}
  • `:nth-last-child(a)`, `:nth-last-child(an+b)` -- то же самое, но отсчёт начинается с конца, например `:nth-last-child(2)` -- второй элемент с конца.

Фильтр по месту среди соседей с тем же тегом

Есть аналогичные псевдоклассы, которые учитывают не всех соседей, а только с тем же тегом:

  • `:first-of-type`
  • `:last-of-type`
  • `:only-of-type`
  • `:nth-of-type`
  • `:nth-last-of-type`

Они имеют в точности тот же смысл, что и обычные :first-child, :last-child и так далее, но во время подсчёта игнорируют элементы с другими тегами, чем тот, к которому применяется фильтр.

Пример использования для раскраски списка DT "через один" и предпоследнего DD:

[iframe src="nthchild-type" border="1" edit link]

/*+ hide="CSS к примеру выше" */
dt:nth-of-type(2n) {
  /* чётные dt (соседи с другими тегами игнорируются) */
  background: #eee;
}

dd:nth-last-of-type(2) {
  /* второй dd снизу */
  color: red;
}

Как видим, селектор dt:nth-of-type(2n) выбрал каждый второй элемент dt, причём другие элементы (dd) в подсчётах не участвовали.

Селекторы атрибутов

На атрибут целиком
  • `[attr]` -- атрибут установлен,
  • `[attr="val"]` -- атрибут равен `val`.
На начало атрибута
  • `[attr^="val"]` -- атрибут начинается с `val`, например `"value"`.
  • `[attr|="val"]` -- атрибут равен `val` *или* начинается с `val-`, например равен `"val-1"`.
На содержание
  • `[attr*="val"]` -- атрибут содержит подстроку `val`, например равен `"myvalue"`.
  • `[attr~="val"]` -- атрибут содержит `val` как одно из значений через пробел. Например: `[attr~="delete"]` верно для `"edit delete"` и неверно для `"undelete"` или `"no-delete"`.
На конец атрибута
  • `[attr$="val"]` -- атрибут заканчивается на `val`, например равен `"myval"`.

Другие псевдоклассы

  • `:not(селектор)` -- все, кроме подходящих под селектор.
  • `:focus` -- в фокусе.
  • `:hover` -- под мышью.
  • `:empty` -- без детей (даже без текстовых).
  • `:checked`, `:disabled`, `:enabled` -- состояния `INPUT`.
  • `:target` -- этот фильтр сработает для элемента, `ID` которого совпадает с анкором `#...` текущего URL.

    Например, если на странице есть элемент с id="intro", то правило :target { color: red } подсветит его в том случае, если текущий URL имеет вид http://...#intro.

Псевдоэлементы ::before, ::after

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

При помощи псевдоэлементов ::before и ::after можно добавлять содержимое в начало и конец элемента:

<!--+ autorun -->
<style>
li::before {
  content: " [[ ";
}

li::after {
  content: " ]] ";
}
</style>

Обратите внимание: содержимое добавляется <b>внутрь</b> LI.

<ul>
  <li>Первый элемент</li>
  <li>Второй элемент</li>
</ul>

Псевдоэлементы ::before/::after добавили содержимое в начало и конец каждого LI.

[smart header=":before или ::before?"] Когда-то все браузеры реализовали эти псевдоэлементы с одним двоеточием: :after/:before.

Стандарт с тех пор изменился и сейчас все, кроме IE8, понимают также современную запись с двумя двоеточиями. А для IE8 нужно по-прежнему одно.

Поэтому если вам важна поддержка IE8, то имеет смысл использовать одно двоеточие.

Версии IE7- не понимают этих селекторов. [/smart]

Практика

Вы можете использовать информацию выше как справочную для решения задач ниже, которые уже реально покажут, владеете вы CSS-селекторами или нет.