1.條件注釋
IE條件注釋是一種特殊的HTML注釋,這種注釋只有IE5.0及以上版本才能理解。比如普通的HTML注釋是:
而只有IE可讀的IE條件注釋是:
“非IE條件注釋”:
non-IE HTML Code
“非特定版本IE條件注釋”(很少用到):
<![IGNORE[]]>Code for browsers that match the if condition
簡而言之,除了“Windows上的IE”之外的所有瀏覽器都會認為條件注釋只是一段普通的HTML注釋。你不能在CSS代碼中使用條件注釋。IE條件注釋是很有用的對IE隱藏或者展現特定代碼的方法,比起在CSS中用詭異的_/制造bug,利用IE條件注釋來寫CSS “hacks”是更合理的方法。通俗點,條件注釋就是一些if判斷,但這些判斷不是在腳本里執行的,而是直接在html代碼里執行的。
條件注釋的基本結構和HTML的注釋(<!– –>)是一樣的。因此IE以外的瀏覽器將會把它們看作是普通的注釋而完全忽略它們。
IE將會根據if條件來判斷是否如解析普通的頁面內容一樣解析條件注釋里的內容。
條件注釋使用的是HTML的注釋結構,因此他們只能使用在HTML文件里,而不能在CSS文件中使用。
從語法上看這是相當合法的普通HTML注釋。任何瀏覽器都會認為<!–和–>之間的部分是注釋從而忽略它。但是IE也會看到其中[if IE]>
,從而開始解釋接下來的代碼直到遇到<![endif]
。所以,下面這些代碼不會顯示在任何其他瀏覽器中面。
通過“比較操作符”可以更靈活地對IE版本進行控制,用法是在IE前面加上“比較操作符”。合法的操作符如下:
lte:就是Less than or equal to的簡寫,也就是小于或等于的意思。
lt :就是Less than的簡寫,也就是小于的意思。
gte:就是Greater than or equal to的簡寫,也就是大于或等于的意思。
gt :就是Greater than的簡寫,也就是大于的意思。
! :就是不等于的意思,跟javascript里的不等于判斷符相同
示例:
<!–[if gt IE 5.5]>
/ 如果IE版本大于5.5 /
<!–[if lte IE 6]>
/ 如果IE版本小于等于6 /
<!–[if !IE]>
/ 如果瀏覽器不是IE /
雖然看上去當你第一次使用條件注釋的時候會更費時,但當你以后調試你的CSS的時候,就會發現非常方便。用條件注釋你只需要寫一遍HTML注釋,而用bug你需要為每一條規則都寫上又長又丑的代碼,而且還經常是為了改變其他的hacks而寫的hacks。除此之外條件注釋對于不支持它的任何瀏覽器而言都是合法的HTML注釋。以下為條件注釋與CSS hacks的一些區別:
Hacks是基于瀏覽器的bug,而這些bug最終可能會被修復。
條件注釋是基于IE特定代碼,這種識別機制任何時候都不會被移除。
每一個瀏覽器都能看見你的hacks,或許下一個版本或者一個新的瀏覽器會在你的hacks代碼上出錯。
只有IE才能看到條件注釋,通過額外的“IE文件”來影響頁面,其他瀏覽器根本就不會下載它。
Hacks不能確保對哪些瀏覽器生效而對哪些不,用的hacks越多,代碼越混亂。
條件注釋利用版本匹配使得作者可以容易地對特定版本寫代碼。
2.IE Hack
什么是CSS hack
由于不同廠商的流覽器或某瀏覽器的不同版本(如IE6-IE11,Firefox/Safari/Opera/Chrome等),對CSS的支持、解析不一樣,導致在不同瀏覽器的環境中呈現出不一致的頁面展現效果。這時,我們為了獲得統一的頁面效果,就需要針對不同的瀏覽器或不同版本寫特定的CSS樣式,我們把這個針對不同的瀏覽器/不同版本寫相應的CSS code的過程,叫做CSS hack!
CSS hack的原理
由于不同的瀏覽器和瀏覽器各版本對CSS的支持及解析結果不一樣,以及CSS優先級對瀏覽器展現效果的影響,我們可以據此針對不同的瀏覽器情景來應用不同的CSS。
IE hack
1.條件注釋法
這種方式是IE瀏覽器專有的Hack方式,微軟官方推薦使用的hack方式。舉例如下
只在IE下生效
<!--[if IE]>
這段文字只在IE瀏覽器顯示
<![endif]-->
只在IE6下生效
<!--[if IE 6]>
這段文字只在IE6瀏覽器顯示
<![endif]-->
只在IE6以上版本生效
<!--[if gte IE 6]>
這段文字只在IE6以上(包括)版本IE瀏覽器顯示
<![endif]-->
只在IE8上不生效
<!--[if ! IE 8]>
這段文字在非IE8瀏覽器顯示
<![endif]-->
非IE瀏覽器生效
<!--[if !IE]>
這段文字只在非IE瀏覽器顯示
<![endif]-->
2.類內屬性前綴法
hack | 寫法 | 實例 | IE6(S) | IE6(Q) | IE7(S) | IE7(Q) | IE8(S) | IE8(Q) | IE9(S) | IE9(Q) | IE10(S) | IE10(Q) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
* | *color | 青色 | Y | Y | Y | Y | N | Y | N | Y | N | Y |
+ | +color | 綠色 | Y | Y | Y | Y | N | Y | N | Y | N | Y |
- | -color | 黃色 | Y | Y | N | N | N | N | N | N | N | N |
_ | _color | 藍色 | Y | Y | N | Y | N | Y | N | Y | N | N |
# | #color | 紫色 | Y | Y | Y | Y | N | Y | N | Y | N | Y |
\0 | color:red\0 | 紅色 | N | N | N | N | Y | N | Y | N | Y | N |
\9\0 | color:red\9\0 | 粉色 | N | N | N | N | N | N | Y | N | Y | N |
!important | color:blue !important;color:green; | 棕色 | N | N | Y | N | Y | N | Y | N | Y | Y |
說明:在標準模式中
“-″減號是IE6專有的hack
“\9″ IE6/IE7/IE8/IE9/IE10都生效
“\0″ IE8/IE9/IE10都生效,是IE8/9/10的hack
“\9\0″ 只對IE9/IE10生效,是IE9/10的hack
3.選擇器前綴法
選擇器前綴法是針對一些頁面表現不一致或者需要特殊對待的瀏覽器,在CSS選擇器前加上一些只有某些特定瀏覽器才能識別的前綴進行hack。
*html *前綴只對IE6生效
*+html *+前綴只對IE7生效
@media screen\9{...}只對IE6/7生效
@media \0screen {body { background: red; }}只對IE8有效
@media \0screen\,screen\9{body { background: blue; }}只對IE6/7/8有效
@media screen\0 {body { background: green; }} 只對IE8/9/10有效
@media screen and (min-width:0\0) {body { background: gray; }} 只對IE9/10有效
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {body { background: orange; }} 只對IE10有效
等等
3.js 能力檢測
引言
我們知道,各個版本的瀏覽器有著許多不一致性。理想狀態下,應該是所有的瀏覽器都提供一套標準的API接口。但是現實中,各個版本的瀏覽器存在的怪癖非常多,我們通常都是使用客戶端檢測來作為補救措施。但是我們應該知道,不到萬不得已,不要使用客戶端檢測。只要能找到更通用的方法,就應該優先采用更通用的方法??傊?。先設計最通用的方案,在使用特定于瀏覽器的技術增強該方案
1、能力檢測
最常用的也是最廣泛使用的客戶端檢測技術是能力檢測(特性檢測)。能力檢測的目標不是識別特定的瀏覽器,而是識別瀏覽器的能力。使用這種方式無需顧及瀏覽器如何如何,只需確定瀏覽器是否支持特定的能力,就可以給出相關的方案。其基本默認如下:
1/特性檢測
2 if (object.propertyInQuestion) {
3 //使用object.propertyInQuestion
4 }
舉例來說,IE5不支持document.getElementById這個DOM方法。盡管可以使用非標準的document.all屬性實現相同的功能。但是早期的IE的確不支持document.getElementById。所以通過下面的特性檢測來保證瀏覽器的兼容性。請看下面的例子:
function getElement(id) {
if (document.getElementById) {
return document.getElementById(id);
}
else if (document.all) {
return document.all[id];
}
else {
throw new Error("瀏覽器版本太老了,不存在搜索DOM接口");
}
}
我們看到方法是想返回指定Id的DOM元素。document.getElementById()是實現這一功能的標準方式,所以首先檢測它。如果瀏覽器不支持這個方法,那么久退而求其次使用document.all屬性來實現類似的功能。如果這兩個特性都無法使用,那么說明這個方法無法使用了。
第二個重要的概念在于:必須檢測實際要用到的特性。一個特性存在,并不意味著另一個特性也存在。請看下面的例子:
1 function getWindowWidth() {
2 //假設是IE瀏覽器
3 if (document.all) {
4 //錯誤的用法
5 return document.documentElement.clientWidth;
6 }
7 else {
8 return window.innerWidth;
9 }
10 }
這是一個錯誤使用能力檢測的例子。在這個例子中,首先檢測document.all這個特性。然后使用document.documentElement.clientWidth返回窗體的寬度。IE8之前的瀏覽器確實不支持window.innerWidth屬性。但是document.all屬性成立的瀏覽器并不是只有IE。Opera也支持這個屬性,也支持window.innerWidth。我們使用到了document.documentElement.clientWidth,這個也是需要進行特性檢測的。
2、更可靠的能力檢測
能力檢測對于想知道某個特性是否會按適當的方式行事非常有效。我們在上面介紹的利用類型轉換來確定某個對象成員是否存在,但這樣是還是不知道該成員是不是你想要的。下面我們來看一個例子:
1 //不要這樣做,這只是檢測了是否存在相應的方法--這不是能力檢測
2 function isSortable(object) {
3 return !!object.sort;
4 }
這個函數通過檢測對象是否有sort方法來確定對象是否支持排序。但是如果一個對象包含了sort屬性,那么也會返回true。這會導致一些問題。所以更好的方法是檢測sort是否是一個函數。例如:
1 function isSortable(object) {
2 return typeof object.sort === "function";
3 }
這里的typeof操作符用于確定sort的確是一個函數。所以后期可以使用sort進行排序。
4.html5shiv.js
html5shiv.js讓IE6、IE7、IE8支持html5
1.插件介紹
用于解決IE9以下版本瀏覽器對HTML5新增標簽不識別,并導致CSS不起作用的問題。所以我們在使用過程中,想要讓低版本的瀏覽器,即IE9以下的瀏覽器支持,那么這款html5shiv.js是一個非常好的選擇!
上面這段代碼僅會在IE瀏覽器下運行,還有一點需要注意,在頁面中調用html5.js文件必須添加在頁面的head元素內,因為IE瀏覽器必須在元素解析前知道這個元素,所以這個js文件不能在頁面底部調用。
2.相關圖片
3.使用方法
<!--[if lt IE 9]>
<script type="text/javascript" src="http://www.ijquery.cn/js/html5shiv.js"></script>
<![endif]-->
4.相關操作
html5shiv.js操作指南
5.下載
html5shiv.js下載
5.respond.js
Respond.js讓IE6-8支持CSS3 Media Query
Bootstrap里面就引入了這個js文件,從名字看出來是自適應的兼容。打開IE看了一下,效果挺好的,自適應的效果挺好的。Respond.js讓不支持css3Media Query的瀏覽器包括IE6-IE8等其他瀏覽器支持查詢。
使用方式
官方demo地址:http://scottjehl.github.com/Respond/test/test.html
1.在css中正常用 min/max-width media queries
2.引入respond.min.js,但要在css的后面(越早引入越好,在ie下面看到頁面閃屏的概率就越低,因為最初css會先渲染出來,如果respond.js加載得很后面,這時重新根據media query解析出來的css會再改變一次頁面的布局等,所以看起來有閃屏的現象)
實現思路
- 1.把head中所有<link rel=“sheetstyle” href=“xx”/>的css路徑取出來放入數組
- 2.然后遍歷數組一個個發ajax請求
- 3.ajax回調后僅分析response中的media query的min-width和max-width語法,分析出viewport變化區間對應相應的css塊
- 4.頁面初始化時和window.resize時,根據當前viewport使用相應的css塊。
respond.js總結
優點:壓縮后僅1k,不跨域時性能ok,只需引入respond.js通用易用
缺點:僅支持media query的min-width和max-width(用于響應式夠用);支持跨域,雖然配置有點麻煩,實現跨域代價高而且有閃屏體驗欠佳。
6.css reset
1.css 重置
重置樣式表的目標是減少瀏覽器在缺省行高,標題頁邊距和字體大小等方面的不一致性。重置樣式經常出現在CSS框架中。(CSS reset的作用是讓各個瀏覽器的CSS樣式有一個統一的基準,而這個基準更多的就是“清零”?。?/p>
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
2.CSS reset的濫用
物極必反,在集體主義的亞洲國家,從眾服從以及跟風是相當常見的,這在CSS reset的應用上可見一般,Eric在其reset代碼頁面中提到:要根據您自己的要求做修改。然而,目前的狀態是(尤其一些中小型網站),CSS reset代碼直接拷貝過去,也不做一番思考,我真是哀其不幸,怒其不爭。我今天就見到了這么一行CSS reset代碼:
body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, button, textarea, p, blockquote, th, td { margin: 0;padding: 0; }
看到這樣子的CSS代碼我只能無奈的搖搖頭,浮躁的不嚴謹這些詞立馬涌現在我腦中。姑且先不說CSS reset這東西的出現以及推崇就是個錯誤,光看看這段樣式代碼,我就吐血三升了。我想,有類似這段樣式代碼的網站不在少數,但是卻是很屎的一段CSS樣式代碼。
1.div
標簽默認有margin
值嗎?有padding
值嗎?怎么會想到應用div{margin:0; padding:0;}
屬性呢?真是畫蛇添足,多此一舉。
-
dt
標簽有默認的margin
與padding
值就是0,這里為什么還要使用呢? -
li
標簽默認有margin
值嗎?有padding
值嗎?壓根就沒有,也不自己測測,還沒事找事設置個li{margin:0; padding:0;}
聲明,真是衰! -
code
標簽是個屬于inline
水平的元素,居然也扯到margin
與padding
的重置,真是好笑。 - 還有,像
form
,input
,button
,textarea
這樣子的表單元素,有margin
值嗎?有padding
值嗎?我真是不解! -
fieldset
,legend
這兩個90年代的標簽你的網站上使用了嗎?使用概率不足1%的標簽也拿來重置,我實在無語了。 - 還有
th
,td
這些標簽,幸好沒有寫上table
與tr
標簽,否則我一起痛批一段。
在我看來,就算要CSS默認屬性要reset重置,也應該如下:
body, dl, dd, h1, h2, h3, h4, h5, h6, p, form{margin:0;} ol,liul{margin:0; padding:0;}
這樣子的CSS reset才是高效的,簡潔的,其他一些標簽都要通通的去掉,完全沒有必要。
3.CSS reset的不足
CSS文件的大小
顯然,CSS reset平白無故的增加了CSS文件的大小,雖然,增加的大小可能有限,但是,要知道,即使0.1秒的載入時間差異也會影響互聯網企業的收入的。
樣式的重置
許多的CSS樣式要重寫與重新覆蓋,典型的多此一舉。
CSS的渲染
這可以說是最大的問題,樣式無緣無故增加了很多的渲染,想想看,一個項目或是一個頁面中有多少個div標簽,居然使用div{margin:0; padding:0;}
當然,*{margin:0; padding:0;}
更是無法容忍的。
7.Normalize.css
Normalize.css 是?
Normalize.css 是一個可以定制的CSS文件,它讓不同的瀏覽器在渲染網頁元素的時候形式更統一。
Normalize.css
是一種CSS reset
的替代方案。經過@necolas和@jon_neal花了幾百個小時來努力研究不同瀏覽器的默認樣式的差異,這個項目終于變成了現在這樣。
我們創造normalize.css
有下面這幾個目的:
- 保護有用的瀏覽器默認樣式而不是完全去掉它們
- 一般化的樣式:為大部分HTML元素提供
- 修復瀏覽器自身的bug并保證各瀏覽器的一致性
- 優化CSS可用性:用一些小技巧
- 解釋代碼:用注釋和詳細的文檔來
Normalize.css
支持包括手機瀏覽器在內的超多瀏覽器,同時對HTML5元素、排版、列表、嵌入的內容、表單和表格都進行了一般化。盡管這個項目基于一般化的原則,但我們還是在合適的地方使用了更實用的默認值。
與 css reste區別
- Normalize.css 保護了有價值的默認值
Reset通過為幾乎所有的元素施加默認樣式,強行使得元素有相同的視覺效果。相比之下,Normalize.css保持了許多默認的瀏覽器樣式。這就意味著你不用再為所有公共的排版元素重新設置樣式。當一個元素在不同的瀏覽器中有不同的默認值時,Normalize.css會力求讓這些樣式保持一致并盡可能與現代標準相符合。 - Normalize.css 修復了瀏覽器的bug
它修復了常見的桌面端和移動端瀏覽器的bug。這往往超出了Reset所能做到的范疇。關于這一點,Normalize.css修復的問題包含了HTML5元素的顯示設置、預格式化文字的font-size問題、在IE9中SVG的溢出、許多出現在各瀏覽器和操作系統中的與表單相關的bug - Normalize.css 不會讓你的調試工具變的雜亂
使用Reset最讓人困擾的地方莫過于在瀏覽器調試工具中大段大段的繼承鏈,如下圖所示。在Normalize.css中就不會有這樣的問題,因為在我們的準則中對多選擇器的使用時非常謹慎的,我們僅會有目的地對目標元素設置樣式。
4. Normalize.css 是模塊化的
這個項目已經被拆分為多個相關卻又獨立的部分,這使得你能夠很容易也很清楚地知道哪些元素被設置了特定的值。因此這能讓你自己選擇性地移除掉某些永遠不會用到部分(比如表單的一般化)。
5. Normalize.css 擁有詳細的文檔
Normalize.css的代碼基于詳細而全面的跨瀏覽器研究與測試。這個文件中擁有詳細的代碼說明并在Github Wiki中有進一步的說明。這意味著你可以找到每一行代碼具體完成了什么工作、為什么要寫這句代碼、瀏覽器之間的差異,并且你可以更容易地進行自己的測試。
8.Modernizr
Modernizr是什么?
Modernizr是一小段JavaScript代碼,可自動檢測用戶瀏覽器中下一代Web技術的可用性。Modernizr 不是基于UA 將所有瀏覽器列入黑名單,而是使用功能檢測功能,以便根據瀏覽器的實際功能輕松定制用戶體驗。
什么是特征檢測?
在網絡開發的黑暗時代,我們經常不得不求助于UA嗅探,以確定他們的用戶是否能夠使用Awesome-New-Feature ?。實際上,這意味著要做如下的事情
if (browser === "the-one-they-make-you-use-at-work") {
getTheOldLameExperience();
} else {
showOffAwesomeNewFeature();
}
現在看起來不錯,對吧?我們正在使用Awesome-New-Feature ?
,當然它不像舊式的硬皮瀏覽器那樣支持,對吧?今天可能就是這種情況。但是如果該瀏覽器的下一個版本增加了對Awesome-New-Feature ?的支持呢?現在你必須回去審計你的代碼,更新你正在做這個檢查的每一個地方。假設您有時間了解每個瀏覽器的每個功能更新。更糟糕的是,直到你意識到它實際上運行在最新版本中,所有這些用戶getTheOldLameExperience
都無緣無故地回到了辦公室。
那些用戶 - 顯然沒有理由給予一個不合標準的網站 - 實際上可以進入他們的瀏覽器和操作系統設置,并將瀏覽器的名稱(或者user-agent- 在執行UA嗅探時與代碼進行比較)更改為任何他們想要的內容。那時 - 你的代碼是沒有意義的。您正在屏蔽可能實際支持您所有功能的用戶,并可能讓那些不支持的功能出現。幾乎每個人都會受到破壞。一定有更好的方法!
有,它被稱為Feature Detection
,它看起來更像這樣
if (Modernizr.awesomeNewFeature) {
showOffAwesomeNewFeature();
} else {
getTheOldLameExperience();
}
功能檢測實際上是以編程方式檢查Awesome-New-Feature ?是否工作,而不是根據用戶是否在one-they-make-you-use-at-work
瀏覽器上做出決定,并假設這意味著他們要么無法訪問Awesome-New-Feature ?功能瀏覽器,并給你一個或結果。所以,現在只要您最不喜歡的瀏覽器添加了對Awesome-New-Feature ?的支持,您的代碼就會在那里自動運行!沒有更多的必須更新,永遠。代碼最終是相似的,但它的實際意圖更加清晰truefalse
9.postCSS
PostCSS是一個很有趣的項目。簡而言之,它將CSS轉換成抽象語法樹(AST),也就是JavaScript可以操作的一種數據形式?;贘avaScript的PostCSS插件可以執行不同的代碼操作。PostCSS本身并沒有改變你的CSS,它請允許插件執行和轉換你的代碼。