The world of CSS selectors: mastering CSS selectors

The world of CSS selectors: mastering CSS selectors

CSS selectors currently have the following: descendant selector space (), sub-selector arrow (>), adjacent sibling selector plus (+), subsequent sibling selector Wanwan (~), and column selector double Pipe (||). For the first four selectors, the browser supports them earlier and is very practical, which is the focus of this chapter. The last column selector is considered "upstart", which is closely related to the layout of Table and other layouts, but the current browser compatibility is not enough to make it practically used, so I will briefly introduce it.

4.1 Descendant selector space ()

The descendant selector is a very commonly used selector. You can see this selector by grabbing an online CSS file. It has been supported since the IE6 era. But even if I see it every day, I don t necessarily understand it very well.

4.1.1 Understanding of possible errors in CSS descendant selectors

Looking at this example, the HTML and CSS codes are as follows:

<div class="lightblue"> <div class="darkblue"> <p>1. What is the color? </p> </div> </div> <div class="darkblue"> <div class="lightblue"> <p>2. What is the color? </p> </div> </div> .lightblue {color: lightblue;} .darkblue {color: darkblue;} Copy code

What is the color of the text?

This problem is relatively simple, because color has inheritance characteristics, so the color of the text is determined by the darkest color element of the DOM, so the colors of 1 and 2 are dark blue and light blue, respectively, as shown in Figure 4-1.

 

Figure 4-1 Type selector and text color

This example is equipped with a demo page, readers can manually enter
demo.cssworld.cn/selector/4/...

However, if the class selector here is replaced with a descendant selector, it is not that simple, and many people will mistake the final text color:

<div class="lightblue"> <div class="darkblue"> <p>1. What is the color? </p> </div> </div> <div class="darkblue"> <div class="lightblue"> <p>2. What is the color? </p> </div> </div> .lightblue p {color: lightblue;} .darkblue p {color: darkblue;} Copy code

In the early years, I used this question as an interview question. The whole army was wiped out. No one answered it correctly. Everyone thought the result was dark blue and light blue. In fact, it was not. The correct answer is that all 1 and 2 are dark blue, such as As shown in Figure 4-2.

 

Figure 4-2 Descendant selector and text color

The reason why many people get it wrong is that they have a wrong understanding of descendant selectors. When the descendant selectors are included, the priority of the entire selector has nothing to do with the DOM level of the ancestor element. At this time, it depends on the landing element. priority. In this case, the landing element is the last <p> element. The two <p> elements are separated from each other and are not nested, so the DOM hierarchy is parallel and there is no order; looking at the priority of the selector, .lightblue p and .darkblue p are a class selector (value 10) and a label selector (Value 1), the calculated value of the selector priority is the same; at this time, it depends on their position in the CSS file, and follows the "later-to-top" rule. Since .darkblue p is more recent, therefore, <p> is always in accordance with color:darkblue performs color rendering, so the final text colors of 1 and 2 are all dark blue.

Readers can manually enter
demo.cssworld.cn/selector/4/...

It's a bit counter-intuitive, everyone can think about it, digest it.

If you feel that you have understood it, you can take a look at the following two CSS statements, which can be regarded as a quiz.

Example 1 : What are the text colors of 1 and 2 at this time?

:not(.darkblue) p {color: lightblue;} .darkblue p {color: darkblue;} Copy code

Answer: The text colors of 1 and 2 are also darkblue (dark blue). Because the priority of :not() itself is 0 (see Chapter 2 for details), the priority calculation values of :not(.darkblue) p and .darkblue p are the same, following the "later to top" rule, .darkblue p It is located at the back, so the text colors of 1 and 2 are both dark blue.

Example 2 : What are the text colors of 1 and 2 at this time?

.lightblue.lightblue p {color: lightblue;} .darkblue p {color: darkblue;} Copy code

Answer: The text colors of 1 and 2 are both lightblue (light blue). Because the selector.lightblue.lightblue p has a higher priority.

4.1.2 Understanding of possible errors in descendant selectors in JavaScript

