前端兼容性問(wèn)題總結(jié)

HTML 篇

樣式兼容性問(wèn)題

<!-- IE 按 Edge 模式渲染 -->
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<!-- IE 8 9 10 按 IE7 模式渲染 -->
<meta http-equiv="X-UA-Compatible" content="IE=Emulate7" />

怪異模式

怪異模式是沒(méi)有遵守 W3C 規(guī)范的一種兼容模式,其中的 width 是包括 contentWidth, 左右padding, 左右border 在內(nèi)的全部范圍(height 也一樣)戈轿,類似于 box-sizing: border-box;,而且 table 的 font-size 不能從父元素繼承思杯。以下情況會(huì)觸發(fā)瀏覽器怪異模式(Quirks Mode):

  • 沒(méi)寫 DOCTYPE 觸發(fā)怪異模式
  • <!DOCTYPE ...>前加<?xml version="1.0" encoding="utf-8" ?>, IE6 下會(huì)觸發(fā)怪異模式
  • <!DOCTYPE ...>前加入``, IE7進(jìn)入怪異模式
  • <!DOCTYPE ...>前有任何非空字符胜蛉,會(huì)在IE6 下會(huì)觸發(fā)怪異模式
  • <!DOCTYPE ...>前有 XML ,在IE7 下不會(huì)觸發(fā)怪異模式色乾,但不能有其他非空字符

檢查document.compatMode,可以查看瀏覽器工作在哪個(gè)模式:值BackCompat為怪異模式誊册,值CSS1Compat為標(biāo)準(zhǔn)模式

display:inline-block 元素間有間隙

<!-- 以下的 li 元素是 display: inline; 類型的 -->
<!-- 這樣寫元素之間有間隙 -->
<ul>
  <li>apple</li>
  <li>banana</li>
  <li>pineapple</li>
  <li>peach</li>
  <li>orange</li>
</ul>
<!-- 換個(gè)寫法解決問(wèn)題-->
<ul>
  <li>apple</li><li>
  banana</li><li>
  pineapple</li><li>
  peach</li><li>
  orange</li>
</ul>

IE可能出現(xiàn)的文檔樣式短暫失效問(wèn)題

<head>
    <!-- meta部分 -->
    <title></title>
    <!-- 可能的script部分 -->
    <script type="text/javascript"></script>   <!-- 關(guān)鍵:添加一個(gè)空標(biāo)簽 -->
    <!-- link部分 -->
</head>

css 篇

雙倍間距問(wèn)題

/*一下代碼在 IE6 中會(huì)出現(xiàn)雙倍間距*/
#box{
  float: left;
  margin: 10px;
}

//解決方法
#box{
  float: left;
  margin: 10px;
  display: inline;
}

錯(cuò)位問(wèn)題

/*IE6中,這樣的多個(gè)盒子并列時(shí)會(huì)發(fā)生向下偏移杈湾,應(yīng)該對(duì)偏移的盒子添加負(fù) margin-top 進(jìn)行修正*/
.box{
  float: left;
}

IE6 奇數(shù)寬高問(wèn)題

IE6 中盒子的寬(width) 和高(height)設(shè)置為奇數(shù)時(shí)會(huì)有 bug,盡量設(shè)置為偶數(shù)即可漆撞。

IE6 Peekaboo Bug

一個(gè) div#top 中加入一個(gè) div#float 向左浮動(dòng)殴泰,然后加入一個(gè)或多個(gè) div, 直到清除浮動(dòng)為止:

<style>
#top{
    border: dotted 2px black;
    background: #eee;    /*top有背景*/
}
#float{
    height: 196px;
    width: 196px;
    border: 2px solid red;
}
.border{
    border: 2px solid green;
}
.clear{
    clear: both;
    border: 2px solid blue;
}
</style>
<body>
    <div id="top">
        <div id="float">float div</div>
        <!-- 這以下在 IE6 中不能正常顯示 -->
        <div class="border">inside-div text!</div>
        <div class="border">inside-div text!</div>
        <!-- 這以上在 IE6 中不能正常顯示 -->
        <div class="clear">clear div</div>
    </div>
</body>

解決方法于宙,給 #top 一個(gè) height 或 width :

