HTML5+CSS3 header creation example and update

HTML5+CSS3 header creation example and update

Last time, we came up with two header layouts, one flexbox and one float. Finally, after communicating with colleagues who were doing the reconstruction, we chose the float layout.

In fact, the layout selection does not require my attention. My participation or some opinions are mostly self-improvement, but it is not necessarily true that the HTML structure is completely controlled by CSS.

During the coding process of the header component, I had repeated discussions and arguments with my refactoring colleagues on some issues. Today, let’s talk about the layout and function implementation of the header component and the coordination between js and css.

The header component itself is an old component. Let’s discuss how to renovate this type of old component.

Initial structure

The colleague who refactored it at the beginning gave me a ready-made page:

We discussed some of these small experiences and informed the design team, and they made changes, which went smoothly. Then I started to happily code. This is the structure of one of the HTML blocks:

 <header class="cm-header" style="top: 50px;">
   <span class="fl cm-header-icon icon-back"></span>
   <span class="fr cm-header-btn">Confirm</span>
   <span class="fr cm-header-icon"><i class="icon-home"></i></span>
   <span class="fr cm-header-icon"><i class="icond-list"></i></span>
   <h1 class="cm-page-title">
     Page Title</h1>
 </header>

Excluding the text in the h1 tag, which may be very complicated, we will talk about it later. The buttons have the following functions:

① Second row: Back button
② Third line: Confirm

PS: The left side uses float layout, so the first element is on the far right

③ Fourth line: home tag
④ The fifth row: three dots, click to display a sidebar

The above is the implementation of HTML, but for programmers, the header only has icons besides buttons (btn), so the above structure is generally not accepted by JS.

The structure required by Jser

After communicating with my refactoring colleagues, the reason is this:

① Because the fallback is special, there is an additional style, but I don’t remember what it is.
② icon represents the background image, icond represents the CSS3 drawing, CSS3 drawing has high scalability, such as changing color, etc.
③ ......

The discussion between the two sides was quite intense at the time, but the refactoring colleague disagreed with changing all icond to icon, so the plan was abandoned. After a round of discussion, the structure became like this:

<header class="cm-header" style="top: 50px;">
   <span class="fl cm-header-icon"><i class="icon-back"></i></span>
   <span class="fr cm-header-btn">Confirm</span>
   <span class="fr cm-header-icon"><i class="icon-home"></i></span>
   <span class="fr cm-header-icon"><i class="icond-list"></i></span>
   <h1 class="cm-page-title">
     Page Title</h1>
 </header>

I made a small change to unify the structure of back with other icon type buttons, and then I started to code happily.

PS: Please note that the icond and icon type tags will appear in the header to varying degrees and cannot be controlled.

Structural issues

Because the company's header has always existed, I had to consider two aspects during the process:

① Convenient for expansion but interface compatibility is required
② It is necessary to conduct joint debugging with Hybrid through the tagname of each tag