Looking directly at the example, the HTML is as follows:

<div id="myId"> <div class="lonely">Single like me</div> <div class="outer"> <div class="inner">Bloom inside and outside</div> </div> </div> Copy code

Next, use JavaScript and descendant selectors to get elements. The output results of the following two lines of statements are:

//1. What is the length? document.querySelectorAll('#myId div div').length; //2. What is the length? document.querySelector('#myId').querySelectorAll('div div').length; Copy code

Many people would think that the length returned by these two statements is 1, but in fact they are not. The length values they return are 1 and 3 respectively!

Figure 4-3 is the result of my test in the browser console.

Figure 4-3 The length of the element obtained by the JavaScript descendant selector

The first result is in line with our understanding and is not explained. Why is the length of the NodeList returned by the next statement 3?

In fact, this is very easy to explain, one sentence: CSS selector is independent of the entire page!

What does that mean? For example, if you write in a deep DOM element on the page:

<style> div div {} </style> Copy code

The entire web page, including the parent, as long as it is an element that satisfies the descendant relationship of div div, all elements will be selected, right, everyone knows this.

The selector in querySelectorAll is also a global feature. document.querySelector('#myId').querySelectorAll('div div') translates to: query the child elements of the #myId element, and select all DOM elements that also meet the div div selector conditions under the entire page.

At this point, if we take a closer look at the original HTML structure, we will find that in the global view, div.lonely, div.outer, and div.inner all meet the selector condition of div div, so the final returned length is 3. If we output all NodeLists in the browser console, this is also the result:

NodeList (3) [div.lonely, div.outer , div.inner] copy the code

This is the wrong understanding of the descendant selectors in JavaScript.

In fact, if the selector behind querySelectorAll is not a global match, there is a way. You can use the :scope pseudo-class, whose function is to limit the scope of the CSS selector to a certain range. For example, you can change the above example to the following:

//3. What is the length? document.querySelector('#myId').querySelectorAll(':scope div div').length; Copy code

The final result is 1, as shown in Figure 4-4.

 

Figure 4-4: The length of the elements obtained under the scope pseudo-class

For more information about the :scope pseudo-class, see Chapter 12.

4.2 Sub-selector arrow (>)

The sub-selector is also a very commonly used and very important selector. IE7 browsers start to support it, and the space of the descendant selector is a bit "distant relative".

4.2.1 The difference between sub-selectors and descendant selectors

The child selector will only match the first generation of child elements, while the descendant selector will match all child elements.

Looking at an example, the HTML structure is as follows:

<ol> <li>What is the color? </li> <li>What is the color? <ul> <li>What is the color? </li> <li>What is the color? </li> </ul> </li> <li>What is the color? </li> </ol> Copy code

The CSS is as follows:

ol li { color: darkblue; text-decoration: underline; } ol> li { color: lightblue; text-decoration: underline wavy; } Copy code

Since the text-decoration attribute values of different parent and child elements will continue to accumulate, we can accurately determine the scope of different selectors based on the type of underscore. The final result is shown in Figure 4-5.

 

Figure 4-5 Screenshot of the test results of sub-selectors and descendant selectors

It can be seen that the underlines of all the outer texts are only of wave type, while the underlines of the inner text are a mixed type of solid lines and wavy lines. The solid underline is generated by the text-decoration:underline statement in the ol li selector, and the wavy underline is generated by the text-decoration:underline wavy statement in the ol>li selector. This means that ol>li can only Acts on the current child <li> element, and ol li can act on all descendant <li> elements.

The above is the difference between these two selectors. The matching range of explicit sub-selectors is wider than that of sub-selectors. Therefore, under the same selector, the matching performance of sub-selectors is better than that of descendant selectors. However, the value of this performance advantage is limited and has almost no meaning, so it cannot be used as a priority condition for the selection of selector technology.

Figure 4-5 is equipped with a demo page, readers can manually enter
demo.cssworld.cn/selector/4/...

4.2.2 Scenarios suitable for sub-selectors