#top{
    height: 300px;
}

盒子坍塌

這個(gè)問(wèn)題比較普遍,在盒內(nèi)層元素設(shè)置外邊距時(shí)會(huì)發(fā)生

/*發(fā)生盒子坍塌*/
#box{
  height: 300px;
}
#box .inner-box{
  margin:20px;
}

/*修正*/
#box{
  height: 300px;
  margin-top: -20px;
}
#box .inner-box{
  margin:20px;
}

文字大小

字體大小在不同瀏覽上不一致悍汛。例如font-size:14px捞魁,在 IE 中的實(shí)際行高是16px,下面有3px留白离咐;在 Firefox 中的實(shí)際行高是17px谱俭,下面有3px留白,上邊1px留白宵蛀;在 opera 中就更不一樣了昆著。解決方式統(tǒng)一指定行高 line-height

html{
  font-size: 14px;
  line-height: 14px;
}

另外,我們會(huì)遇到 font-size:62.5% 這樣的定義术陶,為了把默認(rèn)的 16px 映射為 10px, 這樣1em = 10px 更利于計(jì)算凑懂。

去除元素默認(rèn)邊距

有很多元素默認(rèn)帶有邊距,對(duì)我們排版很不利梧宫。但利用通配符*去除邊距存在性能問(wèn)題接谨,所以用下面語(yǔ)句清除默認(rèn)邊距

body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{
  margin: 0;
  padding: 0;
}

低版本 IE 高度限定失效

一般的元素指定高度屬性 height 可以固定該元素高度,但在低版本 IE 中無(wú)法固定元素高度塘匣,該元素高度依然會(huì)被內(nèi)容撐開(kāi)脓豪,需要注意。(寬度也一樣)

IE6 不支持 png 透明效果

解決方式用濾鏡

#box{
  _background: none;
  filter: progid:DXImageTransForm.Microsoft.AlphaImageLoader(src='路徑');
}

Firefox 的寬度問(wèn)題

Firefox瀏覽器會(huì)的 body 比其他瀏覽器的 body 寬度小1個(gè)像素忌卤,注意設(shè)置其子元素(尤其 float 元素大小扫夜,防止排版混亂。

IE6中的吞吃問(wèn)題

IE6 中為上下2個(gè) div 中的上一個(gè)地址設(shè)置背景時(shí)埠巨,下一個(gè) div 也會(huì)帶有背景历谍。類似的還有 overflow:scroll 時(shí),出現(xiàn)的滾動(dòng)條不完整辣垒。應(yīng)該 分別對(duì)在上方的 div 和滾動(dòng)條不完整的 div 加 zoom: 1樣式望侈。

IE6 圖片格式問(wèn)題

IE6 中的圖片默認(rèn)存在邊框,應(yīng)統(tǒng)一去除勋桶。同時(shí)圖片下方會(huì)有空隙脱衙,用 font-size解決

img{
  border: none;
  font-size: 0;
}

IE中無(wú)法定義1px高度這樣的小盒子

IE6 中的空元素高度不能低于19px,解決方式有四種:

  1. 在元素中插入空注釋 ``
  2. 在元素中插入空格
  3. 加入 css: overflow:hidden;
  4. 加入 css: font-size: 0;

IE6 z-index 失效

當(dāng)父元素已設(shè)置 z-index 屬性后例驹,子元素的 z-index 會(huì)失效捐韩。

IE6中 select 始終高于 div

浮層 div 出現(xiàn)時(shí)隱藏 select她按,浮層 div 消失時(shí)再顯示 select凉泄。

讓 chrome 支持小于 12px 的字體

#box{
  font-size: 8px;
  -webkit-text-size-adjust: none;
}
/* 但是,上面這個(gè)方法 chrome27 以后就不能用了艺谆。但我們可以用 css3 解決這個(gè)問(wèn)題 */
#box{
  font-size: 12px;
  -webkit-transform: scale(0.75);
}

CSS Hack

兼容性屬性設(shè)置屎债,注意書寫順序:優(yōu)先寫高等級(jí)瀏覽器支持方式仅政、優(yōu)先寫支持瀏覽器多的方式

