DOM techniques: parent, child and neighbor elements. Child and contextual CSS selectors Accessing the first child css element

💖 Do you like it? Share the link with your friends

Complex and heavy web applications have become common these days. Cross-browser and easy-to-use libraries like jQuery with their rich functionality can greatly help in manipulating the DOM on the fly. Therefore, it is not surprising that many developers use such libraries more often than working with the native DOM API, with which there were many problems. While browser differences are still an issue, the DOM is in better shape now than it was 5-6 years ago when jQuery was gaining popularity.

In this article, I'll demonstrate the HTML manipulation capabilities of the DOM, focusing on parent, child, and neighbor relationships. In conclusion, I will give information about browser support for these features, but keep in mind that a library like jQuery is still a good option due to the presence of bugs and inconsistencies in the implementation of native functionality.

Counting child nodes

For demonstration I will use the following HTML markup, we will change it several times throughout the article:

  • 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

As you can see, the results are the same, although the techniques used are different. In the first case I use the children property. This is a read-only property and returns the collection of HTML elements contained within the requested element; To count their number, I use the length property of this collection.

In the second example, I'm using the childElementCount method, which I think is a neater and potentially more maintainable way (discuss this more later, I don't think you'll have trouble understanding what it does).

I could try using childNodes.length (instead of children.length), but look at the result:

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

It returns 13 because childNodes is a collection of all nodes, including spaces - keep this in mind if you care about the difference between child nodes and child element nodes.

Checking the existence of child nodes

To check if an element has child nodes, I can use the hasChildNodes() method. The method returns a Boolean value indicating their presence or absence:

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

I know that my list has child nodes, but I can change the HTML so that there aren't any; The markup now looks like this:



And here is the result of running hasChildNodes() again:

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

The method still returns true. Although the list does not contain any elements, it does contain a space, which is a valid node type. This method takes into account all nodes, not just element nodes. In order for hasChildNodes() to return false, we need to change the markup again:



And now the expected result is displayed in the console:

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

Of course, if I know I might encounter whitespace, I'll first check for the existence of child nodes, then use the nodeType property to determine if there are any element nodes among them.

Adding and Removing Children Elements

There are techniques you can use to add and remove elements from the DOM. The most famous of them is based on a combination of the createElement() and appendChild() methods.

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

In this case I create

using the createElement() method and then adding it to body . It's very simple and you've probably used this technique before.

But instead of inserting a specially created element, I can also use appendChild() and simply move the existing element. Let's say we have the following markup:

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

Example text

I can change the location of the list with the following code:

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

The final DOM will look like this:

Example text

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

Notice that the entire list has been removed from its place (above the paragraph) and then inserted after it before the closing body . While the appendChild() method is typically used to add elements created with createElement() , it can also be used to move existing elements.

I can also completely remove a child element from the DOM using removeChild() . Here's how to delete our list from the previous example:

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

The element has now been removed. The removeChild() method returns the removed element so I can save it in case I need it later.

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

There is also a ChildNode.remove() method that was relatively recently added to the specification:

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

This method does not return the remote object and does not work in IE (Edge only). And both methods remove text nodes in the same way as element nodes.

Replacing child elements

I can replace an existing child element with a new one, whether that new element exists or whether I created it from scratch. Here's the markup:

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

As you can see, the replaceChild() method takes two arguments: the new element and the old element it replaces.

I can also use this method to move an existing element. Take a look at the following HTML:

Example text 1

Example text 2

Example text 3

I can replace the third paragraph with the first paragraph using the following code:

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

Now the generated DOM looks like this:

Example text 2

Example text 1

Selecting specific children

There are several different ways selecting a specific element. As shown earlier, I can start by using the children collection or the childNodes property. But let's look at other options:

The firstElementChild and lastElementChild properties do exactly what their names suggest they do: select the first and last child elements. Let's return to our markup:

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


I can select the first and last elements using these properties:

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

I can also use the previousElementSibling and nextElementSibling properties if I want to select child elements other than the first or last one. This is done by combining the firstElementChild and lastElementChild properties:

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

There are also similar properties firstChild , lastChild , previousSibling , and nextSibling , but they take into account all types of nodes, not just elements. In general, properties that consider only element nodes are more useful than those that select all nodes.