If you don't need sub-selectors, try not to use them as much as possible. Although its performance is better than the subsequent generations of selectors, it is not worth mentioning compared with the maintenance cost that it will bring in the future.

For example, there is a module container whose class name is .cs-module-x. There are some differences between the styles of this module in area A and area B, and it needs to be reset. Our usual practice is to rename the outer element of the container. The class is reset, such as .cs-module-reset-b. At this time, many developers (without thinking too much) use sub-selectors:

.cs-module-reset-b> .cs-module-x { width: fit-content; } Copy code

As someone who has come, I suggest you use descendant selectors instead:

/* Suggest*/ .cs-module-reset-b .cs-module-x { position: absolute; } Copy code

Because once the sub-selector is used, the hierarchical relationship of the elements is forcibly bound. When the hierarchical relationship needs to be maintained or changed in the future, once the hierarchical relationship is adjusted, the entire style becomes invalid. At this time, the CSS code must be adjusted synchronously. , Increased maintenance costs.

Remember: the main purpose of using sub-selectors is to avoid conflicts. In this example, there can be no more .cs-module-x inside the .cs-module-x container, so there will never be conflicts when using descendant selectors, but it will make the structure more flexible, even if it is nested in the future A layer of labels will not affect the layout.

The following scenarios are suitable for using sub-selectors.

(1) State class name control. For example, if you use the .active class name to switch states, you will encounter scenarios where both ancestors and descendants have .active switching. At this time, the sub-selector is necessary to avoid affecting the descendant elements, for example:

.active> .cs-module-x { display: block; } Copy code

(2) The label is restricted. For example, when the <li> tag is repeatedly nested, and we cannot modify the tag name or set the class name (such as third-party widgets in WordPress), we need to use sub-selectors for precise control.

.widget> li {} .widget> li li {} Copy code

(3) Level location and dynamic judgment. For example, the HTML of a time selection component is usually placed under the <body> element, as a child element of the <body>, and presented in the form of an absolutely positioned floating layer. But sometimes it needs to be embedded in a certain position of the page with a static layout. At this time, if we are not convenient to modify the component source code, we can quickly apply a patch with the help of sub-selectors:

:not(body)> .cs-date-panel-x { position: relative; } Copy code

It means to cancel the absolute positioning when the component container is not a <body> child element.

The sub-selector is a double-edged sword. It makes the structure more stable by restricting the relationship, but at the same time it loses its flexibility and change, and needs to be used carefully.

4.3 Adjacent sibling selector plus sign (+)

The adjacent sibling selector is also a very practical selector, which is supported by browsers of IE7 and above. It can be used to select adjacent sibling elements, but only the next sibling can be selected. We will quickly understand the adjacent brother selector through a simple example, the HTML and CSS are as follows:

<ol> <li>1. What is the color? </li> <li class="cs-li">2. What is the color? </li> <li>3. What is the color? </li> <li>4. What is the color? </li> </ol> .cs-li + li { color: skyblue; } Copy code

The result is shown in Figure 4-6.

Figure 4-6 Screenshot of the test result of adjacent brother selector

As you can see, the color of the next <li> after .cs-li has become sky blue, and the result is in line with our expectations, because .cs-li+li means to select the next one next to the .cs-li element and the label is The element of li. If the selector here is .cs-li+p, no element will be selected, because .cs-li is followed by a <li> element, not a <p> element.

Readers can manually enter
demo.cssworld.cn/selector/4/...

4.3.1 Details about the adjacent sibling selector

In actual development, our HTML is not necessarily neat and tidy label elements. At this time, how should the adjacent sibling selectors behave?

1. Text node and adjacent sibling selector

The CSS is simple:

h4 + p { color: skyblue; } Copy code

Then we insert some text between the <h4> and <p> elements to see if the color of the <p> element is still sky blue?

<h4>1. Text node</h4> There is a space between characters, what is the color? <p>If its color is sky blue, it means that the adjacent sibling selector ignores the text node. </p> Copy code

The result is shown in Figure 4-7. The color of the <p> element is still sky blue, which shows that the adjacent sibling selector ignores the text node.

 