/*以 color 屬性為例垢油,注意書寫順序*/
#box{
  color: #f00;   //所有瀏覽器都支持
  color: #0f0 !important;   //只有 IE6 無(wú)效
  color: #00f\9;  //所有 IE 都有效
  color: #ff0\0;  //IE8+ 有效
  color: #f0f\9\0; //IE9+ 有效
  *color: #fff;  //僅 IE6, IE7 有效
  #color: #0ff;  //僅 IE6, IE7 有效
  +color: #800;  //僅 IE6, IE7 有效
  -color: #008;  //只有 IE6 有效
  _color: #080;  //只有 IE6 有效
}

由于后定義的屬性覆蓋先定義的屬性,所有上面設(shè)置最后的效果為:
IE6 為 #080
IE7 為 #800
IE8 為 #ff0
IE9,10 為 #0f0
其他 為 #f00

javascript 篇

innerText 和 innerContent

  1. innerText 和 textContent 的作用相同
  2. innerText IE8之前的瀏覽器支持
  3. innerContent 老版本的Firefox支持
  4. 新版本的瀏覽器兩種方式都支持

和以上四種情況完全一致的還有parentElement(老IE)和parentNode

獲取兄弟節(jié)點(diǎn)/元素的兼容性問(wèn)題

ie8以前不支持previousElementSiblingnextElementSibling,以及諸如此類帶有Element的元素屬性圆丹。利用previousSibling
nextSibling等不帶Element的屬性實(shí)現(xiàn)如下:

// 獲取下一個(gè)緊鄰的兄弟元素
function getNextElement(element){
  var ele = element;
  if(ele.nextElementSibling) return ele.nextElementSibling;
  do{
    ele = ele.nextSibling;
  }while(ele && ele.nodeType !== 1);
  return ele;
}

// 獲取上一個(gè)緊鄰的兄弟元素
function getPreviousElement(element){
  var ele = element;
  if(ele.perviousElementSibling) return ele.perviousElementSibling;
  do{
    ele = ele.perviousSibling;
  }while(ele && ele.nodeType !== 1);
  return ele;
}

// 獲取第一個(gè)子元素
function getFirstElement(parent){
  if(parent.firstElementChild) return parent.firstElementChild;
  var ele = parent.firstChild;
  while(ele && ele.nodeType !== 1) ele = ele.nextSibling;
  return ele;
}

// 獲取最后一個(gè)子元素
function getLastElement(parent){
  if(parent.LastElementChild) return parent.LastElementChild;
  var ele = parent.lastChild;
  while(ele && ele.nodeType !== 1) ele = ele.perviousSibling;
  return ele;
}

// 獲取所有兄弟元素
function sibling(ele){
  if(!ele) return null;

  var elements = [ ];
  var el = ele.previousSibling;
  while(el){
  if(el.nodeType === 1)
    elements.push(el);
  el = el.previousSibling;
  }
  el = element.nextSibling;
  while(el){
  if(el.nodeType === 1)
    elements.push(el);
  el = el.nextSibling;
  }
  return elements;
}

其它DOM操作

IE中有一些很好用的 DOM 方法滩愁,但是其他瀏覽器卻沒(méi)有,比如:

  • ele.swapNode(anotherEle)用來(lái)交換節(jié)點(diǎn);
  • ele.removeNode()刪除當(dāng)前節(jié)點(diǎn);
  • ele.insertAgjacentHTML('position','HTMLText')ele.insertAgjacentHTML('position',ele) 用來(lái)插入節(jié)點(diǎn)辫封;

部分實(shí)現(xiàn)方式寫在下面:

//實(shí)現(xiàn)swapNode方法
if(window.Node && !Node.prototype.swapNode){
  Node.prototype.swapNode = function(node){
    var nextSibling = this.nextSibling;
    var parentNode = this.parentNode;
    node.parentNode.replaceChild(this, node);
    parentNode.insertBefore(node, nextSibling);
  }
}
//實(shí)現(xiàn)removeNode
if(window.Node && !Node.prototype.removeNode){
  Node.prototype.removeNode = function(){
    this.parentNode.removeChild(this);
  }
}

//insertAdjacentHTML和insertAdjacentElement可以用insertBefore代替
//由于有現(xiàn)成方法替換硝枉,這里不寫具體實(shí)現(xiàn)了

