Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
224 lines (152 sloc) 9.83 KB

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

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

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

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

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

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

  • * -- любые элементы.
  • 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-селекторы:

/*+ no-beautify */
#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 к примеру выше"  no-beautify */
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 к примеру выше"  no-beautify */
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 можно добавлять содержимое в начало и конец элемента:

<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, то имеет смысл использовать одно двоеточие.


## Практика

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