Inserting content into the DOM

I've already looked at ways to insert elements into the DOM. Let's move on to a similar topic and take a look at the new features for inserting content.

First, there is a simple insertBefore() method, much like replaceChild(), it takes two arguments and works with both new elements and existing ones. Here's the markup:

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

Example Paragraph

Notice the paragraph I'm going to remove first and then insert it before the list, all in one fell swoop:

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

In the resulting HTML, the paragraph will appear before the list and this is another way to wrap the element.

Example Paragraph

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

Like replaceChild(), insertBefore() takes two arguments: the element to be added and the element before which we want to insert it.

This method is simple. Let's now try a more powerful insertion method: the insertAdjacentHTML() method.

The main task of this selector follows from its name and is to access child element. Displayed using a primitive ">" sign, which links the child element to the parent element. It is also worth noting that simple selectors are used. As an example, consider the following encoding:

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

This encoding means that the list that is nested in element will have padding 20 pixels from the top edge. The presence of the “>” icon in this entry indicates that the rule will only apply to lists of the first nesting level.

A detailed analysis of how the child element selector works

A child element selector has similar properties to the concept of a descendant selector. However, there is a characteristic feature that shows the fundamental difference between these operations. It lies in the fact that the influence of the descendant selector extends to absolutely all elements, while the child selector subordinates the styles of positions of the first level of classifications.

The following example will help you more clearly evaluate the work of the child selector operator:

