This article will take you to understand the selectors in CSS, introduce the syntax of simple selectors, compound selectors, complex selectors, and selector priorities.
Let’s first understand the syntax of the selector, and then delve into the related background characteristics.
Simple selector
*
div svg|a
tagName
(tag name) attribute in the element. HTML
, SVG
, MathML
|
. 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
.class-name
.
is the class selector, which is also one of the most classic. .class
only needs to match one of them#id
# and add the ID name to select an ID[attr=value]
attr=value
, which means the attribute name is in front and the attribute value is after. ~
before the equal sign here, which means that like class, it can support a sequence of values separated by spaces: attr~=value
attr|=value
:hover
:
, it is mainly the special status of some attributes::before
that starts with a double colon Compound selector
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.
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
array [
number of inline-style,
ID selector number,
class Number of selectors,
tagName Number of selectors]
##, then S=2000001000001
, this is the specificity priority of the selector in this example
Link/Action Once Tree structure :nth-child empty logical type 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. ::before The pseudo element adds a non-existent element to the interface. The mechanisms of 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 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. first-letter and first-line The available attributes of these two selectors are also different: first-line available attributes ##first-letter Available properties Programming Video! !
: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 :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.
—— Whether this element has child elements
—— Which child is the parent element?
— — Same as
nth-child, except counting from back to front
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,
,
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.
:not pseudo-class - Mainstream browsers only support sequences of simple selectors (complex Selector) We have no way to write complex selector syntax in it
Here is a warm suggestion to everyone,
CSS pseudo elements
There are 4 types in total
::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:
::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. 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. <div>
<::before/>
content content content content
content content content content
content content content content
content content content content
<::after/>
</div>
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>
font Seriescolor Seriesbackground Seriestext-decorationtext-transformletter-spacingword-spacingline-heightfloatvertical-alignBox 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['id'].value;
if (attr) {
for (let selector of idSelectors) {
if (attr.split(' ').indexOf(selector) === -1) return false;
}
}
}
// 检测 class 是否匹配
if (classSelectors !== null) {
let attr = element.attributes['class'].value;
if (attr) {
for (let selector of classSelectors) {
if (attr.split(' ').indexOf(selector) === -1) return false;
}
}
}
return true;
}
/**
* 匹配元素
*/
function match(selector, element) {
if (!selector || !element.attributes) return false;
let selectors = selector.split(' ').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('div #id.class', document.getElementById('id'));
console.log('Match example by 三钻');
console.log('matchResult', matchResult);
</script>
</html>
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!