In other words, the name of each tag is fixed, and even the callbacks of some tags are restricted. My data structure is as follows:

 {
 left: [],
 center: [],
 right: [
   {
     'tagname': 'home', callback: function () {
       console.log('return');
     }
   },
   { 'tagname': 'search' },
   {
     'tagname': 'list', callback: function (e) {
        //......
     }
   },
   { 'tagname': 'tel', 'number': '56973144' },
   {
     'tagname': 'commit', 'value': 'Login', callback: function () {
       console.log('Login');
     }
   },
   {
     'tagname': 'custom', 'value': 'Customization',
     itemFn: function () {
       return '<span class="cm-header-btn fr js_custom">Customization</span>';
     },
     callback: function () {
       console.log('customization');
     }
   }

As you can see, there is one button for each tagname, but now the problem comes: we don’t know whether a tagname should be an icon or an icond

However, based on whether the value field exists, we can determine whether it should have an i subtag. How do we solve this problem?

Establish a mapping relationship between tagname and classname, for example:

 var map = {
   'home': 'icon',
   'list': 'icond'
 }

Of course, this approach is naturally very uncomfortable. If the small icons are unified as icons, I can unify the code in the template like this:

 <span class="cm-header-icon <%=dir %> js_<%=item.tagname %>" >
   <% if(item.value) { %>
     <%=item.value %>
   <% } else { %>
     <i class="icon-<%=item.tagname %>"></i>
   <% } %>
 </span>

However, due to the addition of a mapping relationship, my code became ugly and the business logic became complicated. So I found a refactoring colleague again with these considerations. The refactoring colleague was also very sensible and immediately agreed to change it:

 <header class="cm-header" style="top: 50px;">
   <span class="fl cm-header-icon"><i class="icon-back"></i></span>
   <span class="fr cm-header-btn">Confirm</span>
   <span class="fr cm-header-icon"><i class="icon-home"></i></span>
   <span class="fr cm-header-icon"><i class="icon-list"></i></span>
   <h1 class="cm-page-title">
     Page Title</h1>
 </header> 

Without considering the style in h1, it is really easy for us to get the above code! ! !

 <header class="cm-header">
 <%
 var i = 0, len = 0, j = 0, keyagain = 0;
 var left = left;
 var right = right.reverse();
 var item = null;
 var dir;
 var btnObj = null;
 %>
 <%for(keyagain=0; keyagain < 2; keyagain++) { %>
   <% 
     if(keyagain == 0) { dir = 'fl'; btnObj = left; } else { dir = 'fr'; btnObj = right; }
   %>
   <% for(i = 0, len = btnObj.length; i < len; i++) { %>
     <% item = btnObj[i]; %>
     <%if(typeof item.itemFn == 'function') { %>
       <%=item.itemFn() %>
     <%} else { %>
       <span class="cm-header-icon <%=dir %> js_<%=item.tagname %>" >
         <% if(item.value) { %>
           <%=item.value %>
         <% } else { %>
           <i class="icon-<%=item.tagname %>"></i>
         <% } %>
       </span>
     <%} %>
   <%} %>
 <%} %>
 </header> 

PS: From the code coloring, left and right used in js are keywords, which need to be processed...

Customized requirements

As you can see, with one loop, we can easily generate buttons on the left and right, but the problem comes immediately. What if we need to expand it? There will be the following problems:

① The default tel tag is the a tag, but here it is the span tag

<a href="tel:56973144" class="cm-header-btn fr js_tel "><i class="icon-tel"></i></a>

② The back button is usually made into an a tag to solve the problem of false death caused by javascript errors in Hybrid

To put it bluntly, although the label buttons should have a unified structure, they need to retain the ability to be customized.
The customization work here is assigned to the itemFn function of each tag. It returns a string with certain rules. Here is a code snippet:

 handleSpecialParam: function (data) {
   var k, i, len, item;
   for (k in data) {
     if (_.isArray(data[k])) {
       for (i = 0, len = data[k].length; i < len; i++) {
         item = data[k][i];
         if (this['customtHandle_' + item.tagname]) {
           this['customtHandle_' + item.tagname](data[k][i], k);
         } //if
       } //for
     } //if
   } //for
 },
 
 _getDir: function (dir) {
   var kv = { left: 'fl', right: 'fr' };
   return kv[dir];
 },
 
 //Handle the back button logic customtHandle_back: function (item, dir) {
   dir = this._getDir(dir);
   item.itemFn = function () {
     var str = '<a href="http://m.ctrip.com/html5/" class="cm-header-btn ' + dir + ' js_' + item.tagname + ' " >';
     if (item.value) {
       str += item.value + '</a>';
     } else {
       str += '<i class="icon-' + item.tagname + '"></i></a>';
     }
     return str;
   };
 }, 

When you find that a button does not meet your needs or has customized requirements, you can find a way to set its itemFn. At this time, this code can be written directly to the initialized json string.

Various titles

When it comes to title, you will find that its performance is varied. At this time, different HTML structures are generally generated according to different types. The framework gives several default options. If it is not supported, you can customize itemFn yourself.

 <% item = center; %>
 <%if(typeof item.itemFn == 'function') { %>
   <%=item.itemFn() %>
 <%} else if(item.tagname=='title' || item.tagname=='subtitle') { %>
   <h1 class="cm-page-title js_<%=item.tagname %>" >
     <%if(typeof(item.value) == 'object' && item.title.value == 2) { %>
       <span class="cm-title-l"><%=item.value[0]%></span>
       <span class="cm-title-s"><%=item.value[1]%></span>
     <%} else { %>
       <%=item.value %>
     <%} %>
   </h1>
 <%} else if(item.tagname=='select'){ %>
   <h1 class="cm-page-select-title js_<%=item.tagname %>" >
     <%=item.value %>
   </h1>
 <%} else if(item.tagname=='tabs') { %>
   <h1 class="cm-page-tabs-title js_<%=item.tagname %>" >
     <%for(j = 0; j < item.data.items.length; j ++) { %>
       <span data-key="<%=item.data.items[j].id %>" class="<%if(item.data.index===j){ %>active<%} %>" ><%=item.data.items[j].name %></span>
     <% } %>
   </h1>
 <% } else{ %>
 
 <%} %> 

Implementation of event binding

The header component itself inherits from the Abstract.View class, so just set

this.events = {}

The event can be bound to the root element as an event proxy, and the event of the header is generally a click event:

 setEventsParam: function () {
   var item, data = this.datamodel.left.concat(this.datamodel.right).concat(this.datamodel.center);
 
   for (var i = 0, len = data.length; i < len; i++) {
     item = data[i];
     if (_.isFunction(item.callback)) {
       this.events['click .js_' + item.tagname] = $.proxy(item.callback, this.viewScope);
     }
   }
 }, 

One thing to note here is that the event binding hook is our tagname, which is unique. We will dynamically generate a ".js_tagname" class for each tag to facilitate event binding.

Compatibility with old interfaces

As mentioned before, this component is a renovation of an old component, so various business teams have already used it. For example, it was originally called like this:

 this.header.set({
   title: 'Basic Header Usage',
   subtitle: 'Middle subtitle',
   back: true,
   backtext: 'Cancel',
   tel: { number: 1111 },
   home: true,
   search: true,
   btn: { title: "Login", id: 'confirmBtn', classname: 'header_r' },
   events: {
     returnHandler: function () {
       console.log('back');
     },
     homeHandler: function (e) {
     }
   }
 }); 

Now we expect the calling method to be like this:

this.header.set({
  left: [],
  center: {},
  right: [
    { tagname: 'home', callback: function () { } },
    { tagname: 'tagname', value: 'value', data: {}, itemFn: function(){}, callback: function () { } }
  ]
}); 

What should we do at this time? Of course, there is no construction without destruction, first destruction and then construction, of course the business team is required to make changes! ! ! Then I was ruthlessly criticized, so I made the interface compatible
When refurbishing old components, interface compatibility is a must. Unless the underlying mechanism is disrupted and the disruption can bring disruptive results, it is not recommended to change the interface!
Here the new interface is called above, and the old interface is called below. The effect is as follows:

This is the end of this article about HTML5+CSS3 header creation examples and updates. For more relevant header example content, please search 123WORDPRESS.COM’s previous articles or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

<<:  Deploy grafana+prometheus configuration using docker

>>:  Core skills that web front-end development engineers need to master

Recommend

Realize the CSS loading effect after clicking the button

Since there is a button in my company's produ...

jQuery implements form validation

Use jQuery to implement form validation, for your...

How a select statement is executed in MySQL

Table of contents 1. Analyzing MySQL from a macro...

Solve the problem of secure_file_priv null

Add secure_file_priv = ' '; then run cmd ...

How to run .sh files in Linux system

There are two ways to run .sh files in Linux syst...

JavaScript to implement the back to top button

This article shares the specific code for JavaScr...

New ways to play with CSS fonts: implementation of colored fonts

What if you designers want to use the font below ...

Vue.js implements calendar function

This article example shares the specific code of ...

js realizes the image cutting function

This article example shares the specific code of ...

Detailed explanation of destructuring assignment syntax in Javascript

Preface The "destructuring assignment syntax...

Detailed explanation of padding and abbreviations within the CSS box model

As shown above, padding values ​​are composite at...

Methods for optimizing Oracle database with large memory pages in Linux

Preface PC Server has developed to this day and h...

How to force vertical screen on mobile pages

I recently wrote a mobile page at work, which was...

JavaScript canvas text clock

This article example shares the specific code of ...