Div > p ( color: #ff0000; /* red */ )

< div>This line will have black text by default.< span>This line turns red due to the fact that p is a child tag for div. < p>Again we see black letters.< span>Here we also see black symbols, since for this span the parent is the p tag.

This example confirms the operation of the child selector operator according to the degree of nesting.

Restriction for using the child selector operator

It is worth noting that this operation supported by all browsers except the legendary one Internet Explorer 6. I think few people use this browser, however, if there are such unique ones, then for them there is a way out of the situation, which will be described in a separate article.

Why is it used?

Programmers turn to child element selectors when they need to assign their own unique style to nested elements. Also, using this selector can reduce the amount of CSS, which will improve the readability of the document. As practice shows, this operation is most often used when creating drop-down menus.

The child element selector is also used to assign unique styles to elements whose parents are already known. In other words:

Main > header ( /* decoration applies only to the main header */ }

This example is valid in cases where the header tag is used to highlight article titles. In our case, we set the design only for the main header, and do not affect the secondary ones. This technique also allows you to avoid using unnecessary identifiers, which in turn lightens the weight of the CSS file and makes it more readable.

Summing up

Thus, the child element operator can be used not only to design drop-down menus, but also to slightly optimize your Internet resource for the work of search robots.

Last update: 04/21/2016

A special group of pseudo-classes are formed by pseudo-classes that allow you to select specific child elements:

    :first-child : represents the element that is the first child

    :last-child : represents the element that is the last child

    :only-child : represents an element that is the only child of some container

    :only-of-type : selects an element that is the only element of a certain type (tag) in some container

    :nth-child(n) : represents a child element that has specific number n, for example, the second child element

    :nth-last-child(n) : represents the child element that has a specific number n, starting from the end

    :nth-of-type(n) : selects the child element of a certain type that has a certain number

    :nth-last-of-type(n) : selects the child element of a certain type that has a certain number, starting from the end

Pseudo-class first-child

We use the first-child pseudo-class to select the first links in blocks:

Selectors in CSS3

Tablets

Smartphones



The a:first-child selector is styled on a link if it is the first child of any element.

And in the second block, the first element is a paragraph, so no style is applied to any links.

Pseudo-class last-child

We use the last-child pseudo-class:

Selectors in CSS3

Smartphones

Tablets



The a:last-child selector defines the style for links that are the last child elements.

In the first block, the last child element is the link. But in the second, the last child element is a paragraph, so in the second block the style is not applied to any of the links.

Only-child selector

The :only-child selector selects elements that are the only children of the containers:

Selectors in CSS3

Heading

Text1

Text2

Text3

Text4



The paragraphs with texts "Text1" and "Text4" are the only children in their outer containers, so they are styled with red font color.

Pseudo-class only-of-type

The only-of-type pseudo-class selects an element that is the only element of a particular type in the container. For example, a single div element, while there can be as many elements of other types in the same container as you like.

Selectors in CSS3

Header

Single paragraph and span element

Footer


Although the divs have a style defined, it won't be applied because there are two divs in the body container, not one. But in body there is only one p element, so it will receive styling. And also there is only one span element in the p container, so it will be styled as well.

Pseudo-class nth-child

The nth-child pseudo-class allows you to style every second, third element, only even or only odd elements, etc.

For example, let's style the even and odd rows of the table:

Selectors in CSS3

Smartphones

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


To style odd elements, pass the value "odd" to the selector:

Tr:nth-child(odd)()

To style even elements, pass the value "even" to the selector:

Tr:nth-child(even)()

We can also pass the number of the element to be styled to this selector:

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

In this case, the third line is styled.

Another possibility is to use a placeholder for the number, which is expressed by the letter n:

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

Here the style is applied to every second odd line.

The number before n (in this case 2) represents whichever child element will be highlighted next. The number that comes after the plus sign indicates which element the selection should begin with, that is, +1 means that you should start with the first child element.

Thus, in this case, the selection starts with the 1st element, and the next one selected is 2 * 1 + 1 = 3rd element, then 2 * 2 + 1 = 5th element, and so on.

For example, if we wanted to select every third element, starting with the second, we could write:

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

The pseudo-class :nth-last-child essentially provides the same functionality, only elements are counted from the end rather than from the beginning:

Tr:nth-last-child(2) ( background-color: #bbb; /* 2nd line from the end, that is, the penultimate one */ ) tr:nth-last-child(2n+1) ( background-color: #eee ; /* odd lines, starting from the end */ )

Pseudo-class nth-of-type

The :nth-of-type pseudo-class allows you to select a child element of a certain type by a specific number:

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

The pseudo-class nth-last-of-type works similarly, only now elements are counted from the end:

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

Description

The :nth-child pseudo-class is used to add style to elements based on numbering in the element tree.

Syntax

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

Values

odd All odd element numbers. even All even numbered elements. number The ordinal number of the child element relative to its parent. Numbering starts from 1, this will be the first element in the list. expression Given as an+b , where a and b are integers, and n is a counter that automatically takes the value 0, 1, 2...

If a is zero, then it is not written and the entry is abbreviated to b . If b is zero, then it is also not specified and the expression is written in the form an . a and b can be negative numbers, in which case the plus sign changes to a minus sign, for example: 5n-1.

Through use negative values a and b some results may also come out negative or zero. However, elements are only affected by positive values ​​due to element numbering starting at 1.

In table 1 shows some possible expressions and keywords, and also indicates which element numbers will be used.

HTML5 CSS3 IE Cr Op Sa Fx

nth-child

21342135 213621372138
Oil1634 627457
Gold469 725647
Tree773 793486
Stones2334 8853103


In this example, the :nth-child pseudo-class is used to change the style of the first row of the table, as well as to highlight all even rows (Figure 1).

I think many people know about contextual selectors in CSS. They are used most often, however, experienced layout designers know very well that sometimes contextual selectors introduce certain problems. This problem is due to the fact that in the structure of an element there can be many identical elements nested within each other. And you need to apply the style not to all nested elements, but only to the immediate child element. This is what they are used for child selectors in CSS.

To make the problem clearer, let's give a small example. Let us have one like this HTML code:



First paragraph



Second paragraph


And our task is to make it red only " Second paragraph". If we write using a context selector:

Container p (
color:red;
}

Then both paragraphs will turn red, which we don’t need at all. This problem can be solved very easily using child selectors in CSS:

Container > p (
color:red;
}

That's it, now we only have red " Second paragraph". Since this particular paragraph is a direct child of .container. A " First paragraph" is a child of internal div, thus, it is not affected by the child selector.

This is how such problems are easily solved, however, there is one huge disadvantage child selectors in CSS- they do not work in browsers Internet Explorer. For this reason, their use is highly undesirable. But if you suddenly meet somewhere, now you will know what it means this type selectors and what it does.



tell friends