Home  >  Article  >  Web Front-end  >  A closer look at selectors in CSS

A closer look at selectors in CSS

青灯夜游
青灯夜游forward
2021-07-22 11:15:002609browse

This article will take you to understand the selectors in CSS, introduce the syntax of simple selectors, compound selectors, complex selectors, and selector priorities.

A closer look at selectors in CSS

Selector syntax

Let’s first understand the syntax of the selector, and then delve into the related background characteristics.

Simple selector

  • Asterisk —— *
    • Universal selector, you can select any element
  • Type selector|type selector —— div svg|a
    • is also called type selector, which means it selects the tagName (tag name) attribute in the element.
    • tagName is also our most commonly used selector
    • But because HTML also has namespaces, there are three main ones: HTML, SVG, MathML
    • If we If we want to select specific elements in SVG or MathML, we must use the single vertical bar |. The single vertical bar in the CSS selector is a namespace delimiter, and the namespace delimiter in HTML is Colon:. Then the namespace mentioned earlier needs to be declared by @namespace. They are used together, but this namespace is not used very frequently. It exists only for completeness. It is the only overlapping element between HTML and SVG. There is only one namea
    • so we can think that the type selector is just a simple text string
  • Class selector|class selector —— .class-name
    • The selector starting with . is the class selector, which is also one of the most classic.
    • It will select a class. We can also use spaces as separators to specify it. For multiple classes,
    • this.class only needs to match one of them
  • ID selector|id selector —— #id
    • Start with # and add the ID name to select an ID
    • This is a strict match
    • You can add minus signs or other symbols in the ID
  • Attribute selector|attribute selector —— [attr=value]
    • It includes the class attribute selector and id selector
    • The complete syntax of this selector is attr=value, which means the attribute name is in front and the attribute value is after.
    • You can add ~ before the equal sign here, which means that like class, it can support a sequence of values ​​separated by spaces: attr~=value
    • If you add a single vertical bar before the equal sign, it means that this attribute starts with this value: attr|=value
    • If we have no special requirements for priority, we Theoretically, attribute selectors can be used to replace class selectors and id selectors
  • pseudo-class —— :hover
    • Starting with :, it is mainly the special status of some attributes
    • This has nothing to do with the HTML we write, mostly from interaction and effects
    • Some pseudo-class selectors are pseudo-class selectors with functions, we can use pseudo-classes to solve these problems
  • Pseudo-element selector —— ::before
    • Generally speaking, that starts with a double colon
    • ::
    • actually supports the use of a single colon, but we advocate the writing method of double colon
    • Because we can see at a glance that this is a pseudo-element selector, which is distinguished from pseudo-classes
    • Pseudo-elements belong to selecting some elements that do not originally exist
    • If we do not select them, this This element no longer exists in the place, and there will be one more element after selection

Compound selector

  • * Or the div must be written at the front

First of all, a compound selector is composed of multiple simple selectors. As long as the simple selectors are written next to each other, it becomes a compound selector. Its semantics is that the element we select must match several simple selectors at the same time, forming an "AND" relationship.

Complex selector

You can use a connector in the middle of a compound selector to become a complex selector. Complex Selectors select based on the structure of an element.

  • —— Descendant selector, a single element must have a parent node or ancestor node to the left of the space
  • “>” —— Parent-child selector, must be the direct superior parent element of the element
  • “~” ——Adjacency Selector
  • “ ” ——Adjacency Selector
  • “||” —— Double vertical bars are only available in Selector Level 4. When we make a table, we can select each column

##Selector Priority

I have also been exposed to the concept of selector priority in the previous "Learning the Working Principles of Browsers in Actual Combat". Here we take a deeper look at the concept of selector priority.

Simple selector count

We start from a case, the selector priority is for all simple selectors contained in a selector Make a count. So the selector list is not considered a complete selector (that is, comma-separated selectors), because the middle of the selector list is comma-separated complex selectors for simple selector counting.

Example:

#id div.a#id

    This contains two ID selectors and a type selector And a class selector
  • according to the count of a
  • specificity array [number of inline-style,ID selector number,class Number of selectors,tagName Number of selectors]
  • In our example we will get
  • specificity = [0, 2, 1, 1]
  • In the selector standard, there is a description like this. We will use an N base to represent the selector priority
  • So
  • A closer look at selectors in CSS
  • We only need to take a large N and calculate it to be the priority of the selector
  • For example, we use
  • N=1000000##, then S=2000001000001 , this is the specificity priority of the selector in this example
