浏览器兼容

2019/6/30 JavaScriptCSS

TIPS

首先要了解兼容, 我们先得了解一下为什么会存在浏览器兼容问题. 在各大浏览器厂商的发展过程中, 它们对web的标准各有不同的实现, 标准不同存在差异所以产生兼容性的问题

# 样式兼容性 (CSS)

  • CSS Hack

    CSS中, Hack是指一种兼容CSS在不同浏览器中正确显示的技巧方法, 因为它们都属于个人对CSS代码的非官方的修改, 或非官方的补丁. 有些人更喜欢使用 patch (补丁) 来描述这种行为

  • Filter

    表示过滤器的意思, 它是一种对特定的浏览器或浏览器组显示或隐藏规则或声明的方法. 本质上讲, Filter是一种用来过滤不同浏览器的Hack类型

  1. 不同浏览器的默认样式不同, 可以通过引入 normalize.css 统一, 也可以自己编写css, 如:

    body,ul,li{
        margin:0;
        padding:0;
    }
    
    1
    2
    3
    4
  2. 部分属性需要加浏览器前缀

    前缀 代表浏览器 内核
    -ms IE Trident
    -moz Firefox Gecko
    -o Opera Presto
    -webkit Chrome和Safari Webkit
    /*举例*/
    {
      /* Opera */
      -o-transform: rotate(7deg);
      /* IE */
      -ms-transform: rotate(7deg);
      /* Firefox */
      -moz-transform: rotate(7deg);
      /* Chrome */
      -webkit-transform: rotate(7deg);
      /* 统一标识语句 */
      transform: rotate(7deg);
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

    TIPS

    背景: css3语法还未成为真正标准时, 各大浏览器厂商提供了浏览器前缀, 直到现在部分属性还需要加上前缀

    处理: 开发过程中一般通过IDE插件, css预处理器以及前端自动化构建工具来自动实现这一处理

  3. 针对IE低版本的filter

    过滤器符号 可识别并解析的版本 用法
    _ <= IE6 选择器{_属性: 属性值;}
    !important 除IE6外的所有 选择符{属性: 属性值!important;}
    * <= IE7 选择器{*属性: 属性值;}
    \0 = IE8 选择符{属性: 属性值\0;} (\0仅支持IE8, \9支持IE6+)

# 常见CSS兼容方法

  1. 图片在IE上有边框

    hack: 图片设置: border:0 或者 border: 0 none;

  2. div中的图片间隙: div中插入图片时图片将div下方撑大约3px

    hack: 图片转换为块元素: display:block

  3. 双倍边距(<=IE6): IE6及更低版本浏览器在解析浮动元素时, 会错误地把浮向边界加倍显示

    hack: 浮动元素设置 display:inline;

  4. cursor:hand VS cursor:pointer

    firefox不支持hand, 但IE支持pointer, 解决方法: 统一使用pointer

  5. 透明属性: IE低版本浏览器(小于IE9)只能使用filter设置透明度, IE高版本浏览器及其他浏览器要用opacity来设置

    {
      opacity: 0.5;
      filter: alpha(opacity = 50);/*IE6-8习惯使用filter滤镜属性来实现*/
      filter: progid:DXImageTransform.Microsoft.Alpha(style = 0,opacity = 50);
      /*IE4-IE9都支持滤镜写法progid:DXImageTransform.Microsoft.Alpha(Opacity=xx)*/
    }
    
    1
    2
    3
    4
    5
    6
  6. IE6-7 line-height 失效的问题

    问题: 在IE 中 img 与文字放一起时, line-height 不起作用

    解决: 都设置成 float

  7. a 标签的几种 CSS 状态的顺序

    很多人在写 a 标签的样式, 会疑惑为什么写的样式没有效果, 或者点击超链接后, hover, active 样式没有效果, 其实只是写的样式被覆盖了 正确的a标签顺序应该是: love hate

    • link: 平常的状态
    • visited: 被访问过之后
    • hover: 鼠标放到链接上的时候
    • active: 链接被按下的时候

# 交互兼容性 (js)

  1. DOM 事件处理程序的兼容写法

    var eventshiv = {
      // event兼容
      getEvent: function (event) {
        return event ? event : window.event;
      },
    
      // type兼容
      getType: function (event) {
        return event.type;
      },
    
      // target兼容
      getTarget: function (event) {
        return event.target ? event.target : event.srcElement;
      },
    
      // 添加事件句柄
      addHandler: function (elem, type, listener) {
        if (elem.addEventListener) {
          elem.addEventListener(type, listener, false);
        } else if (elem.attachEvent) {
          elem.attachEvent('on' + type, listener);
        } else {
          // 在这里由于.与'on'字符串不能链接, 只能用 []
          elem['on' + type] = listener;
        }
      },
    
      // 移除事件句柄
      removeHandler: function (elem, type, listener) {
        if (elem.removeEventListener) {
          elem.removeEventListener(type, listener, false);
        } else if (elem.detachEvent) {
          elem.detachEvent('on' + type, listener);
        } else {
          elem['on' + type] = null;
        }
      },
    
      // 添加事件代理
      addAgent: function (elem, type, agent, listener) {
        elem.addEventListener(type, function (e) {
          if (e.target.matches(agent)) {
            listener.call(e.target, e); // this 指向 e.target
          }
        });
      },
    
      // 取消默认行为
      preventDefault: function (event) {
        if (event.preventDefault) {
          event.preventDefault();
        } else {
          event.returnValue = false;
        }
      },
    
      // 阻止事件冒泡
      stopPropagation: function (event) {
        if (event.stopPropagation) {
          event.stopPropagation();
        } else {
          event.cancelBubble = true;
        }
      }
    };
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
  2. 获取 scrollTop 通过 document.documentElement.scrollTop 兼容非chrome浏览器

    var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
    //更强版本:
    var scrollTop = document.documentElement.scrollTop || document.body.scrollTop || window.pageYOffset || 0;
    //谷歌或火狐      = document.documentElement.scrollTop;
    // 老版本IE使用:  = document.body.scrollTop;
    // safari:       = window.pageYOffset;
    // 0:以防万一
    
    1
    2
    3
    4
    5
    6
    7
  3. event.x与event.y

    IE下event对象有x,y属性, 没有pageX,pageY属性; Firefox下event对象没有x,y属性, 有pageX,pageY属性

    const mX = event.x ? event.x : event.pageX;
    
    1
  4. window.location.href问题

    Firefox 1.5.x下,只能使用 window.location; IE或者Firefox2.0.x下, 可以使用 window.locationwindow.location.href ;

    使用 window.location 来代替 window.location.href

  5. event.srcElement问题

    问题说明: IE下, even对象有srcElement属性, 但是没有target属性; Firefox下, even对象有target属性, 但是没有srcElement属性

    const srcObj = event.srcElement ? event.srcElement : event.target;
    
    1
  6. ajax: IE低版本没有XMLHttpRequest对象

    if (window.XMLHttpRequest) {
      xml = new XMLHttpRequest();// (Chrome, Firefox, IE7+, Edge, Safari Opera)
    } else {
      xml = new ActiveXObject("Microsoft.XMLHttp");// (IE5 and IE6)
    }
    
    1
    2
    3
    4
    5
  7. 键盘事件 keyCode 兼容性写法

    var inp = document.getElementById('inp')
    var result = document.getElementById('result')
    
    function getKeyCode(e) {
      e = e ? e : (window.event ? window.event : "")
      return e.keyCode ? e.keyCode : e.which
    }
    
    inp.onkeypress = function (e) {
      result.innerHTML = getKeyCode(e)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
  8. 求窗口大小的兼容写法

    // 浏览器窗口可视区域大小 (不包括工具栏和滚动条等边线)
    // 1600 * 525
    var client_w = document.documentElement.clientWidth || document.body.clientWidth;
    var client_h = document.documentElement.clientHeight || document.body.clientHeight;
    
    // 网页内容实际宽高 (包括工具栏和滚动条等边线)
    // 1600 * 8
    var scroll_w = document.documentElement.scrollWidth || document.body.scrollWidth;
    var scroll_h = document.documentElement.scrollHeight || document.body.scrollHeight;
    
    // 网页内容实际宽高 (不包括工具栏和滚动条等边线)
    // 1600 * 8
    var offset_w = document.documentElement.offsetWidth || document.body.offsetWidth;
    var offset_h = document.documentElement.offsetHeight || document.body.offsetHeight;
    
    // 滚动的高度
    var scroll_Top = document.documentElement.scrollTop || document.body.scrollTop;
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
  9. requestAnimationFrame

    window.requestAnimationFrame = (function (callback) {
      return window.requestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.msRequestAnimationFrame ||
        window.oRequestAnimationFrame ||
        function () {
          window.setTimeout(callback, 1000 / 60)
        }
    })();
    window.cancleAnimationFrame = (function (callback) {
      return window.cancelAnimationFrame ||
        window.mozCancelAnimationFrame ||
        window.webkitCancelAnimationFrame ||
        window.msCancelAnimationFrame ||
        window.oCancelAnimationFrame ||
        function () {
          window.clearTimeout(callback, 1000 / 60)
        }
    })();
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20

# 浏览器hack

  1. 快速判断IE浏览器版本

    <!-- IE条件注释 -->
    <!--[if IE 8]> IE8 <![endif]-->
    <!--[if IE 9]> IE9 浏览器 <![endif]-->
    
    1
    2
    3
  2. 判断是否是Safari浏览器

    /* Safari */
    var isSafari = /a/.__proto__ == '//';
    
    1
    2
  3. 判断是否是Chrome浏览器

    /* Chrome */
    var isChrome = Boolean(window.chrome);
    
    1
    2
最近更新: 2025年03月13日 17:49:47