Common Compatibility Issues

Browsers have a large number of different versions, and the rendering engines of different types of browsers are also different. Therefore, different browsers may have differences in parsing code, which leads to inconsistent rendering effects on web pages.

Initializing Styles

Due to browser compatibility issues, different browsers have different default style values for tags. If styles are not initialized, it will cause display differences between different browsers and layout problems. Therefore, it is necessary to initialize styles to achieve consistent layout.
The most direct solution is to use * to initialize styles, but it will load styles and calculate style priorities for all tags, which may have an impact on performance.

* { 
    margin: 0;
    padding: 0;
}

Usually, Normalize.css is used to normalize the default style differences. Of course, you can also customize your own reset.css based on the styles.

<link href="https://cdn.bootcss.com/normalize/7.0.0/normalize.min.css" rel="stylesheet">

Kernel Style Compatibility

Before the CSS3 standard was finalized, some browsers had already implemented some features based on the initial drafts. In order to be compatible with the later finalized standards, each browser used its own vendor prefix to distinguish from the standard. After the standard was established, major browsers gradually supported CSS3 new properties without prefixes. Many vendor prefixes can now be omitted. However, in order to be compatible with older versions of browsers, it is still recommended to use vendor prefixes and standard methods for a smooth transition.

Kernel Representative Browser Prefix
Trident IE Browser -ms
Gecko Firefox -moz
Presto Opera -o
Webkit Chrome, Safari -webkit

Transparency Property

The opacity property used to set the transparency of an element is a property in CSS3 and is supported by modern browsers. For older versions of browsers, it can be supported by adding vendor prefixes. For IE6-IE8, it can be supported by the filter property. For IE4-IE9, compatibility support can be provided through filter syntax.

opacity: 0.5;
-moz-opacity:0.5;
filter: alpha(opacity = 50); //IE6-IE8
filter: progid:DXImageTransform.Microsoft.Alpha(style = 0, opacity = 50); //IE4-IE9

Media Queries

For browsers that do not support CSS3 media queries below IE9, respond.js is usually used as a compatibility solution.

<script type="text/javascript" src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>

HTML5 Tags

For browsers that do not support new HTML5 tags below IE9, you can create elements using document.createElement and set their CSS styles. Usually, html5shiv.js is used as a compatibility solution.

<script>
    document.createElement('header');
</script>
<style>
    header{display: block;}
</style>
<script type="text/javascript" src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>

Compatibility of placeholder

placeholder is a new attribute added in html5. When input or textarea is set with this attribute, the value will be displayed as a gray hint in the text box. The hint text will disappear when the text box gains focus or when content is entered. To ensure compatibility, first check if input supports placeholder. If it doesn't, you can achieve the placeholder effect by using the onfocus and onblur event listeners of input.

<!-- Simple example -->
<input type="text" value="Tips" onFocus="this.value = '';" onBlur="if (this.value == '') {this.value = 'Tips';}">

Event listener handler

Before IE9, attachEvent was used instead of the standard method addEventListener to register element listeners. To handle event compatibility issues, it is usually necessary to encapsulate an adapter method to filter event handler binding and removal.

var handler = {}

// Bind event
handler.on = function(target, type, handler) {
    if(target.addEventListener) {
        target.addEventListener(type, handler, false);
    } else {
        target.attachEvent("on" + type,
            function(event) {
                return handler.call(target, event);
            }, false);
    }
};

// Remove event listener
handler.remove = function(target, type, handler) {
    if(target.removeEventListener) {
        target.removeEventListener(type, handler);
    } else {
        target.detachEvent("on" + type,
        function(event) {
            return handler.call(target, event);
        }, true);
    }
};

Prevent default behavior

The recommended way to prevent default behavior by W3C is to use event.preventDefault(). This method only prevents the default behavior without stopping the event propagation. For browsers before IE9, preventing default behavior requires using window.event.returnValue = false. Returning false directly in the event handler function can also prevent default behavior, but it is only effective in DOM0 level model. In addition, using return false in jQuery will both prevent default behavior and event propagation. It is also common to encapsulate a method to achieve the prevention of default behavior.

handler.preventDefault = function(event) {
    event = event || window.event;
    if (event.preventDefault) {
        event.preventDefault();
    } else {
        event.returnValue = false;
    }
}

Stop event propagation

The recommended way to stop event propagation by W3C is to use event.stopPropagation(). For browsers before IE9, it is done by using window.event.cancelBubble = true;. It is also common to encapsulate a method to achieve the prevention of event propagation.

handler.stopPropagation = function(event) {
    event = event || window.event;
    if (event.stopPropagation) {
        event.stopPropagation();
    } else {
        event.cancelBubble = false;
    }
}

Scroll Height

To get the scroll height of the window scrollTop, a compatibility writing style is needed, even if the <DOCTYPE> declaration is made, different browsers may handle the document differently.

var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;

Date and Time

Use the new Date() constructor to generate a date and time object. The syntax new Date("2020-06-29") may output invalid date in some earlier browsers. This is mainly because early browsers do not support the - in expressing dates, and / is widely supported. Therefore, when dealing with compatibility in earlier browsers, - needs to be replaced with /.

new Date("2020-06-29".replace(/-/g, "/"));

IE Conditional Comments

A syntax specifically provided by IE, which can only be recognized and executed by IE, while other browsers treat it as a comment.

<!--[if lt IE 9]>
    <script type="text/javascript" src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
    <script type="text/javascript" src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<![endif]-->
<!--[if !IE]>  Recognizable by all browsers except IE   <![endif]-->
<!--[if IE]>   Recognizable by all versions of IE   <![endif]-->
<!--[if IE 6]>   Recognizable by only IE6   <![endif]-->
<!--[if lt IE 6]>   Recognizable by IE6 and versions below IE6   <![endif]-->
<!--[if gte IE 6]>   Recognizable by IE6 and versions above IE6   <![endif]-->
<!--[if IE 7]>   Recognizable by only IE7   <![endif]-->
<!--[if lt IE 7]>   Recognizable by IE7 and versions below IE7   <![endif]-->
<!--[if gte IE 7]>   Recognizable by IE7 and versions above IE7   <![endif]-->
<!--[if IE 8]>   Recognizable by only IE8   <![endif]-->
<!--[if IE 9]>   Recognizable by only IE9   <![endif]-->
<!-- 
    ! NOT operator
    lt Less than operator
    lte Less than or equal to operator
    gt Greater than operator
    gte Greater than or equal to operator
    & AND operator
    | OR operator
    () Subexpression operator used to create more complex expressions with boolean operators
-->

Daily Question

https://github.com/WindrunnerMax/EveryDay

References

https://www.jianshu.com/p/c0b758a88c7c https://juejin.im/post/5b3da006e51d4518f140edb2 https://juejin.im/post/59a3f2fe6fb9a0249471cbb4