Like the old version of IE IE6, because in order to save memory, the value of N is not large enough, a value of 255 is taken as N, so very interesting things happen, for example, the value of N is 256 class is equivalent to an ID. Later, most of our browsers chose 65536, and basically no more quotas were exceeded. Because the standard only says that a relatively large value can be used, but we have to consider the issue of temporary memory usage, so we will take a relatively integral number in hexadecimal, which is generally a whole power of 256 (because 256 is exactly one byte).

CSS pseudo-classPseudo-class is actually a simple selector for a very large number of contents.

Link/Action

  • :any-link —— Can match any hyperlink
  • :link —— Hyperlink that has not been visited yet
  • :link :visited —— Matches all visited hyperlinks
  • :hover —— The state after the user mouse is placed on the element, before It can only take effect on hyperlinks, but now it can be used in many elements.
  • :active - Previously it only took effect on hyperlinks. After clicking, the current link will Valid
  • :focus - This is the state of focus in this element. It is generally used for input tags. In fact, any element that can get focus can use
  • :target —— Link to the current target. This is not used for hyperlinks, but for the a tag of the anchor point. The current HASH points to the current a tag will activate the target pseudo-class

Once :link or :visited is used, we Properties other than the text color of this element can no longer be changed. Why is it designed this way? Because once we use layout-related attributes, for example, if we increase the size of :visited, it will affect scheduling. In this way, we can use the JavaScript API to get whether the link has been visited. But if we can get whether the link has been visited, then we can know which websites the user has visited, which is a fatal blow to the security of the browser. So here I would like to remind everyone, don’t think that making some expressive things has nothing to do with safety. In fact, safety is a comprehensive consideration. CSS can also cause security holes.

Tree structure

  • ##:empty —— Whether this element has child elements
  • :nth-child() —— Which child is the parent element?
  • :nth-last-child() — — Same as nth-child, except counting from back to front
  • :first-child :last-child :only-child

:nth-child is a very complex pseudo-class that supports a syntax. For example, you can write odd and even event or odd in brackets. , you can also write 4N 1, 3N-1, which will match the integer form respectively. Because this is a relatively complex selector, we don’t want to write overly complex expressions in it. We only use it to handle odd and even expressions, such as 1 more when there are 3, 1 more when 4, etc. .

In fact,

empty, nth-last-child, last-child, only-child These two selectors destroy the timing problem of CSS calculation that we mentioned in "Learning Browser Principles in Implementation". We can imagine that when we start label calculation, we definitely don't know whether it has sub-labels. empty The impact is not particularly large, but the relationship between last-child is actually quite influential. Therefore, browsing has done special processing when implementing these. Either the browser does not implement it particularly well, or the browser requires more performance to implement it. Therefore, it is recommended that you try to avoid using these in large quantities.

logical type

    :not pseudo-class - Mainstream browsers only support sequences of simple selectors (complex Selector) We have no way to write complex selector syntax in it
  • :where :has ——These two very powerful logical pseudo-classes have been added to CSS Level 4
Here is a warm suggestion to everyone,

It is not recommended that you write the selector too complicated, We can often add more classes to solve the problem. If our selector is written too complexly, it means that the HTML structure is unreasonable to some extent. We do this not only to save trouble for the browser project, nor for performance, but also for the sake of our own code structure, so we should not have overly complex selectors.

CSS pseudo elements

There are 4 types in total

    ::before
  • ::after
  • ::first-line
  • ::first-letter

::before and ::after inserts a pseudo element before and after the content of the element. Once the before and after attributes are applied, an attribute called content can be written in the declaration (general elements cannot write the content attribute). The attribute of content is just like a real DOM element. It can generate boxes and participate in subsequent typesetting and rendering. So we can declare attributes like border, background, etc. to him.

can be understood as:

The pseudo element adds a non-existent element to the interface. The mechanisms of

::first-line and ::first-letter are different. These two actually exist in content. As the name suggests, they select the "first row" and select the "first letter". They are not a non-existent element, they enclose a part of the text so that we can do some processing on it.

before and after

In our concept, we can think that the selector with the before pseudo-element will actually select it. An element is added in front of the element's content, and we only need to add text content to it through its content attribute. (Here we can also assign content: '' to the pseudo-element and it is empty) So we can specify the display attribute for before and after in any way, just like different elements.

