Introduction to skeleton Screen

When the page is not finished loading, in order to give users a better experience, the easiest solution to think of is to display a progress bar or loading on the page to tell users that the page is not dead, but is still loading, so as to appease them. This may seem like a small thing, but it’s quite important, especially in China, perhaps because there’s so much choice and it seems like our users are demanding more from the page experience. Today, I would like to introduce a better way to improve the experience compared with the progress bar and loading. The progress bar and loading of skeleton screen are used to appease users, but you cannot make users feel that the page is loading faster if the page is slow or not. So in order to make your page stand out from the crowd, you need to make your page load faster. The skeleton screen solves this problem, but the skeleton screen solution doesn’t actually make pages load faster, it makes them feel faster. Luke Wroblewski, a Product director at Google, first proposed the concept of a skeleton screen in 2013. He defined it this way — a skeleton screen is a blank version of a page that contains text or a basic outline of an element through which information is conveyed. Our page is gradually loading. In 2015, Facebook introduced skeleton screens in their mobile apps, and Twitter, Medium, and YouTube all added skeleton screens to their product designs. Skeleton screens became a new trend for first-screen loading. You can now open jingdong mini program to see if the home page is like this – this is the skeleton screen

Implementation scheme

There are many implementations, all of which have one goal: to insert an HTML fragment of the skeleton screen under one of the root nodes of the page, and then replace the skeleton screen when the page loads. Here are a few options

1. Use images, SVG, or manually write skeleton screen HTML fragments

This approach was straightforward, but it was obvious that every time we had to redesign the skeleton screen, it was a bit clunky, whether it was to design images or to use our hand-written HTML.

2. Generate the skeleton screen using Vue server rendering

This way is better than the first way, not much different from the first way in nature. The main idea is to use the vue-server-renderer plugin, which is originally used for server-side rendering, and its basic use of reference documentation. The solution is to use the plugin to render the.vue file as an.html file, which is then manually copied into the root node #app to create a skeleton screen that will be replaced when the page is rendered. However, this scheme still requires us to implement the.vue file, which has the same problem as scheme 1, except that we can use the.vue file to write the skeleton screen, which is relatively convenient, but the problem is also obvious, this scheme is only suitable for vUE projects.

3. Automatic injection of skeleton panel

On the basis of scheme 2, webpack is used to realize the automatic injection of skeleton screen. The simple implementation can refer to the skeleton screen injection practice of Vue page, and the more mature scheme can refer to adding skeleton screen for Vue project. However, this solution still requires us to manually implement the corresponding skeleton screen page, and it can only be used in the Vue project, it would be nice to be able to automatically generate skeleton screen from the page.

4. The scheme of automatically generating skeleton screen

The Ele. me team has implemented such a solution and opened source a plugin, but for some reason this plugin seems to have not been maintained for a long time, please refer to page-skeleton-webpack-plugin. The author tried a wave, the feeling pit is also more, too lazy to solve. Later, I found a more ingenious design scheme — automatic generation scheme of web skeleton screen (DPS). This scheme draws on the implementation of Ele. me and also implements a plug-in. Although it is much simplified, it fully meets the needs in use. The basic principle is simply as follows: Walk through the VISIBLE DOM nodes in the visible area and obtain their width, height and location. Then use this data to generate a skeleton screen. Finally, Puppeteer, Google’s headLesschrome tool, is used to fully automate the skeleton screen. The only downside is that there is no support for setting skeleton screens for different routes on a single page, only one of them (my project is multi-page, so it works perfectly). Here is an example of how to use the plug-in.

Case introduced

I’ll use a Vue project as an example.

  1. First install the draw-Page-structure globally, which relies on Puppeteer, so it may be a bit slow.
npm i draw-page-structure -g
Copy the code
  1. After the installation is complete, go to the project directory and run the command
  • DPS init is going to run and it’s going to ask you to type in the address of the page that you want to generate the skeleton screen and the address of the.html file that you want to insert into the final skeleton screen HTML fragment, and the address of the.html file in this case is going to be the absolute path.

    A successful command will generate the dps.config.js file in the current directory, which is the basic configuration used to generate the skeleton screen.

  • The DPS start command starts the headless browser, which executes the script to read the dps.config.js configuration, and then generates an HTML fragment that is automatically inserted into the appropriate.html file. Run the project and open the browser, and you’ll see that the skeleton screen appears before the page loads.

  1. This section describes the dps.config.js configuration file
const dpsConfig = {
	url: 'http://www.baidu.com'.// To generate the skeleton screen page address, use Baidu (https://baidu.com) can also try
	output: {
	    filepath: ' '.// Generate skeleton screen storage page, generally for the project entrance page
	    injectSelector: '#app'  // The generated skeleton screen is inserted into the node of the page
	},
	// header: {
	// height: 40,
	// background: '#1b9af4'
	// },
	// Background: '#eee', // The background color of each node in the generated skeleton diagram
	// animation: 'opacity 1s linear infinite; ',
	// includeElement: function(node, draw) {
		// Customize what a node looks like with return false
		// if(node.id == 'ui-alert') {
			// Skip this node and its children
			// return false;
		// }
		// if(node.tagName.toLowerCase() === 'img') {
			// draw({
				// width: 100,
				// height: 8,
				// left: 0,
				// top: 0,
				// zIndex: 99999999,
				// background: 'red'
			// });
			// return false;
		// } 
	// },
	// writePageStructure: function(html) {
		// Handle the generated skeleton screen yourself
		// fs.writeFileSync(filepath, html);
		// console.log(html)
	// },
	init: function() {
		// Generate skeleton screen before the operation, such as removing interference nodes}}module.exports = dpsConfig;
Copy the code

This configuration is basically enough to generate a pretty good skeleton screen. If we have special requirements for the skeleton screen, we can use the includeElement, which takes a DOM object as its first argument and a method that points to the drawBlock method inside the plug-in. Used to generate a color block. At the same time, the plugin exposes the following methods, which can be called directly in the includeElement method (init, writePageStructure)

  • GetRect (node) returns {w,h,t,l}, indicating width, height, top, left, respectively
  • WPercent (x) Returns the percentage of the node width to the total width
  • HPercent (y) Returns the percentage of the node height in the total height
  • GetStyle (node,attr) returns: the attribute value of the node

For example, set the border-radius of all nodes whose className is img-icon to 50%

includeElement: function(node, ) {
    if (node.className.indexOf('img-icon')! = =- 1) {
        const {t, l, w, h} = getRect(node);
        draw({
            width: wPercent(w), 
            height: hPercent(h), 
            top: hPercent(t), 
            left: wPercent(l),
            radius:'50%'   // This is radius, not boderRadius
        });
        return false; }}Copy the code

If you want to implement HTML fragments of your skeleton diagram yourself, you can use the writePageStructure method, which I think is a little bit redundant, and some of the nodes that you’re not going to use are probably interfering, and you can write an init function that removes those nodes, and it will do that before you iterate over them.

conclusion

Skeleton screens are now more mainstream. I have tried this solution in the project, for some products, the front-end user experience is still quite important, let’s use it! Pit words welcome to leave a message to exchange.

The appendix

Source code process review