Figure 4-7 A screenshot of the effect of ignoring text nodes by the adjacent sibling selector

2. Comment node and adjacent sibling selector

The CSS is simple:

h4 + p { color: skyblue; } Copy code

Then we insert a comment between the <h4> and <p> elements to see if the color of the <p> element is still sky blue?

<h4>2. Comment node</h4> <!-- There is a comment interval in the middle, what is the color? --> <p>If its color is sky blue, it means that the adjacent sibling selector ignores the comment node. </p> Copy code

The result is shown in Figure 4-8. The color of the <p> element is still sky blue, indicating that the adjacent sibling selector ignores the comment node.

 

Figure 4-8 A screenshot of the effect of ignoring comment nodes by adjacent sibling selectors

From this, we can get more detailed knowledge about the adjacent sibling selector, that is, the adjacent sibling selector will ignore the text node and the comment node, and only recognize the element node.

Both are equipped with test examples demonstrate the page, readers can manually enter
demo.cssworld.cn/selector/ 4/3-2.php to experience and learn.

4.3.2 Achieve similar: first-child effect

The adjacent sibling selector can be used to achieve a similar effect: first-child.

For example, we hope that all lists except the first list have margin-top attribute values. The first thought is the :first-child pseudo-class. If you don't need to be compatible with the IE8 browser, you can implement it like this:

.cs-li:not(:first-child) {margin-top: 1em; } Copy code

If you need to be compatible with the IE8 browser, you can handle it separately:

.cs-li {margin-top: 1em;} .cs-li:first-child {margin-top: 0;} Copy code

Here is another method, which is to use the adjacent sibling selector, as follows:

.cs-li + .cs-li {margin-top: 1em; } Copy code

Since the adjacent sibling selector can only match the next element, the first element will fail and will never be matched, so the matching of non-first list elements is naturally achieved.

In fact, this method is more applicable than :first-child. For example, when the first child element of the container is not .cs-li, the adjacent sibling selector is still valid, but :first- The child is invalid at this time, because no .cs-li element is the first child element, and it cannot match: first-child. To speak with facts, there is the following HTML:

<div class="cs-g1"> <h4>Use: first-child implementation</h4> <p class="cs-li">List content 1</p> <p class="cs-li">List content 2</p> <p class="cs-li">List content 3</p> </div> <div class="cs-g2"> <h4>Use adjacent sibling selector to achieve</h4> <p class="cs-li">List content 1</p> <p class="cs-li">List content 2</p> <p class="cs-li">List content 3</p> </div> Copy code

The .cs-li in .cs-g1 and .cs-g2 are implemented in different ways, as follows:

.cs-g1 .cs-li:not(:first-child) { color: skyblue; } .cs-g2 .cs-li + .cs-li { color: skyblue; } Copy code

The comparison test results are shown in Figure 4-9.

 

Figure 4-9 Comparison of test results obtained by using: first-child and adjacent sibling selectors

It can be clearly seen that the color of the first list element of the method implemented by the adjacent sibling selector is still black instead of sky blue, indicating that the non-first list element is correctly matched, and all the list elements of :first-child are sky blue Color, the match failed. It can be seen that the applicability of the adjacent sibling selector is wider.

Readers can manually enter
demo.cssworld.cn/selector/4/...

4.3.3 The core of many advanced selector technologies

The hardest application of neighboring brothers' selectors is to cooperate with many pseudo-types to achieve many practical interactive effects at low cost, which is the core of many advanced selector technologies.

For a simple example, when we focus on the input box, if we want to display the prompt text behind, we can easily implement it with the help of the adjacent brother selector. The principle is very simple. The prompt text is buried behind the input box in advance, when the trigger When the focus is active, just let the prompt text display, the HTML and CSS are as follows:

Username: <input><span class="cs-tips">no more than 10 characters</span> .cs-tips { color: gray; margin-left: 15px; position: absolute; visibility: hidden; } :focus + .cs-tips { visibility: visible; } Copy code