js 操作 css 兼容性

//透明度
//非IE方法
ele.style.opacity = 0.2;  //0-1
//IE
ele.style.filter = "alpha(opacity=100)";

//float屬性
//非IE
ele.style.float = "left";
//IE
ele.style.cssFloat = "left";

Array方法

array.filter();

if (!Array.prototype.filter)
{
  Array.prototype.filter = function(fun /*, thisArg */)
  {
    "use strict";
    if (this === void 0 || this === null)
      throw new TypeError();
    var t = Object(this);
    var len = t.length >>> 0;
    if (typeof fun !== "function")
      throw new TypeError();
    var res = [];
    var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
    for (var i = 0; i < len; i++){
      if (i in t){
        var val = t[i];
        if (fun.call(thisArg, val, i, t))
          res.push(val);
      }
    }
    return res;
  };
}

array.forEach();

if (!Array.prototype.forEach) {
  Array.prototype.forEach = function(callback, thisArg) {
    var T, k = 0;
    if (this == null) {
      throw new TypeError(' this is null or not defined');
    }
    var O = Object(this);
    var len = O.length >>> 0;
    if (typeof callback !== "function") {
      throw new TypeError(callback + ' is not a function');
    }
    if (arguments.length > 1) T = thisArg;
    while (k < len) {
      var kValue;
      if (k in O) {
        kValue = O[k];
        callback.call(T, kValue, k, O);
      }
      k++;
    }
    return undefined;
  };
}

注冊(cè)事件

標(biāo)準(zhǔn)的綁定方法有兩種倦微,addEventListener和attachEvent前者是標(biāo)準(zhǔn)瀏覽器支持的API妻味,后者是IE8以下瀏覽器支持的API:

//例如給一個(gè)button注冊(cè)click事件
var el = document.getElementById('button');  //button是一個(gè)<button>元素
var handler = function(e){alert("button clicked.");};
if(el.addEventLister){
    el.addEventListener("click", handler,false);
}
if(el.attachEvent){
    el.attachEvent("onclick", handler);
}

需要注意的是:

  • addEventLister的第一個(gè)參數(shù)事件類型是不加on前綴的,而attachEvent中需要加on前綴;
  • addEventLister中的事件回調(diào)函數(shù)中的this指向事件元素target本身璃诀,而attachEvent中的事件回調(diào)函數(shù)的this指向的是window;
  • addEventLister有第三個(gè)參數(shù)弧可,true表示事件工作在捕獲階段蔑匣,false為冒泡階段(默認(rèn)值:false)劣欢。而attachEvent只能工作在冒泡階段;
  • 解除事件方法標(biāo)準(zhǔn)方法removeListen(),在IE8中裁良,對(duì)應(yīng)使用detachEvent()凿将。注意,他們和上面的注冊(cè)方法一一對(duì)應(yīng)价脾,不能混用;
  • 阻止默認(rèn)事件標(biāo)準(zhǔn)方法 event.preventDefault(), 在IE8中牧抵,使用 event.returnValue = false;
  • 阻止冒泡的方法 event.stopPropagation(), 在IE8中,使用 event.cancelBubble = true;
  • 老版本 IE 中侨把,事件函數(shù)內(nèi)部的 this 不是被監(jiān)聽(tīng)元素本身犀变,而是 window 。故應(yīng)該使用 call 改變 this 指向秋柄。

事件對(duì)象

  • e.eventPhase 事件階段获枝,IE8及以前不支持,因?yàn)槟菚r(shí)不支持捕獲
  • e.target 始終是觸發(fā)事件的對(duì)象骇笔。IE8以前用srcElement
  • ie8以前用window.event獲得事件對(duì)象省店,而不是回調(diào)函數(shù)的參數(shù)e
function(e){}
    return e || window.event;
}

// 兼容target
function(e){
  target = e.target || e.srcElement;
  //do something else
 }

獲取鼠標(biāo)在頁(yè)面上的位置

ie8以前沒(méi)有完整的位置屬性,部分屬性需要通過(guò)已有的屬性計(jì)算得到:

var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
var pageX = e.pageX || e.x || e.clientX + scrollLeft;
var pageY = e.pageY || e.y || e.clientY + scrollTop;

獲取鍵盤事件的鍵值

var keyCode = e.keyCode || e.which;

取消用戶的文本的選擇笨触,移動(dòng)端很常用

window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();

使不支持h5的瀏覽器支持h5標(biāo)簽

<!--[if IE]>
<style>
  article, aside, footer, header, nav, section, details, menu, figure {
    display: block;
  }
  canvas, progress, audio, video {
    display: inline-block;
  }
  progress {
    vertical-align: baseline;
  }
  audio:not([controls]) {
    display: none;
    height: 0;
  }
  mark {
    background-color: #ff0;
    color: #000;
  }
</style>
<script>
(function() {
  if(!/*@cc_on!@*/0)
    return;
  var e = "abbr, article, aside, audio, bb, canvas, datagrid, datalist, details, dialog, eventsource, figure, footer, header, hgroup, mark, menu, meter, nav, output, progress, section, time, video".split(', ');
  var i = e.length;
  while(i--) {
    document.createElement(e[i]);
  }
})();
</script>
<![endif]-->

Ajax 兼容問(wèn)題

//定義一個(gè) XMLHttpRequest 對(duì)象
var xhr;
if(XMLHttpRequest){
  xhr = new XMLHttpRequest();    //chrome, safari, opera, firefox
} else if(ActionXObject){
  try{
    xhr = new ActionXObject("Msxml2.XMLHTTP");   //IE 中 Msxml 插件
  }catch(e){
    xhr = new ActionXObject("Microsoft.XMLHTTP");   //IE
  }
}

綜合篇

處理 html 和 css 編碼不一致問(wèn)題

在 web.config 中寫以下代碼

<system.web><globalization fileEncoding="utf-8" resquestEncoding="utf-8" responseEncoding="utf-8" culture="zh-CN" /></system.web>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末懦傍,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子芦劣,更是在濱河造成了極大的恐慌粗俱,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,744評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件虚吟,死亡現(xiàn)場(chǎng)離奇詭異寸认,居然都是意外死亡娱俺,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門废麻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)荠卷,“玉大人,你說(shuō)我怎么就攤上這事烛愧∮鸵耍” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 163,105評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵怜姿,是天一觀的道長(zhǎng)慎冤。 經(jīng)常有香客問(wèn)我,道長(zhǎng)沧卢,這世上最難降的妖魔是什么蚁堤? 我笑而不...
    開(kāi)封第一講書人閱讀 58,242評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮但狭,結(jié)果婚禮上披诗,老公的妹妹穿的比我還像新娘。我一直安慰自己立磁,他們只是感情好呈队,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,269評(píng)論 6 389
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著唱歧,像睡著了一般宪摧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上颅崩,一...
    開(kāi)封第一講書人閱讀 51,215評(píng)論 1 299
  • 那天几于,我揣著相機(jī)與錄音,去河邊找鬼沿后。 笑死沿彭,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的得运。 我是一名探鬼主播膝蜈,決...
    沈念sama閱讀 40,096評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼熔掺!你這毒婦竟也來(lái)了饱搏?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 38,939評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤置逻,失蹤者是張志新(化名)和其女友劉穎推沸,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,354評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鬓催,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,573評(píng)論 2 333
  • 正文 我和宋清朗相戀三年肺素,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宇驾。...
    茶點(diǎn)故事閱讀 39,745評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡倍靡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出课舍,到底是詐尸還是另有隱情塌西,我是刑警寧澤,帶...
    沈念sama閱讀 35,448評(píng)論 5 344
  • 正文 年R本政府宣布筝尾,位于F島的核電站捡需,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏筹淫。R本人自食惡果不足惜站辉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,048評(píng)論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望损姜。 院中可真熱鬧饰剥,春花似錦、人聲如沸薛匪。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,683評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)逸尖。三九已至,卻和暖如春瘸右,著一層夾襖步出監(jiān)牢的瞬間娇跟,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,838評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工太颤, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留苞俘,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,776評(píng)論 2 369
  • 正文 我出身青樓龄章,卻偏偏與公主長(zhǎng)得像吃谣,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子做裙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,652評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容