10 KiB
Знаете ли вы селекторы?
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, то имеет смысл использовать одно двоеточие. [/smart]
Практика
Вы можете использовать информацию выше как справочную для решения задач ниже, которые уже реально покажут, владеете вы CSS-селекторами или нет.