No JavaScript code is required. The effect is shown in Figure 4-10. The above picture is the effect picture when out of focus, and the picture below is the effect picture when in focus.

 

Figure 4-10 Effect picture when out of focus and focus

Readers can manually enter
demo.cssworld.cn/selector/4/...

This is just to start with, please refer to Chapter 9 for more exciting applications.

4.4 Then the brothers choose Fu Wanwan (~)

Subsequently, the compatibility of the sibling selector and the neighboring sibling selector is the same. Both are supported from the IE7 browser and can be used with confidence. The practicability and importance of the two are similar. In short, their relationship is relatively close, a bit of a distant relative.

4.4.1 Difference from adjacent sibling selector

The adjacent sibling selector will only match the first sibling element after it, and the subsequent sibling selector will match all the sibling elements after it.

Looking at an example, the HTML structure is as follows:

<p class="cs-li">List content 1</p> <h4 class="cs-h">Title</h4> <p class="cs-li">List content 2</p> <p class="cs-li">List content 3</p> Copy code

The CSS is as follows:

.cs-h ~ .cs-li { color: skyblue; text-decoration: underline; } .cs-h + .cs-li { text-decoration: underline wavy; } Copy code

The final result is shown in Figure 4-11.

Figure 4-11 Comparison of test results between adjacent sibling selector and subsequent sibling selector

You can see that the text color of all .cs-li elements behind .cs-h has changed to sky blue, but only the first .cs-li element behind has a wavy line. This is the difference between the adjacent sibling selector and the subsequent sibling selector, matching one and matching all the following elements.

Therefore, under the same selector condition, the performance of adjacent sibling selectors is higher than that of subsequent sibling selectors. However, in CSS, there is no certain order of magnitude. It is meaningless to talk about the performance of selectors. Therefore, regarding performance The powerful family can be bearish.

As for other details, the two are similar. For example, the sibling selector will also ignore the text node and the comment node later.

Readers can manually enter
demo.cssworld.cn/selector/4/...

4.4.2 Why is there no previous sibling selector?

We can see that whether it is the adjacent sibling selector or the subsequent sibling selector, they can only select the following elements. When I first met these two selectors, there was a question: why there is no previous sibling Selector?

Later, I realized that the reason for the absence of the previous sibling selector and the absence of the parent element selector is the same, and they are both subject to the DOM rendering rules.

The browser parses the HTML document from the front to the back, from the outside to the inside, so we often see the page head first and then the main content.

However, if CSS supports the previous sibling selector or parent element selector, you must wait for all child elements of the page to be loaded before rendering the HTML document. Because the so-called "front brother selector" means that the latter DOM element affects the previous DOM element. If the latter element has not been loaded and processed, how can it affect the style of the previous element? If CSS really supports such selectors, the rendering speed of web pages will inevitably slow down greatly, and the browser will have a long whiteboard, which will cause a bad experience.

Someone might say, is it still mandatory to adopt the strategy of rendering wherever it is loaded? Doing so will cause a bigger problem, because when loading the following elements, the rendered style of the previous element will suddenly become another style, which will also cause a bad experience and trigger Intense rearrangement and redrawing.

In fact, the specification document now has a pseudo-class: has can achieve the effect similar to the parent selector and the previous selector, and this pseudo-class was proposed in 2013, but after so many years, there is still no browser to achieve related functions . In my opinion, even after another 5 to 10 years, the possibility of CSS supporting the "front brother selector" or "parent selector" is very low. This is not because the possibility of implementation is low at the technical level, but CSS And the rendering mechanism of HTML itself determines this result.

4.4.3 How to achieve the effect of the previous brother selector

But when we are actually developing, there are indeed many scenes that need to control the previous sibling elements. What should we do at this time?

The sibling selector can only select the following elements, but this "behind" only refers to the back of the code level, not the back of the visual level. In other words, if we want to achieve the effect of the previous brother selector, we can still put the relevant code of this "front element" at the back, but visually present it in the front.