When we implement some components, we often use this method to add some decorative content to the page in a way that does not pollute the DOM tree but can actually create visual effects.

<div>
  <::before/>
  content content content content
  content content content content
  content content content content
  content content content content
  <::after/>
</div>

first-letter and first-line

first-letter is equivalent to us having an element to put the content inside The first letter of is enclosed in brackets. This first-letter We can declare various attributes at will, but we cannot change its content. We should all have seen the effect that the first letter in a newspaper will be larger and then will float out. In CSS, we can use the ::first-letter pseudo-element selector. Using this to implement will be more stable and the code will be more elegant than using JavaScript.

<div>
  <::first-letter>c</::first-letter>ontent content content content
  content content content content
  content content content content
  content content content content
</div>

first-line is for line after typesetting. In fact, it has nothing to do with first line in our source code. If our browsers provide different rendering widths, first-line will ultimately enclose a different number of elements in the two environments. So when we use this selector, we need to use it according to the needs. It is very likely that the rendering effect on our development machine and the user's machine will be different!

<div>
  <::first-line>content content content content content</::first-line>
  content content content content
  content content content content
  content content content content
</div>

The available attributes of these two selectors are also different:

first-line available attributes

  • font series
  • color series
  • background series
  • word-spacing
  • letter- spacing
  • text-decoration
  • text-transform
  • line-height

##first-letter Available properties

    font Series
  • color Series
  • background Series
  • text-decoration
  • text-transform
  • letter-spacing
  • word-spacing
  • line-height
  • float
  • vertical-align
  • Box model Series: margin, padding, border

Small exercise

Write a match function. It accepts two parameters, the first parameter is a selector string property, and the second parameter is an HTML element. You can think of this element as it must be in a DOM tree. Use selectors and DOM elements to determine whether the current element can match our selector. (You cannot use any built-in browser functions, only use the DOM's parent and children APIs to determine whether an element can match a selector.) The following is an example of a call.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Match Example —— by 三钻</title>
  </head>
  <body>
    <div>
      <b>
        <div class="class classA" id="id">content</div>
      </b>
    </div>
  </body>
  <script language="javascript">
    /**
     * 匹配选择器
     */
    function matchSelectors(selector, element) {
      // 先匹配当前元素是否匹配
      let tagSelector = selector.match(/^[\w]+/gm);
      let idSelectors = selector.match(/(?<=#)([\w\d\-\_]+)/gm);
      let classSelectors = selector.match(/(?<=\.)([\w\d\-\_]+)/gm);

      /**
       * 实现复合选择器,实现支持空格的 Class 选择器
       * --------------------------------
       */
      // 检查 tag name 是否匹配
      if (tagSelector !== null) {
        if (element.tagName.toLowerCase() !== tagSelector[0]) return false;
      }
      // 检测 id 是否匹配
      if (idSelectors !== null) {
        let attr = element.attributes[&#39;id&#39;].value;
        if (attr) {
          for (let selector of idSelectors) {
            if (attr.split(&#39; &#39;).indexOf(selector) === -1) return false;
          }
        }
      }
      // 检测 class 是否匹配
      if (classSelectors !== null) {
        let attr = element.attributes[&#39;class&#39;].value;
        if (attr) {
          for (let selector of classSelectors) {
            if (attr.split(&#39; &#39;).indexOf(selector) === -1) return false;
          }
        }
      }

      return true;
    }

    /**
     * 匹配元素
     */
    function match(selector, element) {
      if (!selector || !element.attributes) return false;

      let selectors = selector.split(&#39; &#39;).reverse();

      if (!matchSelectors(selectors[0], element)) return false;

      let curElement = element;
      let matched = 1;

      // 递归寻找父级元素匹配
      while (curElement.parentElement !== null && matched < selectors.length) {
        curElement = curElement.parentElement;
        if (matchSelectors(selectors[matched], curElement)) matched++;
      }

      // 所有选择器匹配上为 匹配成功,否则是失败
      if (matched !== selectors.length) return false;

      return true;
    }

    let matchResult = match(&#39;div #id.class&#39;, document.getElementById(&#39;id&#39;));
    console.log(&#39;Match example by 三钻&#39;);
    console.log(&#39;matchResult&#39;, matchResult);
  </script>
</html>
For more programming related knowledge, please visit:

Programming Video! !

The above is the detailed content of A closer look at selectors in CSS. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:csdn.net. If there is any infringement, please contact admin@php.cn delete