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

Вы дошли до третьей части этой главы. Здесь вы узнаете, как использовать селекторы дочерних элементов в CSS, а также познакомитесь с некоторыми дополнительными псевдоклассами для более точной выборки.

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

В предыдущей статье мы рассказывали о родственных связях между элементами HTML-документа, в том числе и о дочерних элементах. Давайте посмотрим на примере, как эти связи можно использовать в CSS.

Представьте, что вам нужно присвоить стиль только тем тегам

Которые являются дочерними по отношению к , не затрагивая остальные

(например,

Дочерние по отношению к

).
Как это сделать? Очень просто: создадим дочерний селектор:

Body > p { color: #333; }

Обратите внимание на символ > после body . С помощью него вы указываете, что стиль применяется исключительно для дочерних тегов

Родителя . Если символ убрать, то стиль применится абсолютно ко всем тегам

Которые находятся внутри тега , хотя они могут и не являться для него дочерними.

Дополнительные псевдоклассы

В CSS3 существует ряд псевдоклассов для работы с дочерними элементами. Ниже приведено описание каждого из них, примеры использования, а также отличия между псевдоклассами вида «child» и «of-type».

  • :first-child – с помощью этого псевдокласса можно применить стиль к указанному элементу веб-страницы, при условии, что он является первым
  • :last-child – стиль применяется к указанному элементу веб-страницы при условии, что он является последним дочерним элементом своего родителя;
  • :nth-child – позволяет выбрать четные (even) и нечетные (odd) дочерние элементы; также с помощью данного псевдокласса можно стилизовать чередующиеся дочерние элементы, используя выражения вида an+b и числа;
  • :only-child – применяется к дочернему элементу при условии, что тот является единственным ребенком у родителя;
  • :first-of-type – стиль применяется к первому элементу указанного типа (даже если этот элемент не является первым дочерним для своего родителя и над ним находятся другие дочерние элементы других типов);
  • :last-of-type – работает точно так же, как и предыдущий псевдокласс, с той лишь разницей, что стиль применяется к последнему элементу указанного типа ;
  • :nth-of-type – по принципу работы похож на:nth-child , но ориентируется на тип элемента;
  • :only-of-type – применяется к дочернему элементу указанного типа при условии, что тот является у родителя единственным ребенком своего типа .

Пример использования:first-child, :last-child и:nth-child

Первый ребенок

Второй ребенок

Третий ребенок

Нечетный номер
Четный номер
Нечетный номер
Четный номер

Последний ребенок

/* CSS */ p:first-child { font-weight: bold; text-transform: uppercase; } p:last-child { font-style: italic; font-size: 0.8em; } p:nth-child(3) { color: red; } tr:nth-child(odd) { background-color: #A2DED0; } tr:nth-child(even) { background-color: #C8F7C5; } Скриншот: применение:first-child, :last-child и:nth-child

Мы написали CSS стиль для дочерних элементов простого HTML-документа, где тег

является родителем для тегов

,

. Разберем CSS по порядку.

Первое правило – p:first-child – касается элемента p: если он является первым дочерним элементом своего родителя , то к нему применяется стиль (в нашем случае это жирный шрифт и преобразование текста в верхний регистр). Если в данный HTML-код сразу после открывающего тега

добавить еще какой-нибудь тег (к примеру,

), то стиль p:first-child уже не будет отображаться, поскольку

Перестанет быть первым дочерним тегом. В данном случае первым дочерним элементом будет h2 .

Всё то же самое происходит и с правилом p:last-child – стиль CSS будет применен к тегу

Лишь тогда, когда он будет являться последним дочерним элементом своего родителя . Добавьте после

Любой другой тег отличного типа и вы увидите, что правило p:last-child перестанет применяться.

Правило p:nth-child(3) работает для третьего дочернего тега

(об этом свидетельствует число 3 в скобках). Цвет шрифта для этого абзаца становится красным. Вы можете изменить число 3 (например, на 2) и посмотреть результат.

Правила tr:nth-child(odd) и tr:nth-child(even) работают для нечётных и чётных элементов tr соответственно. Вы можете увидеть результат на скриншоте, а также скопировать весь код и поэкспериментировать со стилями самостоятельно.

Пример использования:first-of-type, :last-of-type, :nth-of-type и:only-of-type

Первый ребенок

Второй ребенок

Третий ребенок

Четвертый ребенок

Пятый ребенок

Последний ребенок

/* CSS */ p:first-of-type { color: violet; text-transform: uppercase; } p:last-of-type { font-style: italic; font-size: 0.8em; } p:nth-of-type(3) { color: red; } p:nth-of-type(odd) { background-color: #A2DED0; } p:nth-of-type(even) { background-color: #C8F7C5; } h3:only-of-type { text-decoration: underline; }
Скриншот: применение:first-of-type, :last-of-type, :nth-of-type и:only-of-type

Первое правило CSS, которое вы видите – это p:first-of-type . Что оно делает? Оно выбирает дочерний элемент типа p , который первым встречается у родителя. И не важно, на каком месте среди элементов других типов находится данный тег – на первом, втором или десятом. В этом и заключается отличие между псевдоклассами:first-child и:first-of-type .

Второе правило – p:last-of-type – применяет стиль к последнему дочернему элементу типа p . Как видно из HTML-кода, после последнего тега

Есть еще и тег

, присутствие которого никак не влияет на выполнение CSS-правила (в отличие от варианта с:last-of-child).

Следующее правило – p:nth-of-type(3) – изменяет цвет шрифта на красный. Применяется этот стиль к тегу

Который является третьим по счету элементом своего типа у родителя. На скриншоте вы видите, что красный цвет применяется к тегу

Который по факту является пятым ребенком тега

. Но если не брать во внимание элементы других типов, то получается, что тег

С красным шрифтом находится на третьем месте (среди тегов своего типа). Таким образом работает данное правило.

Правила p:nth-of-type(even) и p:nth-of-type(odd) работают аналогично: поскольку перед двоеточием указано имя p , то выбираются четные и нечетные дочерние элементы типа p и окрашиваются в заданные цвета. Остальные элементы пропускаются.

Последнее правило – h3:only-of-type – применяется к содержимому тега

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

является единственным дочерним элементом своего типа. Если в HTML-код добавить еще один тег

, стиль не будет применён.

Выводы

Дочерний селектор CSS позволяет изменить стиль дочернего элемента HTML-документа, исходя из того, кто является его родителем.

С помощью дополнительных псевдоклассов:first-child, :last-child, :nth-child, :only-child можно стилизовать дочерние элементы HTML-документа, ориентируясь на их местоположение, нумерацию в дереве элементов.

Псевдоклассы:first-of-type, :last-of-type, :nth-of-type, :only-of-type позволяют применять стиль к дочерним элементам HTML-документа, ориентируясь на их тип, а также на нумерацию в дереве элементов.

Я думаю, что многие знают о контекстных селекторах в CSS . Они используются чаще всего, однако, опытные верстальщики прекрасно знают, что иногда контекстные селекторы вносят определённые проблемы. Это проблема связана с тем, что в структуре элемента может быть много одинаковых элементов, вложенных друг в друга. И необходимо применить стиль не для всех вложенных элементов, а только к непосредственно дочернему элементу. Вот для этого и используются дочерные селекторы в CSS .

Чтобы проблема стала более понятной, давайте приведу небольшой пример. Пусть у нас есть такой HTML-код :



Первый абзац



Второй абзац


И наша задача сделать красным только "Второй абзац ". Если мы напишем с использованием контекстного селектора:

Container p {
color: red;
}

То у нас станут красным оба абзаца, что нам совсем не нужно. Данная задача очень просто решается с помощью дочерних селекторов в CSS :

Container > p {
color: red;
}

Всё, теперь красным у нас стал только "Второй абзац ". Поскольку именно данный абзац является непосредственно дочерним для .container . А "Первый абзац " является дочерним для внутреннего div , таким образом, под действие дочернего селектора он не попадает.

Вот так легко решаются такие задачи, однако, есть один огромный минус дочерних селекторов в CSS - они не работают в браузерах Internet Explorer . По этой причине, их использование крайне нежелательно. Но если Вы вдруг где-нибудь встретите, то теперь Вы будете знать, что означает данный тип селекторов и что он делает.

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

Давайте рассмотрим пример простого html-кода:

Дочерние элементы.

Абзац и в нём жирный элемент, и вот наклонный элемент.

Тут жирный и подчёркнутый и наклонный элементы.

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

Теперь давайте к этому html-коду добавим CSS-стили с использованием дочерних селекторов.

Синтаксис дочерних селекторов:

Селектор 1 > Селектор 2 { Свойство: значение; }

Вот обновлённый код:

Дочерние элементы.

Абзац и в нём жирный элемент, и вот наклонный элемент.

Тут жирный и подчёркнутый и наклонный элементы.

Итак, вспомним: дочерний элемент - это элемент вложенный непосредственно в родительский. То есть, дочерний элемент - это потомок первого уровня. Давайте обратим внимание на тег , в первом абзаце он вложен в тег

А во втором он вложен в тег , хотя также является потомком тега

Поэтому во втором абзаце CSS правило для дочернего селектора p>i { color : blue ; } не сработает - наклонный текст второго абзаца не будет отображён синим цветом.

Рисунок 1. Работа примера №1.

Добраться к html-элементу второго абзаца можно используя CSS-правило: p>u>i { color : blue ; }.

Давайте при помощи такого правила зададим наклонному тексту второго абзаца жёлтый цвет.

Дочерние элементы.

Абзац и в нём жирный элемент, и вот наклонный элемент.

Тут жирный и подчёркнутый и наклонный элементы.

Этот стиль сработает и наклонный текст во втором абзаце будет отображён жёлтым цветом.

Рисунок 2. Работа примера №2.

Более сложный пример

У нас есть html-код:

Дочерние элементы.

По умолчанию он интерпритируется так:

Задача: при помощи CSS превратить этот список в горизонтальное меню.


Рисунок 3. Цель преобразований.

Вот решение этой задачи с использованием дочерних селекторов:

Дочерние элементы.

Для лучшего понимания этого примера читайте.

Сложные и тяжелые веб-приложения стали обычными в наши дни. Кроссбраузерные и простые в использовании библиотеки типа jQuery с их широким функционалом могут сильно помочь в манипулировании DOM на лету. Поэтому неудивительно, что многие разработчики использую подобные библиотеки чаще, чем работают с нативным DOM API, с которым было немало проблем . И хотя различия в браузерах по-прежнему остаются проблемой, DOM находится сейчас в лучшей форме, чем 5-6 лет назад , когда jQuery набирал популярность.

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

Подсчет дочерних узлов

Для демонстрации я буду использовать следующую разметку HTML, в течение статьи мы ее несколько раз изменим:

  • Example one
  • Example two
  • Example three
  • Example four
  • Example five
  • Example Six

Var myList = document.getElementById("myList"); console.log(myList.children.length); // 6 console.log(myList.childElementCount); // 6

Как видите, результаты одинаковые, хотя техники используются разные. В первом случае я использую свойство children . Это свойство только для чтения, оно возвращает коллекцию элементов HTML, находящихся внутри запрашиваемого элемента; для подсчета их количества я использую свойство length этой коллекции.

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

Я мог бы попытаться использовать childNodes.length (вместо children.length), но посмотрите на результат:

Var myList = document.getElementById("myList"); console.log(myList.childNodes.length); // 13

Он возвращает 13, потому что childNodes это коллекция всех узлов, включая пробелы - учитывайте это, если вам важна разница между дочерними узлами и дочерними узлами-элементами.

Проверка существования дочерних узлов

Для проверки наличия у элемента дочерних узлов я могу использовать метод hasChildNodes() . Метод возвращает логическое значение, сообщающие об их наличии или отсутствии:

Var myList = document.getElementById("myList"); console.log(myList.hasChildNodes()); // true

Я знаю, что в моем списке есть дочерние узлы, но я могу изменить HTML так, чтобы их не было; теперь разметка выглядит так:

И вот результат нового запуска hasChildNodes() :

Console.log(myList.hasChildNodes()); // true

Метод по прежнему возвращает true . Хотя список не содержит никаких элементов, в нем есть пробел, являющийся валидным типом узла. Данный метод учитывает все узлы, не только узлы-элементы. Чтобы hasChildNodes() вернул false нам надо еще раз изменить разметку:

И теперь в консоль выводится ожидаемый результат:

Console.log(myList.hasChildNodes()); // false

Конечно, если я знаю, что могу столкнуться с пробелом, то сначала я проверю существование дочерних узлов, затем с помощью свойства nodeType определяю, есть ли среди них узлы-элементы.

Добавление и удаление дочерних элементов

Есть техника, которые можно использовать для добавления и удаления элементов из DOM. Наиболее известная из них основана на сочетании методов createElement() и appendChild() .

Var myEl = document.createElement("div"); document.body.appendChild(myEl);

В данном случае я создаю

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

Но вместо вставки специально создаваемого элемента, я также могу использовать appendChild() и просто переместить существующий элемент. Предположим, у нас следующая разметка:

  • Example one
  • Example two
  • Example three
  • Example four
  • Example five
  • Example Six

Example text

Я могу изменить место расположения списка с помощью следующего кода:

Var myList = document.getElementById("myList"), container = document.getElementById("c"); container.appendChild(myList);

Итоговый DOM будет выглядеть следующим образом:

Example text

  • Example one
  • Example two
  • Example three
  • Example four
  • Example five
  • Example Six

Обратите внимание, что весь список был удален со своего места (над параграфом) и затем вставлен после него перед закрывающим body . И хотя обычно метод appendChild() используется для добавления элементов созданных с помощью createElement() , он также может использоваться для перемещения существующих элементов.

Я также могу полностью удалить дочерний элемент из DOM с помощью removeChild() . Вот как удаляется наш список из предыдущего примера:

Var myList = document.getElementById("myList"), container = document.getElementById("c"); container.removeChild(myList);

Теперь элемент удален. Метод removeChild() возвращает удаленный элемент и я могу его сохранить на случай, если он потребуется мне позже.

Var myOldChild = document.body.removeChild(myList); document.body.appendChild(myOldChild);

Таке существует метод ChildNode.remove() , относительно недавно добавленный в спецификацию:

Var myList = document.getElementById("myList"); myList.remove();

Этот метод не возвращает удаленный объект и не работает в IE (только в Edge). И оба метода удаляют текстовые узлы точно так же, как и узлы-элементы.

Замена дочерних элементов

Я могу заменить существующий дочерний элемент новым, независимо от того, существует ли этот новый элемент или я создал его с нуля. Вот разметка:

Example Text

Var myPar = document.getElementById("par"), myDiv = document.createElement("div"); myDiv.className = "example"; myDiv.appendChild(document.createTextNode("New element text")); document.body.replaceChild(myDiv, myPar);

New element text

Как видите, метод replaceChild() принимает два аргумента: новый элемент и заменяемый им старый элемент.

Я также могу использовать это метод для перемещения существующего элемента. Взгляните на следующий HTML:

Example text 1

Example text 2

Example text 3

Я могу заменить третий параграф первым параграфом с помощью следующего кода:

Var myPar1 = document.getElementById("par1"), myPar3 = document.getElementById("par3"); document.body.replaceChild(myPar1, myPar3);

Теперь сгенерированный DOM выглядит так:

Example text 2

Example text 1

Выборка конкретных дочерних элементов

Существует несколько разных способов выбора конкретного элемента. Как показано ранее, я могу начать с использования коллекции children или свойства childNodes . Но взглянем на другие варианты:

Свойства firstElementChild и lastElementChild делают именно то, чего от них можно ожидать по их названию: выбирают первый и последний дочерние элементы. Вернемся к нашей разметке:

  • Example one
  • Example two
  • Example three
  • Example four
  • Example five
  • Example Six

Я могу выбрать первый и последний элементы с помощью этих свойств:

Var myList = document.getElementById("myList"); console.log(myList.firstElementChild.innerHTML); // "Example one" console.log(myList.lastElementChild.innerHTML); // "Example six"

Я также могу использовать свойства previousElementSibling и nextElementSibling , если я хочу выбрать дочерние элементы, отличные от первого или последнего. Это делается сочетанием свойств firstElementChild и lastElementChild:

Var myList = document.getElementById("myList"); console.log(myList.firstElementChild.nextElementSibling.innerHTML); // "Example two" console.log(myList.lastElementChild.previousElementSibling.innerHTML); // "Example five"

Также есть сходные свойства firstChild , lastChild , previousSibling , и nextSibling , но они учитывают все типы узлов, а не только элементы. Как правило, свойства, учитывающие только узлы-элементы полезнее тех, которые выбирают все узлы.

Вставка контента в DOM

Я уже рассматривал способы вставки элементов в DOM. Давайте перейдем к похожей теме и взглянем на новые возможности по вставке контента.

Во-первых, есть простой метод insertBefore() , он во многом похож на replaceChild() , принимает два аргумента и при этом работает как с новыми элементами, так и с существующими. Вот разметка:

  • Example one
  • Example two
  • Example three
  • Example four
  • Example five
  • Example Six

Example Paragraph

Обратите внимание на параграф, я собираюсь сначала убрать его, а затем вставить перед списком, все одним махом:

Var myList = document.getElementById("myList"), container = document.getElementBy("c"), myPar = document.getElementById("par"); container.insertBefore(myPar, myList);

В полученном HTML параграф будет перед списком и это еще один способ перенести элемент.

Example Paragraph

  • Example one
  • Example two
  • Example three
  • Example four
  • Example five
  • Example Six

Как и replaceChild() , insertBefore() принимает два аргумента: добавляемый элемент и элемент, перед которым мы хотим его вставить.

Этот метод прост. Попробуем теперь более мощный способ вставки: метод insertAdjacentHTML() .

Дочерние селекторы CSS - это селекторы, которые используются для применения стилей к элементам только в тех случаях, когда они являются дочерними по отношению к другим (родительским) элементам. Как и селекторы потомков, дочерние селекторы являются составными и складываются из простых селекторов (классы, идентификаторы и т.д.).

И снова, если вы забыли, что такое дочерние элементы, то давайте вспомним, разобрав уже знакомый вам пример.

<тег1> <тег2>... <тег3><тег4>...

Элемент называется дочерним по отношению к другому элементу, если он находится внутри него на первом уровне вложенности. В нашем примере <тег2> и <тег3> являются дочками <тег1> , а <тег4> - это дочка <тег3> .

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

селектор1 > селектор2 {

Пробелы с обоих сторон знака "> " можно ставить, а можно и нет, по желанию.

Пример использования дочерних селекторов CSS

Дочерние селекторы

Параграф1.

Параграф2.

Результат в браузере

Параграф1.

Параграф2.

В этом примере вам надо обратить внимание на два момента. Здесь имеется три элемента , но только у двух из них есть рамки, отступы и поля. Почему? И второй момент. Только у первого параграфа синий цвет текста.

Internet Explorer 6.0 не понимает дочерние селекторы, поэтому, если вы создаете свой сайт с учетом этого старого браузера - помните об этом.

Дочерние селекторы в HTML-таблицах

Многие новички (а иногда уже и не новички) в создании сайтов сталкиваются с определенными проблемами при использовании дочерних селекторов в HTML-таблицах. Чтобы вы поняли, о чем идет речь, давайте посмотрим на такую обычную таблицу.

Ячейка 1.1Ячейка 1.2
Ячейка 2.1Ячейка 2.2

А теперь вопрос. Как вы поступите, если вам понадобится с помощью дочерних селекторов пройти от тега к ячейкам? Если вы решили написать вот так, то это неверно:

table > tr > td { свойство: значение; свойство: значение; ... }

А догадываетесь, почему неверно? Нет? Дело в том, что вы забыли еще про один элемент - , который даже если не указан явно, то все равно незримо присутствует в каждой HTML-таблице. Просто у него нет обязательных открывающих и закрывающих тегов, поэтому про него часто забывают. Кстати да, в HTML-учебнике мы его с вами не проходили, так как в реальности его явное указание редко когда нужно. Ну, думаю вы уже догадались, какая будет правильная запись, но я вам все же покажу.

table > tbody > tr > td { свойство: значение; свойство: значение; ... }

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

Домашнее задание.

  1. Установите на странице шрифт Arial с размером 0.9em и какой-нибудь фон.
  2. Напишите на странице несколько заголовков и параграфов, измените размер и цвет текста заголовков так, как посчитаете нужным.
  3. Сделайте так, чтобы ссылки непосредственно в параграфах страницы были синего цвета без подчеркивания. Но при этом, если ссылки дополнительно обрамляются любым тегом, например для курсива, то они должны отображаться уже с подчеркиванием и красного цвета. Еще раз заостряю ваше внимание на том, что не надо прописывать стили ссылок с каждым обрамляющим тегом в отдельности, сделайте универсально. Как? Подумайте.
  4. Создайте небольшое меню в правой части страницы и зафиксируйте его, для этого вам понадобится свойство и еще парочка сопутствующих ему свойств, там разберетесь. При этом, пусть меню не только остается на месте в пределах окна браузера, но и при скроллинге не наползает на содержимое страницы.

Думаю последний пункт урока будет для вас самым сложным, но не пытайтесь сразу полностью погрузиться в освоение позиционирования. Просто сделайте домашнее задание. Кстати, этот пункт не будет работать в Internet Explorer 6.0, так как старичек не понимает фиксированное позиционирование.


© 2024, leally.ru - Твой гид в мире компьютера и интернета