There are many ways to achieve inconsistency between DOM position and visual position. Common ones such as float and absolute positioning. All CSS properties with positioning characteristics (such as margin, left/top/right/bottom, and transform) can also be implemented. A more advanced point is to use direction or writing-mode to change the document flow order. On the mobile side, we can also use Flex layout, which can help us more flexibly control the position of DOM elements.

Use examples to speak. For example, when we want to focus on the input box, the previous description text "Username" is also highlighted, as shown in Figure 4-12.

 

Figure 4-12 The input box is focused and the text in front is highlighted.

Here are four different ways to achieve the effect of the previous brother selector here.

(1) Flex layout realization. There is a property called flex-direction in the Flex layout, which can control the order in which the elements are presented in the horizontal or vertical direction.

The HTML and CSS codes are as follows:

<div class="cs-flex"> <input class="cs-input"><label class="cs-label">User name:</label> </div> .cs-flex { display: inline-flex; flex-direction: row-reverse; } .cs-input { width: 200px; } .cs-label { width: 64px; } :focus ~ .cs-label { color: darkblue; text-shadow: 0 0 1px; } Copy code

This method mainly uses
flex-direction:row-reverse to change the horizontal presentation order of elements to realize the difference between the DOM position and the visual position. This method is simple to use, convenient and fast, and the only problem is compatibility. The user group is external users' desktop website projects with caution, and the mobile terminal is no problem.

(2) Float floating realization. The position can be swapped by letting the front <input> input box float to the right.

The HTML and CSS codes are as follows:

<div class="cs-float"> <input class="cs-input"><label class="cs-label">User name:</label> </div> .cs-float { width: 264px; } .cs-input { float: right; width: 200px; } .cs-label { display: block; overflow: hidden; } :focus ~ .cs-label { color: darkblue; text-shadow: 0 0 1px; } Copy code

The compatibility of this method is excellent, but there are still shortcomings. 1. the width of the container needs to be calculated based on the width of the child element. Of course, if it is not compatible with IE8, there is no such problem if it is calculated with calc(); secondly, multiple elements cannot be implemented. The effect of the selector in front of, this one is fatal.

(3) Absolute absolute positioning is realized. This is easy to understand, just position the back <label> absolutely to the front.

The HTML and CSS codes are as follows:

<div class="cs-absolute"> <input class="cs-input"><label class="cs-label">User name:</label> </div> .cs-absolute { width: 264px; position: relative; } .cs-input { width: 200px; margin-left: 64px; } .cs-label { position: absolute; left: 0; } :focus ~ .cs-label { color: darkblue; text-shadow: 0 0 1px; } Copy code

This method is compatible and easy to understand. The disadvantage is that when there are more elements, the control cost is higher.

(4) Realization of the direction attribute. With the help of the direction attribute to change the order of the document flow, the DOM position and the visual position can be exchanged easily.

The HTML and CSS codes are as follows:

<div class="cs-direction"> <input class="cs-input"><label class="cs-label">User name:</label> </div> /* The order of the horizontal document flow is changed from right to left*/ .cs-direction { direction: rtl; } /* Horizontal document flow order restoration*/ .cs-direction .cs-label, .cs-direction .cs-input { direction: ltr; } .cs-label { display: inline-block; } :focus ~ .cs-label { color: darkblue; text-shadow: 0 0 1px; } Copy code

This method can completely change the horizontal presentation position of any number of inline elements, the compatibility is very good, and it is easy to understand. The only downside is that it must target inline elements. Fortunately, the text and input boxes in this case are inline elements, which are more suitable.

To summarize these four methods roughly, the Flex method is suitable for multi-element and block-level elements, and has certain compatibility issues; the direction method is also suitable for multi-element and inline elements, and there is no compatibility problem. Because block-level elements can also be set to internal Therefore, the direction method is theoretically an ultimate solution; although the float method and the absolute method are more suitable for novice development and there is no compatibility problem, they are not suitable for multiple elements and are more suitable for two-element scenarios. You can choose the appropriate method according to the actual scene of your project.

Of course, more than the above 4 methods, we can also achieve similar effects with a margin positioning, and we will not expand them one by one here.

