preface
The cause of the incident was a wechat message sent to me by a friend
Wondering what font has to do with data binding, I asked him to write a demo for me and he sent me a code file
Code simplification is as follows:
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Demo</title>
<style>
body {
font-size: 40px;
}
.time1 {
display: inline-block;
background: linear-gradient(to right, #a6ffcb, #1fa2ff);
-webkit-background-clip: text;
color: transparent;
}
</style>
</head>
<body>
<div id="app">
<div class="time1">{{ time }}</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
<script>
new Vue({
el: "#app".data: {
time: new Date().toLocaleString()
},
methods: {
updateTime() {
this.time = new Date().toLocaleString();
}
},
mounted() {
setInterval(this.updateTime, 1000); }});</script>
asdasd
</body>
</html>
Copy the code
Click to see the Live Demo
I found that the time did not change in the browser. When I commented out the color in the console, I found that the data had changed. I’m just going to try another gradient here
CSS text gradient some methods
Background property method
I’m not going to go into detail about this but it’s easy to understand if you look at the code above
Mask attribute method
<style>
.time2 {
position: relative;
color: #a6ffcb;
}
.time2:before {
content: attr(time);
position: absolute;
z-index: 10;
color: #1fa2ff;
-webkit-mask: linear-gradient(to left, #1fa2ff, transparent);
}
</style>
<div class="time2" time="time">I'm gradient text</div>
Copy the code
The selector:before
Inserts content in front of the selected element usingcontent
Property to specify what to insert.mask
Attributes let parts of an element be shown or hidden
-
Content value attr is what we use to get the value of the property. Content :attr
content: attr(time); You can get the time attribute of the element, here the time attribute is a custom attribute, arbitrary write
<h1 date="I'm gradient text.">I'm gradient text</h1> Copy the code
And then the content property looks like this: content: attr(date); It can also work.
-
The mask attribute allows the user to partially or completely hide the visible area of an element. This effect can be done by masking or cropping specific areas of the image.
Details can be found at developer.mozilla.org/zh-CN/docs/…
Go back to the original question
Let’s see if the other case doesn’t render
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Demo</title>
<style>
body {
font-size: 40px;
}
.time1 {
display: inline-block;
}
.time1 {
background: linear-gradient(to right, #a6ffcb, #1fa2ff);
-webkit-background-clip: text;
color: transparent;
}
.time2 {
position: relative;
color: #a6ffcb;
}
.time2:before {
content: attr(time);
position: absolute;
z-index: 10;
color: #1fa2ff;
-webkit-mask: linear-gradient(to left, #1fa2ff, transparent);
}
</style>
</head>
<body>
<div id="app">
<div class="time1">{{ time }}</div>
<div class="time2" :time="time">{{ time }}</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
<script>
new Vue({
el: "#app".data: {
time: new Date().toLocaleString()
},
methods: {
updateTime() {
this.time = new Date().toLocaleString();
}
},
mounted() {
setInterval(this.updateTime, 1000); }});</script>
</body>
</html>
Copy the code
Look at the effect
The look on my face
It occurred to me that the browser was rearranged and redrawn
Browser rearrangement and redrawing
So let’s talk about rearranging and redrawing
The browser compiles a page in five steps
- Process HTML to generate DOM (Document Object Model) Tree
- Generates the CSSOM (CSS Object Model) Tree
- The DOM tree is merged with the CSS-DOM tree into the Render tree
- Render tree layout calculation
- Walk through each node of the Render tree and draw to the screen
Redraw and rearrange concepts
When a DOM change affects the geometry of an element (width, height, etc.), the browser needs to recalculate the geometry of the element, and the geometry of other elements on the page may be affected. In this way, the rendering tree is changed. This process is called reflow.
If the DOM changes only affect non-geometric properties such as the background color, then it is repainted rather than rearranged because the layout has not changed
Changes in page layout and element geometry can lead to rearrangements
The following rearrangements will occur:
- Initial page rendering
- Add/remove visible DOM elements
- Change element position
- Change element dimensions (width, height, inside and outside margins, borders, etc.)
- Changing element content (text, images, etc.)
- Change window size
- The extent and extent of rearrangement will be different under different conditions
- In some cases, it even rearranges the entire page, such as sliding the scroll bar
- The following properties or methods refresh the render queue (offsetTop, offsetLeft, offsetWidth, offsetHeight clientTop, clientLeft, clientWidth, clientHeight) ScrollTop, scrollLeft, scrollWidth, scrollHeight getComputedStyle() (currentStyle in IE)
The problem
Here the text has changed, but the size of the text has not changed. I feel that there should be no trigger rearrangement so that the background color has not changed. Then I will try to change the length of the text
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Demo</title>
<style>
body {
font-size: 40px;
}
.time1 {
display: inline-block;
}
.time1 {
background: linear-gradient(to right, #a6ffcb, #1fa2ff);
-webkit-background-clip: text;
color: transparent;
}
.time2 {
position: relative;
color: #a6ffcb;
}
.time2:before {
content: attr(time);
position: absolute;
z-index: 10;
color: #1fa2ff;
-webkit-mask: linear-gradient(to left, #1fa2ff, transparent);
}
</style>
</head>
<body>
<div id="app">
<div class="time1">{{ time }}</div>
<div class="time2" :time="time">{{ time }}</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
<script>
new Vue({
el: "#app".data: {
time: new Date().toLocaleString(),
arr: [
"The Arcane Masters Of Great And Great."."It's a stupid thing to do."."Beat dud by the hour."."Oskara's Home wire-drawing machine Decaron."]},methods: {
updateTime() {
// this.time = new Date().toLocaleString();
this.time = this.arr[Math.floor(Math.random() * this.arr.length)];
}
},
mounted() {
setInterval(this.updateTime, 1000); }});</script>
</body>
</html>
Copy the code
Results the following
It turns out that the text length does not change, the first one will not be re-rendered, once the length changes, the first one will change the rendering, and the second one will always be rendered
The problem seemed to have suddenly found its cause, but I had no intention of discovering new problems
The new problem
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Demo</title>
<style>
body {
font-size: 40px;
}
.time1 {
display: inline-block;
}
.time1..time3 {
background: linear-gradient(to right, #a6ffcb, #1fa2ff);
-webkit-background-clip: text;
color: transparent;
}
.time2 {
position: relative;
color: #a6ffcb;
}
.time2:before {
content: attr(time);
position: absolute;
z-index: 10;
color: #1fa2ff;
-webkit-mask: linear-gradient(to left, #1fa2ff, transparent);
}
</style>
</head>
<body>
<div id="app">
<div class="time1">{{ time }}</div>
<div class="time2" :time="time">{{ time }}</div>
<div>
<span class="time3">{{ time }}</span>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
<script>
new Vue({
el: "#app".data: {
msg: "Hello".time: new Date().toLocaleString()
},
methods: {
updateTime() {
this.time = new Date().toLocaleString();
}
},
mounted() {
setInterval(this.updateTime, 1000); }});</script>
</body>
</html>
Copy the code
When I change the DOM structure, it’s fine
Results the following
Okay, I’m totally dumbfounded
The last
Finally I did not understand, hope to know the big guy to help answer.
But just to be on the safe side, use the second gradient.