Техніки роботи з DOM: батьківські, дочірні та сусідні елементи. Дочірні та контекстні CSS селектори Звернення до першого дочірнього елемента css

💖 Подобається?Поділися з друзями посиланням

Складні та важкі веб-програми стали звичайними в наші дні. Кросбраузерні та прості у використанні бібліотеки типу 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 , якщо я хочу вибрати дочірні елементи, відмінні від першого або останнього. Це робиться поєднанням властивостей першого elementChild і 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() .

Основне завдання даного селектора випливає з його назви та полягає у зверненні до дочірнього елемента. Виводиться за допомогою елементарного знака ">", який пов'язує дочірній елемент з елементом батька. Також варто зазначити, що у використанні прості селектори. Як приклад розглянемо таке кодування:

Element > ul ( padding- top: 20px; )

Це кодування означає, що до списку, який вкладено в element, буде застосовано внутрішній відступ 20 пікселів від верхнього краю. Наявність цього запису значка «>» показує, що правило застосовується лише до списків першого рівня вкладеності.

Докладний аналіз роботи селектора дочірнього елемента

Селектор елемента дочірнього має схожі характеристики з поняттям селектор нащадка. Однак існує характерна риса, яка показує важливу відмінність даних операцій. Воно у тому, що вплив селектора нащадка поширюється абсолютно всі елементи, тоді як дочірній селектор підпорядковує стилі позицій першого рівня класифікацій.

Наочніше оцінити роботу оператора дочірнього селектора допоможе наступний приклад:

Div > р (color: #ff0000; /* червоний */ )

< div>Цей рядок буде мати за промовчанням чорний текст.< span>Цей рядок перефарбуватися в червоний через те, що р є дочірнім тегом для дива. < p>Знову бачимо чорні літери.< span>Тут ми бачимо також чорні символи, тому що для цього спана батьком є ​​тег р.

Цей приклад підтверджує роботу оператора дочірнього селектора відповідно до ступеня вкладеності.

Обмеження для використання оператора дочірнього селектора

Варто відмітити що дана операціяпідтримується всіма браузерами окрім легендарного Internet Explorer 6. Думаю, мало хто використовує даний браузерОднак якщо такі унікуми є, то для них існує вихід із ситуації, який буде описаний в окремій статті.

Навіщо застосовується

Програмери звертаються до селекторів елементів дочірніх у тих випадках, коли потрібно привласнити свій унікальний стиль вкладеним елементам. Також використання цього селектора може скоротити обсяг CSS, що підвищить читабельність документа. Як показує практика, до цієї операції звертаються найчастіше при створенні меню, що випадають.

Також селектор елемента дочірнього використовується для присвоєння унікальних стилів елементам, батьки яких вже відомі раніше. Іншими словами:

Main > header ( /* оформлення відноситься лише до головного хедеру */ }

Даний приклад справедливий у випадках, коли тег header використовують виділення заголовків статей. У нашому випадку ми задаємо оформлення тільки основному хедеру, і не зачіпаємо другорядні. Цей прийом також дозволяє уникати застосування зайвого разу ідентифікаторів, що полегшує вагу CSS-файлу і робить його більш читабельним.

Підбиваючи підсумки

Таким чином, оператор дочірнього елемента можна застосовувати не тільки для оформлення меню, що випадають, але і для невеликої оптимізації вашого інтернет ресурсу до роботи пошукових роботів.

Останнє оновлення: 21.04.2016

p align="justify"> Особливу групу псевдокласів утворюють псевдокласи, які дозволяють вибрати певні дочірні елементи:

    :first-child : представляє елемент, який є першим дочірнім елементом

    :last-child : представляє елемент, що є останнім дочірнім елементом

    :only-child : представляє елемент, який є єдиним дочірнім елементом у якомусь контейнері

    :only-of-type : вибирає елемент, який є єдиним елементом певного типу (тегу) в якомусь контейнері

    :nth-child(n) : представляє дочірній елемент, який має певний номер n, наприклад, другий дочірній елемент

    :nth-last-child(n) : представляє дочірній елемент, який має певний номер n, починаючи з кінця

    :nth-of-type(n) : вибирає дочірній елемент певного типу, який має певний номер

    :nth-last-of-type(n) : вибирає дочірній елемент певного типу, який має певний номер, починаючи з кінця

Псевдоклас first-child

Використовуємо псевдоклас first-child для вибору перших посилань у блоках:

Селектори в CSS3

Планшети

Смартфони

Топ-смартфони 2016

Samsung Galaxy S7
Apple iPhone SE
Huawei P9


Стиль за селектором a:first-child застосовується до посилання, якщо вона є першим дочірнім елементом будь-якого елемента.

А в другому блоці першим елементом є параграф, тому до жодного посилання не застосовується стиль.

Псевдоклас last-child

Використовуємо псевдоклас last-child:

Селектори в CSS3

Смартфони

Планшети



Селектор a:last-child визначає стиль посилань, які є останніми дочірніми елементами.

У першому блоці саме останнім дочірнім елементом є посилання. А ось у другому останнім дочірнім елементом є параграф, тому у другому блоці стиль не застосовується до жодного з посилань.

Селектор only-child

Селектор: only-child вибирає елементи, які є єдиними дочірніми елементами в контейнерах:

Селектори в CSS3

Заголовок

Текст1

Текст2

Текст3

Текст4



Параграфи з текстами "Текст1" і "Текст4" є єдиними дочірніми елементами у зовнішніх контейнерах, тому до них застосовується стиль - червоний колір шрифту.

Псевдоклас only-of-type

Псевдоклас only-of-type вибирає елемент, який є єдиним елементом певного типу в контейнері. Наприклад, єдиний елемент div, при цьому елементів інших типів у цьому контейнері може бути скільки завгодно.

Селектори в CSS3

Header

Єдиний параграф та елемент спан

Footer


Хоча для елементів div визначено стиль, він не застосовуватиметься, оскільки в контейнері body знаходиться два елементи div, а не один. Зате body є тільки один елемент p, тому він отримає стилізацію. І також у контейнері p є лише один елемент span, тому він також буде стилізований.

Псевдоклас nth-child

Псевдоклас nth-child дозволяє стилізувати кожен другий, третій елемент, лише парні або непарні елементи і т.д.

Наприклад, стилізуємо парні та непарні рядки таблиці:

Селектори в CSS3

Смартфони

SamsungGalaxy S7 Edge60000
AppleiPhone SE39000
MicrosoftLumia 65013500
AlcatelIdol S430000
HuaweiP960000
HTCHTC 1050000
MeizuPro 640000
XiaomiMi535000


Щоб визначити стиль для непарних елементів, селектор передається значення "odd":

Tr:nth-child(odd)()

Для стилізації парних елементів у селектор передається значення "even":

Tr:nth-child(even)()

Також у цей селектор ми можемо передати номер елементу, що стилізується:

Tr:nth-child(3) ( background-color: #bbb; )

У цьому випадку стилізується третій рядок.

Ще одну можливість представляє використання замінника для номера, який виражається буквою n:

Tr:nth-child(2n+1) ( background-color: #bbb; )

Тут стиль застосовується до кожного другого непарного рядка.

Число перед n (у разі 2) представляє той дочірній елемент, який буде виділено наступним. Число, яке йде після знака плюс, показують, з якого елемента потрібно починати виділення, тобто +1 означає, що потрібно починати з першого дочірнього елемента.

Таким чином, у даному випадку виділення починається з 1-го елемента, а наступним виділяється 2*1+1=3-й елемент, далі 2*2+1=5-й елемент і так далі.

Наприклад, якщо хочемо виділити кожен третій елемент, починаючи з другого, ми могли б написати:

Tr:nth-child(3n+2) ( background-color: #bbb; )

Псевдоклас :nth-last-child по суті надає ту саму функціональність, тільки відлік елементів йде не з початку, а з кінця:

Tr:nth-last-child(2) ( background-color: #bbb; /* 2 рядок з кінця, тобто передостанній */ ) tr:nth-last-child(2n+1) ( background-color: #eee ; /* непарні рядки, починаючи з кінця */ )

Псевдоклас nth-of-type

Псевдоклас :nth-of-type дозволяє вибрати дочірній елемент певного типу за певним номером:

Tr:nth-of-type(2) ( background-color: #bbb; )

Аналогічно працює псевдоклас nth-last-of-type тільки тепер відлік елементів йде з кінця:

Tr:nth-last-of-type(2n) ( background-color: #bbb; )

Опис

Псевдоклас :nth-child використовується для додавання стилю до елементів на основі нумерації у дереві елементів.

Синтаксис

елемент: nth-child (odd | even |<число> | <выражение>) {...}

Значення

odd Усі непарні номери елементів. even Усі парні номери елементів. Порядковий номер дочірнього елемента щодо свого батька. Нумерація починається з 1, це буде перший елемент у списку. вираз Задається у вигляді an+b , де a і b цілі числа, а n - лічильник, який автоматично набуває значення 0, 1, 2...

Якщо a дорівнює нулю, воно не пишеться і запис скорочується до b . Якщо b дорівнює нулю, воно також не вказується і вираз записується у формі an . a і b може бути негативними числами, у разі знак плюс змінюється мінус, наприклад: 5n-1.

За рахунок використання негативних значень a і b деякі результати можуть вийти негативними або рівними нулю. Однак елементи впливають лише позитивні значення через те, що нумерація елементів починається з 1.

У табл. 1 наведені деякі можливі вирази та ключові слова, а також зазначено, які номери елементів будуть задіяні.

HTML5 CSS3 IE Cr Op Sa Fx

nth-child

21342135 213621372138
Нафта1634 627457
Золото469 725647
Дерево773 793486
Камені2334 8853103


У цьому прикладі псевдоклас :nth-child використовується зміни стилю першого рядка таблиці, і навіть виділення кольором всіх парних рядків (рис. 1).

Я думаю, що багато хто знає про контекстних селекторах у CSS. Вони використовуються найчастіше, проте досвідчені верстальники чудово знають, що іноді контекстні селектори вносять певні проблеми. Ця проблема пов'язана з тим, що в структурі елемента може бути багато однакових елементів, вкладених один в одного. І необхідно застосувати стиль не для всіх вкладених елементів, а лише безпосередньо дочірньому елементу. Ось для цього і використовуються дочірні селектори в CSS.

Щоб проблема стала зрозумілішою, давайте наведу невеликий приклад. Нехай у нас є такий HTML-код:



Перший абзац



Другий абзац


І наше завдання зробити червоним лише " Другий абзацЯкщо ми напишемо з використанням контекстного селектора:

Container p (
color: red;
}

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

Container > p (
color: red;
}

Все, тепер червоним у нас став лише " Другий абзацОскільки саме даний абзац є безпосередньо дочірнім для .container. А " Перший абзацє дочірнім для внутрішнього divТаким чином, під дію дочірнього селектора він не потрапляє.

Ось так легко вирішуються такі завдання, однак є один величезний мінус дочірніх селекторів у CSS- вони не працюють у браузерах Internet Explorer. З цієї причини їх використання вкрай небажане. Але якщо Ви раптом десь зустрінете, то тепер Ви знатимете, що означає даний типселекторів та що він робить.



Розповісти друзям