The above 4 methods are equipped with demo pages, readers can manually enter
demo.cssworld.cn/selector/4/...

4.5 Quickly understand the column selector double pipe (||)

The column selector is a new selector that has just appeared in the specification. The current browser compatibility is not enough for it to be used in actual projects, so I will only briefly introduce it to let everyone know what it is used for.

Both Table layout and Grid layout have the concept of columns. Sometimes we want to control the style of the entire column. There are two methods: one is with the help of: nth-col() or: nth-last-col() pseudo-classes, but currently The browser does not yet support these two pseudo-classes; the other is achieved by using the <colgroup> and <col> elements in the native Table layout. This method is very compatible.

Let's quickly understand these two elements through a simple example. For example, the HTML code of the table is as follows:

<table border="1" width="600"> <colgroup> <col> <col span="2" class="ancestor"> <col span="2" class="brother"> </colgroup> <tr> <td> </td> <th scope="col">Descendant selector</th> <th scope="col">Sub selector</th> <th scope="col">adjacent sibling selector</th> <th scope="col">The subsequent brother selector</th> </tr> <tr> <th scope="row">Example</th> <td>.foo .bar {}</td> <td>.foo> .bar {}</td> <td>.foo + .bar {}</td> <td>.foo ~ .bar {}</td> </tr> </table> Copy code

It can be seen that the table has 5 columns. Among them, there are three <col> elements in the <colgroup> element. As can be seen from the span attribute value, these three <col> elements occupy 1, 2 and 2 columns respectively. At this point, we set the background color for the next two <col> elements, and we can see that the background color is applied to the entire column. The CSS is as follows:

.ancestor { background-color: dodgerblue; } .brother { background-color: skyblue; } Copy code

The final effect is shown in Figure 4-13.

 

Figure 4-13 The entire column style control in the table

But sometimes our cells do not belong to a certain column, but cross columns. At this time, the <col> element will ignore these cross-column elements. for example:

<table border="1" width="200"> <colgroup> <col span="2"> <col class="selected"> </colgroup> <tbody> <tr> <td>A</td> <td>B</td> <td>C</td> </tr> <tr> <td colspan="2">D</td> <td>E</td> </tr> <tr> <td>F</td> <td colspan="2">G</td> </tr> </tbody> </table> col.selected { background-color: skyblue; } Copy code

At this time, only cells C and E have a sky blue background color. Although cell G also covers the third column, it is also ignored because it also belongs to the second column. The effect is shown in Figure 4-14. Show.

 

Figure 4-14 Cell G has no background color

This is a problem. In many cases, we just want the G cell to have a background color. As long as the column is included, it is considered to be the target object. In response to this demand, column selectors came into being.

The column selector is written as a double pipe (||), which is two characters, which is consistent with the writing of logical or in the JavaScript language. However, it does not mean "or" in CSS. It is more appropriate to use "belonging" to explain.

Through the following CSS selector, you can make G cell also have a background color:

col.selected || td { background-color: skyblue; } Copy code

The meaning of col.selected || td is to select all <td> elements belonging to col.selected, even if this <td> element spans multiple columns.

Then, you can see the effect shown in Figure 4-15.

 

Figure 4-15 Cell G has a background color

This article is excerpted from "CSS Selector World"

 

This is a CSS advanced book, which is very suitable for front-end personnel with a certain CSS foundation to learn and refer to. It will be a bit difficult for novices to read, because in order to achieve concise content, the book will directly omit too basic knowledge.

This book incorporates a lot of my personal understanding, which is the product of my personal emotional retouching and cognitive refinement after years of persistent research and thinking on CSS. Therefore, compared with dry, dogmatic technical books, this book should be easier to understand, warm, and more humanistic. However, personal understanding is not guaranteed to be 100% correct. Therefore, individual opinions in this book may also be incorrect. Readers are welcome to question and challenge.

Since the specifications have not been finalized, some of the more cutting-edge knowledge points in this book will undergo some minor changes in the future. I will follow up in real time and update them in the official forum.