en.javascript.info/8-css-for-js/15-css-selectors/article.md
2015-03-12 10:26:02 +03:00

254 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Знаете ли вы селекторы?
CSS3-селекторы -- фундаментально полезная вещь.
Даже если вы почему-то (старый IE?) не пользуетесь ими в CSS, есть много фреймворков для их кросс-браузерного использования CSS3 из JavaScript.
Поэтому эти селекторы необходимо знать.
[cut]
## Основные виды селекторов
Основных видов селекторов всего несколько:
<ul>
<li>`*` -- любые элементы.</li>
<li>`div` -- элементы с таким тегом.</li>
<li>`#id` -- элемент с данным `id`.</li>
<li>`.class` -- элементы с таким классом.</li>
<li>`[name="value"]` -- селекторы на атрибут (см. далее).</li>
<li>`:visited` -- "псевдоклассы", остальные разные условия на элемент (см. далее).</li>
</ul>
**Селекторы можно комбинировать, записывая последовательно, без пробела:**
<ul>
<li>`.c1.c2` -- элементы одновременно с двумя классами `c1` и `c2`</li>
<li>`a#id.c1.c2:visited` -- элемент `a` с данным `id`, классами `c1` и `c2`, и псевдоклассом `visited`</li>
</ul>
## Отношения
В CSS3 предусмотрено четыре вида отношений между элементами.
Самые известные вы наверняка знаете:
<ul>
<li>`div p` -- элементы `p`, являющиеся потомками `div`.</li>
<li>`div > p` -- только непосредственные потомки</li>
</ul>
Есть и два более редких:
<ul>
<li>`div ~ p` -- правые соседи: все `p` на том же уровне вложенности, которые идут после `div`.</li>
<li>`div + p` -- первый правый сосед: `p` на том же уровне вложенности, который идёт сразу после `div` (если есть).</li>
</ul>
Посмотрим их на примере HTML:
```html
<h3>Балтославянские языки</h3>
<ol id="languages">
...Вложенный OL/LI список языков...
</ol>
```
CSS-селекторы:
```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]
## Фильтр по месту среди соседей
При выборе элемента можно указать его место среди соседей.
Список псевдоклассов для этого:
<ul>
<li>`:first-child` -- первый потомок своего родителя.</li>
<li>`:last-child` -- последний потомок своего родителя.</li>
<li>`:only-child` -- единственный потомок своего родителя, соседних элементов нет.</li>
<li>`:nth-child(a)` -- потомок номер `a` своего родителя, например `:nth-child(2)` -- второй потомок. Нумерация начинается с `1`.</li>
<li>`:nth-child(an+b)` -- расширение предыдущего селектора через указание номера потомка формулой, где `a,b` -- константы, а под `n` подразумевается любое целое число.
Этот псевдокласс будет фильтровать все элементы, которые попадают под формулу при каком-либо `n`. Например:
<ul>
<li>`:nth-child(2n)` даст элементы номер `2`, `4`, `6`..., то есть чётные.</li>
<li>`:nth-child(2n+1)` даст элементы номер `1`, `3`..., то есть нечётные.</li>
<li>`:nth-child(3n+2)` даст элементы номер `2`, `5`, `8` и так далее.</li>
</ul>
</li>
</ul>
Пример использования для выделения в списке:
[iframe src="nthchild" border="1" edit link]
```css
/*+ hide="CSS к примеру выше" no-beautify */
li:nth-child(2n) { /* чётные */
background: #eee;
}
li:nth-child(3) { /* 3-ий потомок */
color: red;
}
```
<ul>
<li>`:nth-last-child(a)`, `:nth-last-child(an+b)` -- то же самое, но отсчёт начинается с конца, например `:nth-last-child(2)` -- второй элемент с конца.</li>
</ul>
## Фильтр по месту среди соседей с тем же тегом
Есть аналогичные псевдоклассы, которые учитывают не всех соседей, а только с тем же тегом:
<ul>
<li>`:first-of-type`</li>
<li>`:last-of-type`</li>
<li>`:only-of-type`</li>
<li>`:nth-of-type`</li>
<li>`:nth-last-of-type`</li>
</ul>
Они имеют в точности тот же смысл, что и обычные `:first-child`, `:last-child` и так далее, но во время подсчёта игнорируют элементы с другими тегами, чем тот, к которому применяется фильтр.
Пример использования для раскраски списка `DT` "через один" и предпоследнего `DD`:
[iframe src="nthchild-type" border="1" edit link]
```css
/*+ 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`) в подсчётах не участвовали.
## Селекторы атрибутов
<dl>
<dt>На атрибут целиком</dt>
<dd>
<ul>
<li>`[attr]` -- атрибут установлен,</li>
<li>`[attr="val"]` -- атрибут равен `val`.</li>
</ul>
</dd>
<dt>На начало атрибута</dt>
<dd>
<ul>
<li>`[attr^="val"]` -- атрибут начинается с `val`, например `"value"`.</li>
<li>`[attr|="val"]` -- атрибут равен `val` *или* начинается с `val-`, например равен `"val-1"`.</li>
</ul>
</dd>
<dt>На содержание</dd>
<dd>
<ul>
<li>`[attr*="val"]` -- атрибут содержит подстроку `val`, например равен `"myvalue"`.</li>
<li>`[attr~="val"]` -- атрибут содержит `val` как одно из значений через пробел.
Например: `[attr~="delete"]` верно для `"edit delete"` и неверно для `"undelete"` или `"no-delete"`.</li>
</ul>
</dd>
<dt>На конец атрибута</dt>
<dd>
<ul>
<li>`[attr$="val"]` -- атрибут заканчивается на `val`, например равен `"myval"`.</li>
</ul>
</dd>
</dl>
## Другие псевдоклассы
<ul>
<li>`:not(селектор)` -- все, кроме подходящих под селектор.</li>
<li>`:focus` -- в фокусе.</li>
<li>`:hover` -- под мышью.</li>
<li>`:empty` -- без детей (даже без текстовых).</li>
<li>`:checked`, `:disabled`, `:enabled` -- состояния `INPUT`.</li>
<li>`:target` -- этот фильтр сработает для элемента, `ID` которого совпадает с анкором `#...` текущего URL.
Например, если на странице есть элемент с `id="intro"`, то правило `:target { color: red }` подсветит его в том случае, если текущий URL имеет вид `http://...#intro`.
</li>
</ul>
## Псевдоэлементы ::before, ::after
"Псевдоэлементы" -- различные вспомогательные элементы, которые браузер записывает или может записать в документ.
При помощи *псевдоэлементов* `::before` и `::after` можно добавлять содержимое в начало и конец элемента:
```html
<!--+ 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-селекторами или нет.