
前言
《CSS世界》這本書可以說是張鑫旭的一本CSS領域的内功心法修煉手冊了,閱讀這本書,其實是為了印證一些自身在CSS學習上的一些東西,是以,有了這篇讀書筆記,記錄一些我不是很清晰的知識點,同時也分享給你,希望對你也有所幫助與啟發。
正文筆記總結
1、僞類選擇器:一般指前面有個英文冒号(:)的選擇器,如first-child或:last-child等。
2、僞元素選擇器:就是有連續兩個冒号的選擇器,如::first-line、::first-letter、::before、::after等。P.S:單、雙冒号都是現在的規範,為了區分僞類和僞元素。IE8僅支援單冒号的僞元素。
3、後代選擇器:選擇所有合乎規則的後代元素。用空格連接配接。
4、相鄰後代選擇器:僅選擇兒子(一層後代)元素,用>連接配接。
5、>、~、+選擇器适用于IE7以上版本。
6、通常把HTML标簽分為兩種:塊級元素和内聯元素。
7、塊級元素和display: block不是一回事,但是它們都具備一個基本特征:一個水準流隻能單獨顯示一個元素。
8、具有換行特性的”塊級元素”(筆記7的綜合體),可以配合clear屬性來清除浮動帶來的影響。
9、實際開發中不會使用display: list-item來配合清除浮動。
理由①:會出現不必要的項目符号·,但是可以通過list-style: none規避。
理由②:IE不支援僞元素設定display: list-item,普通元素設定有效。
10、a标簽預設display是inline。
11、替換元素:根據其标簽和屬性來決定元素的具體顯示内容,即内容可被替換,如input, textarea, select, img, video, object等。
它們具備了一些其他特性,如内容的外觀不受頁面上的CSS影響,有自己的尺寸:像video、iframe、canvas等這些預設尺寸為300X150px,img等則是0,表單無明顯規則。
在很多CSS屬性上有自己的一套表現規則:如vertical-align的預設值為baseline,在非替換元素,對應西方字元x的下邊緣,而替換元素由于幾乎不可能出現字元這種,是以變成了元素的下邊緣。
替換元素尺寸的計算優先級:CSS樣式設定 > HTML内聯屬性 > 固有。如果發生了隻設定了width沒有設定height的情景怎麼辦?最終height = width X 原圖高寬比例。
12、了解樣式屬性的意義,規避不必要的樣式書寫,減少性能損耗:
栗子1:當我們修改a标簽成display: block的時候,它已經具備了塊級特性,即它本身會有流的自然填充性,它會像流一樣自動鋪滿外部容器空間。
但是,如果你設定了寬度,不論是百分比還是固定值,它的流動性就丢失了。見書中提供的width: 100%流破壞和自然流填充對比Demo。
栗子2:*{box-sizing: border-box},這種通配符的屬性選擇器應當盡量避免,因為比如search類型的搜尋框,其預設的box-sizing就是border-box,這種重複指派就是一種損耗,再比如普通内聯元素(非圖檔等替換元素),box-sizing無論是什麼值,對渲染表現都沒有影響,同樣設定這種就是無意義的指派。
13、在本書中,作者将CSS的盒模型分為了”外盒”以及”内盒”,兩者對應具有”外部尺寸”以及”内部尺寸”。流的自然填充性就是依賴于外部尺寸的作用。
14、格式化寬度:該寬度僅出現在position: absolute或position: fixed情形中,這種情形下,寬度表現為”包裹性”,寬度由内部尺寸決定。但是對于非替換元素,如果left/right,top/bottom這種對向屬性同時存在的時候,寬度将會呈現為”格式化寬度”,表現形式就是相對于最近的具有定位特性的祖先元素計算,适應于該包含塊的padding box。
15、在本書中作者有提到”寬度分離原則”,文中的解釋為CSS中的width屬性不與影響寬度的padding/border屬性共存,即外層容器單獨設定width屬性,margin、border、padding利用流動性在内部自适應實作。這種設定的目的在于:使寬度嚴格按照我們預期的設計圖寬度生效,用”人話”來說,width = content-width + padding-width + border-width。
16、當然我們實際使用的時候,提供了box-sizing: border-box,這種設定的效果與筆記15中的寬度分離原則一緻。預設情況下是
box-sizing: content-box,即content-width = width+ padding-width + border-width。
17、對height屬性,如果父屬性height為auto,隻要子元素在文檔流中,其設定的百分比值會被完全忽略。舉一個備援的為div設定背景的樣式。
div {
width: 100%; /*多餘*/
height: 100%; /*無效*/
background: url(bg.jpt);
}
這樣設定的結果就是高度永遠為0,實踐的結果是百分比高度值要生效,其父級必須有一個可以生效的高度值。規範中如此描述:如果包含的高度沒有顯示指定(即高度由内容提供),且該内容非絕對定位,則計算值為auto,而auto自然是沒辦法跟百分比計算的。
18、根據浏覽器渲染順序,其實按DOM自上而下渲染,可以看出嵌套的樣式外部是先固定下來的,是以不存在那種不斷根據自适應改變進行無限的寬高變化。
19、max-width和max-height的應用場景一定是自适應布局或流體布局中:以一個最常見的适配場景為例,雖然我們現在使用的顯示器大多數都是預設1920X1080分辨率的,但是,還是有很多以前的小螢幕分辨率機型,這種可能是古董桌上型電腦,也有可能是小屏的筆記本電腦。我自身在工作時,就遇到過筆記本是1600X900分辨率的業務,此時,通過這兩個屬性就能讓寬度在設定的區間内自适應:
.container {
min-width: 1600px;
max-width: 1920px;
}
除此之外,它們的相容性很好,IE7開始就支援了。
20、以前我的認知裡面!important對樣式的權重是最高的,但是像max-width屬性如果小于width屬性将會直接将其覆寫,如果大于,當然還是以width顯示。
21、同時存在min-width和max-width的描述,那麼最大者生效。
22、max-width和max-height的初始值是none,min-width和min-height的初始值是auto。
23、max-height的一種應用:任意高度元素的展開收起動畫技術,傳送門。這種是原生的CSS3實作,傳統可以用JQ的slideUp()或slideDown()。
如果元素内容是固定的,即高度固定時,可以用height+overflow: hidden實作。當内容是不确定的時候,想通過動畫操作實作從0到内容高度,那麼動畫結束的樣式應該是height: auto,前面我們也記錄過,auto沒辦法和百分比計算。
此時我們改用max-height,隻需要保證它是一個比展開的内容高度值更大的值即可。那麼在動畫計算的時候,取的就是height的計算高度。
當然這個max-height在文中還有别的限制,因為其在過高的情況下,由于收起恢複到原本高度需要時間,并且在變化過程中區域不會被隐藏,會給人一種延遲感。
綜上,max-height的取值應當是一個比内容高度高,同時不能高出太多的值,怎麼界定太多呢,即視覺殘留不能有明顯的延遲感。
24、移動端的CSS3動畫支援良好,是以移動端的JS架構都是沒有動畫子產品的(原文,本人沒确認過)。
25、假想盒:規範中有如此描述,每一個行框盒子前,會有一個寬度為0但是具有元素字型和行高屬性的内聯盒子,我們把這個假想盒稱為支柱。注:假想盒僅在HTML5文檔聲明中出現。
26、Web開發時,為了提高加載性能以及節約帶寬費用,首屏以下的圖檔會通過滾屏的方式異步加載。常采取的方案是直接使用<img>占位,然後設定樣式:
img { visibility: hidden; }
img[src] { visibility: visible; }
注,此處的<img>是直接沒有src屬性。因為即便是src="",在很多浏覽器下依然會有請求,并且請求的是當頁資料。
27、内聯标簽設定寬高樣式是無效的,但是可以通過轉換display成塊級生效。
28、img标簽在Firefox下帶src屬性時,不會被識别為替換元素,而是普通内聯元素,即會有筆記27的問題。
29、基于僞元素的圖檔内容區域預處理技術,這個demo我覺得挺有意思的,見傳送門。主要的知識點是,::before和::after這種僞元素作用在img上是有限制的,對IE來講,暫不支援這樣操作,對CHROME和FF。
有額外的附加條件:①不能有src屬性(Both),②不能使用content屬性生成圖檔(Chrome),③需要有alt屬性并有值(Chrome),④::before僞元素的content值會被無視,::after則無問題(FF)。
30、作者觀點:替換和非替換元素之間隻隔一個src屬性。對于CHROME而言,它還需要一個alt不為空的值才會成立。對于IE而言,它的确在沒有src屬性的時候還是表現為替換元素,這是因為IE有個預設的占位替換内容,當src缺失的時候,會預設用這個占位内容去替換(高版本的IE透明化處理了,IE8下會顯示)。
31、作者觀點:替換元素和非替換元素之間隻隔了一個CSS content屬性。見傳送門,這是一個EMOJI替換的處理,不過這種hover下隻是切換樣式,實際上img裡的資源在渲染的時候已經下載下傳了,是以不管切不切換顯示,儲存的都是老圖。
32、替換元素的固有尺寸無法修改,即使用content設定了背景圖後,我們無法調整大小,若是在移動端使用這種方法設定背景,原比例的圖會導緻圖檔模糊(retina螢幕需要2倍圖),推薦使用SVG圖,矢量圖随意縮放不會失真。
33、使用content屬性生成的文本無法被選中也無法被螢幕閱讀裝置讀取也無法被搜尋引擎抓取,即不利于SEO,它隻适合用來生成一些無關緊要的内容,如裝飾圖、序号。
34、:empty僞類選擇器用來比對無内容的元素,用僞元素::after生成的content内容不會影響實體内容。
35、content動态生成值無法擷取。
36、getComputedStyle可以擷取僞元素的計算樣式,window.getComputedStyle(DOM,"::after").content。
37、content内容生成應用:
①輔助元素生成,如清除浮動:
.clear:after {
content: '';
display: 'block';
clear: both;
}
再如等分空間的柱狀圖,傳送門,核心在于通過:before實作底對齊,:after實作兩端對齊。
②字元内容生成:傳送門,原理就是通過@font-face自定義字型集合,然後替換文本内容。除此之外,這個content也可以為Unicode字元,比如\A換行(LF),\D回車(CR)。配合CSS3 animation的loading demo,傳送門。
③圖檔生成,content: url(),适用于png、jpg、svg、ico、base64URL等,但是不支援CSS3漸變背景圖(linear-gradient)。
④利用content開啟符号閉合,一種使用open-quote和close-quote實作的方式:通過 選擇器 { quotes: '前引号插入内容' '後引号插入内容'; }配合選擇器:before { content: open-quote; }以及選擇器:after { content: close-quote; }實作。另一種則是直接把這種quote放到content内容中直接書寫:僞元素before/after選擇器: { content: '你要加的内容'; }。
⑤通過attr屬性設定content内容:img::after { content: attr(alt) },注:attr内可以傳入原生HTML屬性以及自定義data-X屬性且這些屬性不能帶引号。
⑥content計數器:這種應用,需要先掌握幾個核心的方法屬性,{ counter-reset: 變量命名1 數值1 變量命名2 數值2 ···; }這是一個初始化計數器的動作并且能夠同時指定多個計數器,數值内容在CHROME下可以是負數,如果是小數則向下取整;但在FF和IE下不會識别,視作0處理;除了指定數值,還能夠設定none和inherit來取消重置和繼承重置。具體見傳送門。
counter-increment屬性的值可以是counter-reset指定的一個或多個關鍵字,後面可選跟随數字,表示每一次增加的值,預設值為1。counter-increment可以被多次觸發,即在::before和::after中的該屬性都會被觸發,然後通過counter(關鍵字)輸出結果。counter()/counters()方法類似于CSS3的calc()方法,比較有意思的一點是,counter()還能接收第二個參數style,它對應的是list-style-type支援的屬性值,即遞增的顯示可以不隻是單純數字,也可以是羅馬字、英文等,見傳送門。
content裡可以調用多個counter()。counters(name, string,style可選)的string傳參需要引号包圍,并且是必傳,它用來表示子序号的連接配接字元串,那子序号需要重新定義關鍵字麼?其實不需要,counter-reset設定的關鍵字僅對他最近的層級生效(唯一性),即同一個初始名,但其實不同嵌套初始化的不共享這個值,見傳送門。
注:設定了counter/counters方法顯示輸出樣式的DOM在文檔流中必須在設定counter-increment元素的後面才有技數效果。
38、HTML5可以接受自定義标簽,浏覽器預設樣式沒有規範,會被應用預設inline,向下相容,IE8等低版本不識别,會直接顯示其内容。
39、筆記16中,我們知道了設定box-sizing: border-box以後,width成了真正意義上的總寬度。但如果是具有塊狀特性的元素且内部padding足夠大,怎麼樣算足夠大?比如總寬度是100px,橫向左右padding和為120px,那麼最終寬度是120px。
40、對内聯元素來說,它們沒有可視寬度和高度,即clientHeight和clientWidth永遠是0。垂直方向上的行為表現完全受line-height和vertical-align的影響。
41、内聯元素的垂直padding,可以用來擴大連結或按鈕的點選區域,同時不會影響到現有布局,還有一種登陸 | 注冊管道符的demo,見傳送門。
42、對于非替換元素的内聯元素,不僅padding不會加入行盒高度計算,margin和border也不會參與計算,它們的表現形式是在内聯盒周圍發生渲染。
43、padding屬性:
①不支援負值。
②支援百分比,塊級元素div { padding: 50%; }可以撸出一個正方形,但是内聯元素由于有假想盒的存在(筆記25),會有個額外的高度導緻最終寬高不等,解決方案很簡單,其實就是用控制内聯高度的方式即font-size解決該問題:
span {
padding: 50%;
font-size: 0;
background-color: gray;
}
注:padding百分比無論是水準還是垂直方向上都是相對于寬度計算的。
44、頭圖相容性較好的做法(包括IE6在内的大部分浏覽器),傳送門。
45、内聯元素的padding在文字較多的時候可能會出現斷行。
46、标簽元素存在内置padding,ol/ul内置padding機關是px。如果清單中的font-size很小,則li元素内的ul或ol左邊緣就會離文本内容區域很遠,反之font-size很大就會出現項目符号跑到元素外的情況。
當font-size在12px-14px時,22px是一個較好的padding-left設定值,所有浏覽器都能正常顯示。不過為了更佳的體驗,用content計數器用法更舒服。
47、button的padding在設定為0的時候,在FF下依舊會保留左右的padding。可以通過button::-moz-focus-inner { padding: 0; }來解決這個相容問題。
48、IE7下button内文字過多會使左右padding逐漸變大。
49、padding可以配合background-clip屬性實作一些CSS圖形的繪制效果。
50、元素偏移尺寸:對應元素的border box尺寸,如offsetWidth和offsetHeight。
51、元素内部尺寸:對應元素内部區域尺寸,即padding box尺寸,包括padding但不包括border。如clientWidth和clientHeight。
52、元素外部尺寸:對應元素外部區域尺寸,包括padding、border以及margin。即margin box尺寸,沒有原生DOM API,JQ中可以使用$().outerWidth(true)和$().outerHeight(true)來控制。
53、對于margin,元素設定width值或者保持”包裹性”的時候,margin對尺寸沒有影響。隻有在空間可被充分利用的條件下是可以被影響的,那啥是空間可被充分利用呢?比如說有父子DOM嵌套關系,分别有father和son的class,那麼如果在father設定width,son不設定寬度,設定margin就會影響到自身的寬度,以下面代碼為例,最後son寬度就是340px,并且這種條件下,垂直方向的高度也可以改變。
<div class="father">
<div class="son"></div>
</div>
.father {
width: 300px;
}
.son {
margin: 0 -20px;
}
那這種充分利用的特性帶來了什麼實際場景中的應用?比如:一側定寬的兩欄自适應布局,見傳送門。其實本質就是margin來擴充了父級的寬度,然後内部兩欄,一欄為固定死的,另一欄自适應剩餘部分的結果。
再比如表格間隙多餘的最後一項消除的替代方案,舉個例子,我們想要我們的每一條li之間産生20px的間隙,那麼一般來講會設定一個margin-right: 20px;,
但事實上,換行的時候,最後一項就會多出一個間隙,消除手段通常是在這個元素上生成的時候,附加一個margin-right: 0;的樣式類或用CSS3的nth-of-type選擇器(不考慮IE8)。
現在充分利用margin這種改變布局的特性,我們可以在父容器給一個margin-right: -20px;,子元素則根據剩餘部分自适應,那麼多餘的20的px相當于就被抹除了!
54、不同浏覽器的滾動條觸發規則:Chrome是子元素超過content-box尺寸觸發,IE和FF則是超過padding-box觸發。這種規則會導緻padding-bottom在IE和FF下失效。
55、筆記54中我們知道了padding-bottom有相容性問題,即在頁面底部留白時,我們不應使用padding來控制,而可以轉投筆記53中的利用特性,使用margin擴充縱向留白。
56、利用margin外部尺寸來實作等高布局,傳送門,核心見下面代碼:
.column-box {
overflow: hidden;
}
.column-left,
.column-right {
margin-bottom: -9999px;
padding-bottom: 9999px;
}
57、margin的百分比值同padding一樣,無論是水準還是垂直方向上都是相對于寬度計算的。
58、像<h1>、<p>、<ul>這些标簽是有預設垂直方向的margin值的,并且機關是em這種相對字型的機關。這裡作者說了他的了解,我覺得沒啥毛病,即如果margin使用px這種絕對機關,當字型font-size變大了,那麼整個容器其實寬高還是那麼大就會造成内容臃腫在一起。
而使用em它是根據父元素的font-size按比例算的,是以margin會跟着自适應變大,整個容器的排版依舊能夠保持一緻。
59、margin的合并問題:
①:隻發生在塊級元素上(不包括那些通過浮動和絕對定位産生塊級特性的元素)。
②:隻發生在垂直方向上(前提是不通過writing-mode改變方向)。
60、margin的合并場景:
①:相鄰兄弟元素margin合并。
②:父級和第一個子元素或者最後一個子元素的合并(如果父級沒有聲明垂直margin,子級聲明的垂直margin将被合并到父級去,傳送門)。
③:空塊級元素的margin合并(這裡這個空的塊提不提供margin垂直方向上的值,它都會産生合并特性)。
61、引出筆記61前,讓我們先溫習一下啥是BFC,BFC英文全稱是Block Formatting Context,即塊狀格式化上下文。
BFC指的是頁面布局中的一塊區域,它擁有自己獨有的内部渲染規則,不受外部影響,同時也不會影響到外部區域,是以BFC元素是不會發生margin重疊的情況;另外BFC也可以清除浮動帶來的影響,原因也是那個不影響外部區域,假設它無法清除,那就會造成高度坍塌,破壞外部結構。
除此之外,BFC還有一個很關鍵的用處:自适應布局,怎麼自适應?當我們的元素形成BFC以後将不受外部影響,打個比方,如果他們同在一塊浮動容器控制下,那麼這塊BFC将脫離控制,自動填滿刨去其他浮動元素的剩餘空間。
62、如何觸發BFC?
①根元素(即html)。
②float屬性不為none。
③position屬性為absolute,fixed(不為relative和static)。
④display為inline-block,table-cell,table-caption,flex,inline-flex。
⑤overflow不為visiable時(auto、scroll或hidden)。
63、消除margin合并的方式:
對于margin-top合并的情況:
①父元素設定為BFC。
②父元素設定border-top。
③父元素設定為padding-top。
④父元素和第一個子元素之間添加内聯元素進行分隔。
對于margin-bottom合并的情況:
①父元素設定為BFC。
②父元素設定border-bottom。
③父元素設定為padding-bottom。
④父元素和最後一個子元素之間添加内聯元素進行分隔。
⑤父元素設定height、min-height或max-height。
64、margin合并後的計算值:
①正正取大。
②正負相加。
③負負最負(轉成絕對值,取大)。
65、margin合并的意義:
①兄弟元素合并:和em作用類似,為了排版更加舒适。
②父子元素合并:在頁面任何地方嵌套或直接插入空div都不會影響原本的塊狀布局。
③自身margin合并:避免不小心遺落或者生成的空标簽影響原本的排版和布局。
66、margin: auto的問題:這個問題我覺得可以分為兩種情況,第一種是元素沒有設定width和height,注意這裡的設定即便值是auto也算設定,它會自動填充父容器。另一種則是設定了寬高,這個時候前者的填充性被覆寫,根據”剩餘空間”進行配置設定。
67、關于利用margin: auto來進行水準垂直居中的應用,我在<<到底怎麼樣才能水準垂直居中喔>>一文中有對其進行應用的例子,但是那隻是在水準方向上利用了該特性,垂直方向上其實使用的是transform來移動。
那為什麼容器定高,元素定高,margin: auto無法垂直方向上居中呢?因為觸發margin: auto計算的一個前提條件是當width或height為auto時,元素是具有對應方向的自動填充特性的。見筆記66中第二種情況,設定寬高後該特性将被覆寫。是以沒辦法在按這種規則計算配置設定空間。
在前文我提到的另一篇部落格中有另一個方案對絕對定位元素的垂直居中進行控制,即在對向屬性上同時設定值,這個時候該元素會表現為”格式化寬度和格式化高度”,見筆記14。
68、margin: auto的計算需要IE8及以上的浏覽器才能支援。
69、内聯非替換元素的垂直margin無效,但替換元素的垂直margin有效,并且沒有margin合并的問題,是以圖檔永遠不會發生margin合并。
70、tr,td或者display: table-cell,display: table-row的元素margin都是無效的。
71、絕對定位元素非定位方向的margin值無效。
72、定高容器的子元素的margin-bottom或定寬容器的子元素的margin-right無效,這個就比較經典了,我自己在寫需求的時候,就有一個地方需要使用絕對定位設定margin-right定位,但是卻發現無效了。
怎麼了解這個問題呢?當我們想通過margin屬性改變自身位置時,必須是和目前元素定位方向一樣的margin屬性才行,否則設定的margin隻能影響後面的兄弟元素或父元素。這裡的定位方向又是啥?對一般元素,預設流是左側以及上方,那麼隻能通過margin-left和margin-top來影響元素定位。
但是如果通過float: right或者絕對定位設定right屬性,就會改變定位方向,就可以通過另一側設定了。
附:當absolute遇到left/top/right/bottom屬性時,才變成真正的絕對定位元素。其實這裡涉及到一個相對性問題,當設定了一個方向的屬性,那麼那個水準或者垂直方向上的相對性将丢失,那這個相對性到底是個啥呢?
73、border-width不支援百分比值,除了使用固定數值,還支援關鍵詞如thin,等同1px;medium,預設值等同3px;thick,等同4px。
74、border-style預設值為none。你也可以通過設定border-width: 0來重置。文中描述說如果同時對這兩種屬性進行設定,渲染性能最高?
div {
border: 1px solid;
border-bottom: 0 none; /* 渲染性能高的寫法 */
}
75、border-style: dotted在IE下和在CHROME、FF下表現形式不同,前者是小圓點,後者是小方點。
由于CSS的border-radius是在IE9浏覽器才開始支援的,是以之前版本的IE圓角實作可以利用這種特性來hack模拟,本質就是結合overflow: hidden來隐藏多餘點(當我們想單獨得到一個圓的時候)。
.box {
width:150px;
height: 150px;
overflow: hidden;
}
.dotted {
width:100%;
height: 100%;
border: 149px dotted #cd0000;
}
<div class="box">
<div class="dotted"></div>
</div>
76、border-style: double上下兩線border實線,值為1px和2px時,與solid表現形式一緻。當3px開始才有雙線表現,是以有筆記73中的medium預設值。
77、border-color在沒有設定時,預設取color色值。
78、border與transparent的巧妙配合:color: transparent在IE9以上才支援,而border-color: transparent在IE7就支援了。
①右下角background定位:現在CSS3操作直接background-position: right 數值 bottom 數值即可。文中提到的下面這種操作…em…我沒實踐出來。
.box {
border-right: 50px solid transparent;
background-position: 100% 50%;
}
②增大移動端點選按鈕的可觸區域:第一種是在外層嵌套标簽專門控制區域,第二種則是利用其自身的padding或bottom擴充區域大小。
而設定padding在我們使用外部font庫時,可能會造成中間圖案定位問題,是以最佳方案是使用透明border增加點選區域傳送門。
③三角形等圖檔繪制。
div {
width: 0;
border: 10px solid;
border-color: #f30 transparent transparent;
}
79、塊級元素負責結構,内聯元素負責排版。
80、line-height行高的定義是兩條baseline的間距,而baseline又對應着英文字母x的下邊緣。vertical-align的預設值為baseline。而CSS中有一個概念x-height,它對應字母x的高度,等于等分線mean-line到基線baseline的距離。
81、我們常用的vertical-align: middle并不是等分線mean-line處,而是基線往上1/2個x-height處。是以我們有通過vertical-align: middle來進行垂直居中時,其實它并不是容器的垂直居中,而是我們字型樣式的垂直居中。
82、ex機關對應的就是x-height的高度,它是一個相對機關,不管字型字号如何改變,永遠相對于這個變化。那麼這個機關可以怎麼利用呢?比如基于ex機關的天然垂直居中對齊效果執行個體頁面,見傳送門。
83、<div>内容為空的情況高度為0,當添加文字後,高度被撐起,但本質上這個撐起的高度是由行高line-height屬性絕對的而不是font-size。
84、前面我們提到了font-size,現在我們來看看font-size到底作用在啥子地方。首先,line-height的數值屬性和百分比屬性值都是相對于font-size計算的。而vertical-align又是根據line-height計算的,見筆記80。以下面的代碼塊為計算樣例,最終的vertical-align = 16px * 1.5 * -0.25 = -6px。
p {
font-size: 16px;
line-height: 1.5;
}
p > img {
vertical-align: -25%;
}
然後我們看看font-size的關鍵字屬性值。
相對目前元素font-size計算的有:
①larger,<big>标簽對應font-size大小。
②smaller,<small>标簽對應font-size大小。
與目前元素font-size無關,僅受浏覽器設定的字号影響:
①xx-large,和<h1>元素計算值一樣。
②x-large,和<h2>元素計算值一樣。
③large,和<h3>元素計算值相似(偏內插補點在1px以内)。
④medium,font-size的初始值,和<h4>的元素計算值一樣,為16px。
⑤還有與large相對格式的small。
85、浏覽器預設font-size大小是16px,是以設定font-size: 87.5%和font-size: 14px是等價的。
86、Chrome下有一個12px的字号限制,就是文字的font-size計算值不能小于12px,由于Chrome的特殊性,我們通常進行移動端em、rem适配的時候,就不能直接設定。
html {
font-size: 62.5%;
}
這樣計算結果是10px,換算成em,如果是直屬父級,或rem就是1em/1rem,但是Chrome老哥說,我覺得不行,因為隻要小于12px且不為0的大小我就覺得它是12px大小的,什麼?你問是0的時候Chrome怎麼看?那當然是0咯。那怎麼弄呢,可以設定成625%,即100px。既便于計算又不會有之前的問題。
87、希望隐藏logo對應元素内的文字,除了text-indent縮進隐藏外,還可以通過設定font-size: 0。
88、font-family預設值由作業系統和浏覽器共同決定。它支援兩類屬性值,一類是“字型名”,一類是“字型族”,如果字型名包含空格需要使用引号包裹,不區分大小寫,且如果有多個字型設定将遵從從左往右依次比對本地是否有對應的字型。
字型名用法:
body {
font-family: simsun;
}
body {
font-family: 'Microsoft Yahei', 'PingFang SC';
}
字型族分類:
①serif 襯線字型,即那些橫豎撇捺、張弛有度,有深有淺的字型。
②sans-serif 無襯線字型(現在更普适的使用字型),即那些所有筆畫都差不多粗細的字型。
以上兩者還可以和具體字型名寫在一塊,但是必須寫在最後,因為大多數浏覽器下,寫在這兩種屬性後面的字型會被忽略。
body {
font-family: "Microsoft Yahei", sans-serif;
}
③monospace 等寬字型,這種一般針對英文字型而言,即每個字元在同等font-size下寬度相同。這種特性的其中一種應用就是在模拟選擇欄中的solid、dashed這些效果時,使它們長度相當,見穿送門。ch機關結合等寬字型特性進行手機長度校驗這類的寬度控制。ch本身是一個相對機關,它對應着阿拉伯數字0的寬度,CSS3才開始支援該機關。
④cursive 手寫字型
⑤fantasy 奇幻字型
⑥system-ui 系統UI字型
89、font-weight同樣支援關鍵詞屬性和具體的數值,如normal,bold,lighter,bolder,數值從100到900(間隔100為一個關鍵詞),其中400對應normal,700對應bold。關于lighter和bolder是對繼承的font-weight進行解析的,解析規則如下,這裡需要注意的是,系統裡面需要安裝了該字型家族的全部字重字型才能将所有解析情景呈現,否則缺失的字重字型是無法解析的,即沒有表現形式。
90、font-style屬性值有normal,italic,oblique,其中要提的一點差異是italic與oblique,這兩者都是指斜體控制,那麼有什麼差別呢,答案就是如果目前字型有設定專門的斜體字型,那麼italic會取那個專門的“樣式”,如果沒有就會适應成oblique,oblique僅單純地讓文字傾斜。
91、縮寫的font屬性:它的基本文法組成有[ [ font-style || font-variant || font-weight ] ? font-size [ / line-height ] ? font-family ],其中font-size和font-family是必選的。
值得注意的是這種縮寫的font屬性将會破壞部分屬性的繼承性。原文對這塊的例子解釋,我覺得有點繞人的意思,概括下來就是當你想用font内的font-weight屬性時,line-height将會被覆寫成這個值,并且不同浏覽器的這個值是不一樣的,存在相容性問題。另外,由于font-family是必選項,當這個屬性很長的時候,後面繼承的時候就會挂很長的清單。文中提供了如下兩種解決方式:
①設定一個不存在的字型名占位,然後再設定font-family: inherit來重置這個占位字型。
②利用@font face将我們的字型清單重定義為一個字型。
92、關于@font face,我們常在字型圖示技術中應用它:本質是一個定義字型或字型集的變量,它不僅可以簡單定義字型,還包括字型重命名,預設字型樣式設定等。需要我們關注的屬性包括font-family,src,font-style,font-weight和unicode-range。
這裡主要記錄一下src和unicode-range,其餘的前文我們有過描述。src表示引入的字型資源,如果使用系統安裝字型可以使用locale()功能符,該功能符IE9及以上版本才支援。而unicode-range則是可以替換特定字元或者特定範圍内的字元為我們指定的字型(IE8不支援),如下面這個替換前後雙引号的demo。
@font-face {
font-family: quote;
src: local('SimSun');
unicode-range: U+201c, U+201d;
}
.font {
font-family: quote, 'Microsoft Yahei';
}
93、text-indent用于對文本進行縮進控制,我們可以使用text-indent負值隐藏文本内容,這種操作可以應用在将網站的标記放在<h1>這種标題标簽中然後隐藏,利于SEO。關于text-indent為負值的情景,要注意百分比和數值的差別:百分比是根據目前元素的包含塊來運算的,而數值則是目前内聯盒子,見執行個體。有一點需要注意,一些裝置在text-indent負值特别大的時候可能會存在卡頓和性能風險,以及對于一些螢幕閱讀軟體不會讀取越界的内容,将給無障礙閱讀使用者帶來困擾。
94、text-indent僅對第一行内聯盒子内容有效。
95、非替換元素意外的display計算值為inline的内聯元素設定text-indent無效。在生效時,注意是否存在嵌套的子元素,由于繼承性,如果你還想對其進行别的控制,需要在子元素上覆寫這個值。
96、<input>的text-indent值無效,<button>的text-indent有效但是存在相容性問題,IE下百分比根據容器計算,Chrome和FF以及其他Shadow DOM元素浏覽器百分比按照自身尺寸計算。
97、letter-spacing用來控制字元之間的間距,具有繼承性。預設值是normal而非0,支援負值,當值足夠大的時候,會讓字元重疊甚至反向排列。
98、word-spacing與letter-spacing特性類似,但前者僅作用在空格字元上。啥意思呢?它生效的條件是你首先得有空格存在。
99、word-break屬性有normal:預設的換行規則;break-all:允許任意非CJK(中日韓)文本單詞斷行;keep-all:不允許CJK單詞換行,隻能在半角空格或連字元處換行。非CJK的文本行為實際上和normal一緻。目前移動端不支援keep-all屬性。
100、word-wrap在CSS3中有了另外的命名overflow-wrap,但是考慮到相容性問題我們還是用以前的寫法,屬性有normal,正常換行規則;break-world,一行單詞中是在沒有其他靠譜的換行點再換行,這個換行點比較關鍵,具體見傳送門。
101、white-space用于處理元素内的空白字元(包含了Space、Enter、Tab産生的空白)。屬性有normal:合并空白字元和換行符;pre:空白字元不合并,并且内容隻在有換行符的地方換行;nowrap:合并空白字元,但不允許文本環繞;pre-wrap:pre的作用上同時允許文本環繞;pre-line:合并空白字元,但隻在換行符的地方換行,允許文本環繞。
102、white-space設定nowrap時,元素寬度表現為”最大可用寬度”,換行符和一些空格合并,文本一行顯示。以下是常見的應用場景:
①包含塊尺寸過小處理。
②單行文字溢出點點點效果(配合text-overflow: ellipsis)。
③水準清單切換效果,DEMO。
103、text-decoration下劃線和文本重疊問題如何解決?結合text-decoration: none以及設定border-bottom和padding-bottom。
104、text-transform這個屬性就比較有趣了,它是為英文字元定制的,可以将這些字元進行大小寫轉化。屬性也比較簡單uppercase和lowercase。應用價值也極高,比如我們在輸入驗證碼、身份證這些資訊時,如果有強校驗大寫,這種轉化無異于幫我們省了一個重大工序。
105、:first-letter是用來選擇首字元進行操作的,不過這裡的首字元比較特殊,裡面有個比較神奇的設定:就是一些常見的标點符号在:first-letter眼中是”附贈品”,什麼意思呢?當這些附贈品出現在頭部時,它們就像贈品一樣預設受我們的選擇器影響,然後直到我們真正意義上的首字元(商品)變化為止。其次:first-letter生效的前提是display值為block、inline-block、list-item、table-cell或table-caption,其他如table、flex都無效。另外:before僞元素的content内容會影響:first-letter,即裡面的内容将會被優先作用。下面看看它支援的CSS屬性:
①所有字型相關屬性。
②所有背景相關屬性。
③所有margin相關屬性。
④所有padding相關屬性。
⑤所有border相關屬性。
⑥color屬性。
⑦text-decoration等修飾用屬性。
不能使用visibility、display這些去控制顯隐性。
:first-letter具有嵌套選擇的能力,比如<p>下嵌套了一個<span>,<span>外沒内容,能夠直接選擇到span内的首字元。
:first-letter其實是作為子元素存在的,是以在衡量特指度權重的時候,相同屬性聲明,它的級别一定會比父級高,因為先繼承再覆寫。
實際應用:如在字段、金額前加符号标記。
106、:first-line沒有筆記105中”附贈品的”操作,兩者支援的CSS屬性相近。這一類的僞元素選擇器視作子元素,跟前文中一樣,存在總是高一級樣式權重的特征。在标簽嵌套的時候有所不一樣,它不支援table相關屬性(inline-block/inline-table),DEMO。文中對該選擇器的應用舉了個覆寫父級的例子:按鈕具有一個全局的顔色控制,但是按鈕的字型不就被遮了麼,用:first-line指定顔色,就可以規避這個問題。
107、關于顔色的關鍵字:如果浏覽器能夠識别關鍵字,不會有什麼問題,但如果浏覽器無法識别的話,在HTML和CSS中定義的這個關鍵字将會産生不同的解析結果。前者,會有特殊的算法替換這個顔色,後者則會直接使用預設顔色。
108、background-color: transparentIE6就開始支援,border-color: transparentIE7開始支援,但color: transparent從IE9才開始支援(高版本的IE8相容可以透明化,但是使用者實際上使用的都是原生IE8)。
109、currentColor使用目前color計算值,但這是個CSS3變量,IE9+才支援。
110、rgba、hsl,CSS3屬性,IE9+才支援。rgba在低版本中可以使用透明度PNG圖檔以及filter漸變濾鏡來相容。
111、background-color背景色永遠是最低的。
112、一些沒見過的隐藏操作:
①不占據空間、輔助裝置無法通路、同時不渲染,可以使用<script>标簽。
<script>
<img src="1.jpg">
</script>
②不占據空間,輔助裝置無法通路,顯隐的時候可以有transition淡入淡出效果(其實這種應用場景我沒有接觸過,先記錄下)。
.hidden {
position: absolute;
visibility: hidden;
}
③不能點選,不占據空間,鍵盤可通路,可使用clip裁剪。
.clip {
position: absolute;
clip: rect(0, 0, 0, 0);
}
.out {
position: relative;
left: -999em;
}
④可以點選,不占據空間,可以使用透明度。
.opacity {
position: absolute; /* 是否占據空間控制 */
opacity: 0;
filter: Alpha(opacity=0); /* 相容 */
}
113、display: none和background-image的問題:FF中,display: none元素的background-image是不加載的;但在Chrome和Safari中,若父元素是display: none,圖檔才會不加載,僅是本身元素的背景圖display: none,圖檔依舊會去加載。而IE老哥表示,任何情況他都會去加載圖檔。
<img>标簽則不受display: none影響,所有浏覽器都會去請求圖檔資源。有了這種特性,我們就可以利用這種方式去優化我們輪播的加載體驗。
114、visibility具有繼承性,父元素設定hidden後子元素也會被隐藏。另外visibility: hidden并不會影響CSS計數器的計算,但是display: none時,就完全不會參與計算。
115、visibility可以配合transition實作顯隐的過度效果,如transition: opacity 延遲時間。
CSS3中的transition支援CSS屬性visibility。這種延遲顯示的場景有個比較經典的例子:光标移動的過程中,如果不設定延遲效果将會瞬間觸發一些hover動作,可能會造成一些不必要的遮擋,見傳送門。
116、關于視覺障礙使用者的體驗:其實這個問題目前我做的需求都是沒有涉及的,作者對display: none和visibility: hidden兩種情景的螢幕閱讀進行了對比,即visibility的顯隐性在視覺障礙使用者進行操作時,體驗更佳,它能夠精準地讀取目前操作狀态的title資訊。而display顯隐無法通知。
另外,普通元素的title屬性不會被朗讀,需要輔助按鈕等控件元素,如role="button"。注意:visibility: hidden的元素是不會被朗讀的。見文中DEMO,似乎是個反例,但是其實在從顯示到隐藏的這個過程中,區域還沒有消失,是以會被朗讀出來。
117、outline表示元素的輪廓,文法和border屬性非常類似;outline與focus狀态以及鍵盤通路關系密切。Tab鍵可以依次不斷切換focus元素,包括連結、按鈕、輸入框等表單,甚至設定了tabindex的普通根元素。
Shift+Tab可以反向focus。預設狀态下,focus元素會通過虛框或者外發光的形式進行區分和提示,當元素被focus後,敲擊Enter鍵相當于觸發了該元素的click事件。現代浏覽器,點選連結按鈕後已經不會觸發outline效果了,但通過Tab或element.focus()才會觸發發光效果。
118、outline的應用:outline是真正意義上的不占據任何空間的屬性。輪廓寬度設定再厚也不會影響任何其他元素的布局。并且outline輪廓是可穿透的。書中例子有二,①頭像裁剪的矩形镂空效果。②自動填滿螢幕剩餘空間。
119、cursor光标屬性:auto,cursor的預設值,會跟着内容而變化成不同的光标形态;default系統預設光标形态,不會變化,指那種未標明的情形。
none,隐藏光标,比如觀看視訊全屏時,靜止幾秒我們就将滑鼠圖示隐藏掉,有mouseover再重新顯示,注意這裡cursor: none的相容性是IE9+,即IE8下要做相容處理,可以通過自定義透明光标(Chrome弄一張透明PNG)實作,傳送門。
代碼中出現了:root選擇器,首先這是一個根元素選擇器,html就是我們的根,其次這是一個CSS3屬性,相容性IE9+。還有一些常用的如pointer、text就不全部贅述了。
120、direction主要關注2個屬性ltr預設值以及rtl,分别代表從左到右left to right以及右到左。它負責的東西很關鍵,就是改變水準流向,比如交換按鈕位置,圖檔左右互換等等。
121、unicode-bidi,這個屬性是配合direction一起使用的,因為direction其實隻能改變圖檔或按鈕的呈現順序,而對純字元内容無能為力(尤其是中文字元),這個時候就需要兄弟unicode-bidi幫忙了。
bidi的全寫英文是bidirectionality,它意味着雙向性(阿拉伯文是從右往左讀的),它幫助規範字元出現雙向性時該有的表現,預設值為normal,表示正常排列,而embed隻能作用于内聯元素上,并且embed屬性不會受外部嵌套的元素屬性設定影響(相當于自身開了個内嵌區域,自己操作),傳送門。
bidi-override,會強制所有字元按照direction設定的方向反向排列。embed和bidi-override可以使用特殊字元替代。
122、writing-mode就比較牛逼了,它可以将頁面預設的水準流改成垂直流。預設值為horizontal-tb很好了解,horizontal水準,tb,topbottom,即水準方向從上到下排列。由于不同浏覽器和版本支援的屬性都有所不同,作者整理出了幾個需要關注的屬性:
.example {
writing-mode: lr-tb | tb-rl | tb-lr; /* IE8+ */
writing-mode: horizontal-tb | vertical-rl | vertical-lr;
}
123、關于float,浮動的本質就是為了實作文字環繞的效果,文章原話。
124、float特性:
①包裹性,由兩部分組成,包裹和自适應性。包裹可以了解為,具有float設定的容器的寬高将會以嵌套的内容寬高為表現。自适應則是浮動元素嵌套的元素如果是多個,将會自适應配置設定剩餘空間。
②塊狀化格式上下文(BFC)
③破壞文檔流
④無任何margin合并
125、筆記124中的第二條中,強調了塊狀化的說法,那麼什麼是塊狀化?即一旦float屬性不為none,則display計算值将是block或者table。像以下的寫法都是備援的:
span {
display: block; /* 多餘 */
float: left;
}
span {
float: left;
vertical-align: middle; /* 無效 控制内聯的你還指望在塊級裡搞事情? */
text-align: center; /* 無效 */
}
126、行框盒子如果和浮動元素的垂直高度有重疊,則行框盒子在正常定位狀态下隻會跟随浮動元素,而不會發生重疊。
行框盒子怎麼了解呢,其實就是我們内聯元素所在的那一層,當浮動元素導緻高度塌陷時,其實塊盒的确發生重疊了,但是内聯元素所在的層則由于有這種特性不會發生重疊。
127、文字環繞其實是由”父級高度塌陷”和”行框盒子區域限制”(筆記126中描述)兩方面作用的結果。”父級高度塌陷”可以通過設定高度來cover但是”行框盒子區域限制”就沒辦法了,是以當你出現設定容器高度與内嵌圖檔高度一樣時,由于内聯下圖檔底部的間隙導緻實際高度大于這個高,後面的文本就會産生環繞。
128、IE8以下的浏覽器産生浮動,文字會浮動到下一行内容顯示。這與我現在的認知IE8+的同行浮動顯示不同。
129、浮動元素的作用機制:
①浮動錨點:float所在流中的一個點,這個點本身并不浮動,表現得像一個沒有margin、border和padding的空内聯元素。作用就是産生”行框盒子”:在沒有”行框盒子”進行浮動參考時(比如浮動元素前後都是塊級時),提供參考。
①浮動參考:浮動元素對齊參考的實體。浮動元素進行對齊的實體就是目前float元素的”行框盒子”,而非外部包含塊盒。
130、官方文檔對clear屬性的解釋是:元素盒子的邊不能和前面的浮動元素相鄰。是以其實這個值真正意義上定義的是設定了clear屬性元素本身的行為,而不是float元素的行為。
預設是none,即左右浮動正常作用于本身,left左側抗拒浮動,right右側抗拒浮動,both兩側抗拒浮動。在我們實際應用場景中使用clear來清除浮動其實使用clear: both即可,因為clear: left\right都可以用前者替代。文中有一個DEMO比較好地闡釋了什麼clear針對的前面的浮動元素:
li {
width: 20px; height: 20px;
margin: 5px;
float: left;
}
li: nth-of-type(3) {
clear: both;
}
以上樣式為第三個li設定clear: both,假設我們有10個<li>元素,最終隻會形成2行排列而不是三行。首先最基本的一點,li是塊級元素,在float: left;的作用下,才會出現單行的情景,然而clear: both事實上隻針對前面的浮動,是以第三個li本身恢複塊級排列到了第二行,其後的浮動不受影響跟着第三個li到第二行。綜上所述,當我們遇到需要屏蔽浮動的場景統一使用clear: both。
131、clear屬性隻有塊級元素才生效,而::after等僞元素預設都是内聯水準,這就是為什麼我們在清除浮動的時候往往還需要同時設定一個display屬性的原因,比如下面這種:
.clear:after {
content: '';
display: table/block/list-item;
clear: both;
}
132、clear隻能在一定程度上消除浮動的影響,因為clear: both這種本質上是使自身不和float元素在一行顯示,是以float一些特性還是會被保留。比如:
①clear: both元素前也是浮動元素,即使margin-top負值設為-9999px也無效。
②clear: both後面元素依舊可能發生文字環繞現象。
133、再看看overflow,它才是最适合進行清除浮動的控制屬性。為什麼呢?因為它不會影響原本的流體特性或寬度表現。而其他的CSS聲明基本都會讓元素産生”包裹性”。
134、overflow屬性本身是為了對溢出元素的内容進行裁剪而設計的,并且裁剪邊界的判定是以border box為基準而非padding box。,執行個體。
135、overflow屬性有一個典型的相容問題,即在Chrome浏覽器下如果容器支援滾動,則padding-box也會被計入滾動尺寸内,表現形式就是拖到容器最下方,若有設定padding,Chrome下将會有留白,而IE和FF不會計算這個padding,即不會有留白問題。
136、IE8以上開始支援overflow-x和overflow-y屬性,它們提供的屬性跟overflow一緻:
①visible: 預設值。
②hidden: 剪裁。
③scroll: 滾動條區域一直在。
④auto: 不足以滾動時沒有滾動條,可以滾動時滾動條出現。
但是,overflow-x和overflow-y有互相限制:除非overflow-x和overflow-y屬性值都是visible,否則visible會被當作auto解析。看看下面這個例子:
html {
overflow-x: hidden;
overflow-y: auto; /* 多餘,如果不設定,預設是visible,又因為其中一個不是visible,是以這個預設最終會被當auto解析 */
}
137、textarea和html元素是預設可以産生滾動條的。因為它們預設的overflow不是visible,IE8開始都是使用auto作為預設屬性,即預設狀态下是沒有卷軸框的,隻有當内容溢出時才出現。而IE7的表現就是如同設定了overflow-y: scroll一樣(為什麼說如同,見筆記136),一直保有垂直卷軸框。
138、PC端,無論什麼浏覽器,預設滾動條都是來自html,如果想去除預設滾動條可以直接通過如下樣式設定剔除:
html {
overflow: hidden;
}
139、移動端使用筆記138中的方式就不一定能夠隐藏預設滾動條了,PC端的滾動高度可以使用document.documentElement.scrollTop擷取,而移動端需要使用document.body.scrollTop擷取。那結果已經很明顯了,使用body元素選擇器即可:
body {
width: 400px;
height: 100px;
overflow: auto;
}
這裡的寬度雖然是400px,但要注意到其實滾動條本身會占據空間,在WIN7系統下的IE7+、Chrome、FF浏覽器卷軸框所占據的寬度均為17px。
關于滾動條占據空間帶來最大的影響是水準居中布局可能會産生晃動,因為窗體預設沒有滾動條,而HTML内容是自上而下加載的,就會發生一開始沒有滾動條,然後突然出現滾動條的情況,此時頁面的可用寬度發生變化,水準居中重新計算,就會發生頁面晃動。比較簡單的做法是:
html {
overflow-y: scroll;
}
但這樣雖然橫向的overflow最終計算就是auto了,并且在頁面比較高的時候還湊合,但是如果頁面就隻用一屏,右側還是始終有卷軸框就不合适了。
下面是作者提供的讓頁面滾動條不發生晃動的技巧:
html {
overflow-y: scroll; /* for IE8 */
}
:root {
overflow-y: auto;
overflow-x: hidden;
}
:root body {
position: absolute;
}
body {
width: 100vh; /* 移動端100% */
overflow: hidden;
}
140、自定義浏覽器滾動條:IE的自定義效果要比原生的還差;支援-webkit-字首的浏覽器可以使用以下屬性:
::-webkit-scrollbar整體部分。
::-webkit-scrollbar-button兩端按鈕。
::-webkit-scrollbar-track外層軌道。
::-webkit-scrollbar-track-piece内層軌道。
::-webkit-scrollbar-thumb滾動滑塊。
::-webkit-scrollbar-corner邊角。
實際開發中使用其中3個就夠了:
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-thumb {
background-color: rgba(0,0,0,.3);
border-radius: 6px;
}
::-webkit-scrollbar-track {
background-color: #ddd;
border-radius: 6px;
}
141、錨點是如何跳轉的就不贅述了,主要記錄一下錨點行為的本質:通過改變容器滾動高度或者寬度亦可以說是修改scrollTop和scrollLeft來實作(注意不是浏覽器的滾動高度或寬度)。
錨點的定位可以發生在普通容器元素上,并且由内而外,這個由内而外的意思是當普通元素和窗體同時可滾動的時候,會由内而外觸發所有可滾動窗體的錨點定位,假設目前一個是容器盒子的錨點定位,另一個則是頁面的視窗錨點定位,即先定位到内部錨點再在整個頁面視窗定位,見DEMO。
142、設定了overflow: hidden的元素僅是隐藏了滾動條,當内容溢出時,依然可以進行滾動。當然此時滾動條已經消失,無法通過滑鼠滾輪進行操作,但是錨點定位還是可以使得頁面滾動。
143、結合筆記141和筆記142,可以通過錨點切換來做一些簡單的頁籤切換動作。但是在筆記141中的錨點互動中存在由内而外觸發錨點定位的頁面跳動問題,是以我們可以使用另外一種錨點定位方式:focus錨點定位,即類似連結或按鈕、輸入框那種在被focus時發生的重定位現象。
這種方式隻要定位的元素在窗體當中,就不會觸發窗體的滾動。見DEMO。操作的原理就是往清單裡加入一個隐藏的input框并設定id,然後關聯一個label,這一步其實跟那篇<<input與label标簽的關聯>>文章原理一緻,隻不過當我們點選關聯label的同時也focus了我們的輸入框,這才真正實作了滾動切換,并且這種focus實作還能通過TAB來控制。
144、position: absolute和float都兼具”塊狀化”、”包裹性”、”破壞性”等特性。但是當absolute和float同時存在時,float屬性是無效的,是以這兩者沒有理由同時出現。
145、absolute元素的寬高百分比取決于它的包含塊,而這包含塊指的是該元素第一個position不為static的祖先元素。一些基本的計算規則:
①position: statc\relative以最近的塊級元素祖先的content-box計算。
②positoin: fixed以根元素,即浏覽器可視視窗大小計算。
③position: absolute前文提及。
對于absolute元素,内聯元素也能成為它的包含塊;包含塊不是它的父級元素,而是最近的非static祖先或根元素;邊界取padding-box。
146、在移動端,清單和子產品域往往會有一定的留白來回報手指按壓的感覺,比如加深顔色背景,這種留白往往都是通過padding來實作的,那為什麼不用margin呢?因為margin box永遠是透明的。
147、在頁頭放置一個标簽,使用透明border設定,可以規避padding和top/right這種方向屬性的耦合(兩者的數值都要同時修改)。
148、absolute是非常獨立的CSS屬性值,起樣式和行為表現不依賴其他任何CSS屬性就可以完成。我們很多時候使用絕對定位的時候,都習慣在外層嵌套一層relative控制,但其實它自己就能完成這件事,見DEMO。
作者将那些沒有設定方向屬性left/top/right/bottom的絕對定位稱為”無依賴絕對定位”,它可以了解為不占據空間的相對定位。見DEMO。後面作者舉的輸入框校驗提示語的DEMO也很亮,就是利用absolute的不占據空間的優勢而不會破壞最初定好的容器總寬度。傳送門。
雖然以上足以說明”無依賴絕對定位”好處多多,但是最好隻在靜态互動效果上使用,如導航二級菜單的顯示與定位。
149、IE9及其以下版本的浏覽器不支援placeholder占位符效果。那怎麼模拟呢?可以使用前文提到過的label與input關聯,然後focus轉變樣式,定位使用前面的”無依賴絕對定位”就很合适,不會占據空間。
150、absolute在遇到left/top/right/bottom後才真正具有絕對定位的特性,如果僅有一個方向設定了值,那麼沒有設定值的方向依然保有相對特性。
151、前文中,我們曾提到過當對立方向同時發生定位的時候會産生”格式化寬度”,對于absolute元素而言,當它具備”格式化寬度”時,也同時具備了流體特性,如果包含塊的padding box發生變化,這個塊的寬度也會跟着一起變。
152、如果想讓絕對定位元素寬高自适應于包含塊,沒有理由不使用流體特性寫法。因為其不僅跟普通元素持有一樣的水準流動性,在垂直方向上它也可以保持流動性。
153、當絕對定位元素處于流體狀态的時候,它的盒模型相關解析和普通流體元素都是一模一樣的:
①:margin負值可以讓元素尺寸更大。
②:一側margin定值,一側auto,auto為剩餘空間大小。
③:如果兩側均為auto,則平分剩餘空間。
④:絕對定位元素的margin: auto從IE8開始才支援,而普通元素的很早就支援了。
⑤:百分比transform在部分場景可能會造成IOS微信閃退。
154、relative定位具有”無侵入性”,即relative元素自身進行偏移時,不會影響周圍元素的布局。見DEMO。
155、關于relative的定位問題:
①:letf/top/right/bottom的百分比值是相對于包含塊計算的,垂直方向上的屬性百分比值計算跟height的百分比值一樣,都是相對高度計算。是以當包含塊高度是auto時,計算值為0,會導緻偏移無效。即我們要注意到父元素沒有設定高度或者不是”格式化高度”的情況。
②:當relative的對向屬性同時出現的時候,和absolute表現非常不一樣;當水準方向屬性同時出現,隻保留left;當垂直方向屬性同時出現,隻保留top。因為預設文檔流是從左到右,自上而下的。
156、relative的最小化影響:
①盡量不要使用relative,如果想定位某些元素,可以考慮是否能用”無依賴絕對定位”,優勢在筆記148中有記錄。
②如果場景受限,必須使用relative時,務必使其最小化,這個最小化可以了解為便于之後的維護以及規避場景複雜後的樣式問題。前文中,我們曾提到過relative有無侵入性,即它能夠保證不影響之後的元素布局。按書中的一個例子,場景是在某個子產品右上角定位一個圖示:
<img src="xx.jpg" style="position: absolute; top: 0; right:0;"> <!-- not good -->
<div style="position: relative"> <!-- better -->
<img src="xx.jpg" style="position: absolute; top:0; right:0;">
</div>
其實這種relative限制還有一個好處,那就是層疊級别提升,relative比普通元素的層級要高,那麼後面的元素就不會出現可能覆寫前者的情況。
157、position: fixed正常來講,不管在啥地方,都是根據根元素即html來定位的;但我們可以操作一波把它也按照我們的想法根據包裹的父容器定位,因為fixed和absolute一樣,在沒有方向屬性的時候具有相對定位特性。
158、position: fixed的absolute模拟:說實話一開始我看這個解釋挺懵逼的,什麼既不跟随滾動,又被定位元素限制。後面看了下DEMO代碼大概能了解其行為了:
<html>
<body>
<div class="page">
<div class="fixed">
</body>
</html>
html, body {
height: 100%;
overflow: hidden;
}
.page {
height: 100%;
overflow: auto;
}
.fixed {
position: absolute;
}
首先同時适配移動端隐藏根的滾動條,然後自行生成一個page容器來配置滾動條,最後将絕對定位元素脫離文檔流塞進去。
由于這個絕對定位元素不在這個滾動容器内,是以它不會滾動,ok符合第一種情況,然後自身絕對定位,可以使用relative或者overflow等定位剪裁,滿足第二個情況。
那麼這種模拟可以應用在哪種場景呢?比如說我們有一個Modal框點選然後會彈出一個蒙層,如果通過fixed定位,蒙層會無法覆寫浏覽器右側的卷軸框,即當有滾動條時,背景内容在蒙層下依舊可以滾動,無法被鎖定,但是如果用absolute模拟這種問題就被修複了。
不過,如果我們的頁面結構已經固定了,不太适合全局調整的時候,可以結合JS,移動端,我們阻止touchmove事件就能防止滾動,PC端可以通過overflow: hidden來隐藏,但這麼玩前文中有記錄,會導緻頁面晃動,因為卷軸欄也占據了可視寬度,我們可以通過透明border修複這個問題:
蒙層顯示:
var widthBar = 17; //通常情況是17px
var root = document.documentElement;
if (typeof window.innerWidth == 'number') {
widthBar = window.innerWidth - root.clientWidth;
}
root.style.overflow = 'hidden';
root.style.borderRight = widthBar + 'px solid transparent';
蒙層隐藏:
var root = document.documentElement;
root.style.overflow = '';
root.style.borderRight = '';
159、CSS層疊上下文和層疊水準:其實關于層疊的問題,我在<<CSS特指度與布局層疊順序>>一文中曾經結合水印需求讨論過一次,不過那個時候其實隻是取了作者部落格中的一張圖示,在這本書中其實有更為細緻的講解:
①誰大誰上:當具有明顯的層疊水準辨別時,如z-index,在同一層疊上下文領域,層疊水準值大的那一個覆寫小的那一個。
②後來居上:當元素層疊水準一緻、順序相同時,DOM流處于後面的元素會覆寫前面的元素。
③獨立性:每個層疊上下文和兄弟元素獨立,進行層疊變化或渲染的時候,隻需要考慮自身的後代元素;且元素發生層疊的時候,整個元素被認為在其父元素的層疊上下文當中。
④根元素html本身就具有層疊上下文。
⑤對于position為relative/absolute以及FF/IE下含有position: fixed的元素(注意不包括Chrome),當它們的z-index不是auto時,會建立層疊上下文。這裡可以參見一個提供的DEMO。
從DEMO中看到,當元素預設z-index是auto的時候就是一個普通定位元素,容器内的元素進行層疊比較将不會受到父級的影響,可以通過①和②的規律來判斷。就算z-index的值為0,它也會建立層疊上下文。
是以DEMO中,相當于後面的覆寫了之前的,内部由于兩塊都是獨立的層疊上下文,都作用在自己的父容器當中,故不會作用于外面對比,真正進行比較的是兩個父容器。
另外,作者提及在IE6/IE7下,z-index: auto同樣會建立層疊上下文;以前的position: fixed跟absolute/relative一樣都需要z-index有值才會産生層疊,但是後面,在-webkit-核心的浏覽器中fixed定位不需要z-index就可以産生層疊,而IE和FF還是和以前保持一緻。
160、clip從英文看就可以知道是個剪裁屬性,并且它僅在position為fixed或absolute時生效,它的基本文法為clip: rect(top right bottom left),clip: rect(top, right, bottom, left)這種有逗号的寫法其實才是标準的,不過前者相容性更好,IE6、IE7也支援,并且字元更少。那麼它的應用場景在那裡呢?
①首先是對fixed定位進行裁剪,因為fixed本身的包含塊是html,overflow雖然也能進行剪裁作用,但是它主要還是應用于普通元素或絕對定位元素,對fixed元素除了滾動條區域,其他區域也沒辦法操作。
②隐藏首頁上SEO的文本,僅展示圖檔,比如:
<a href="/" class="logo">
<h1>CSS世界</h1>
</a>
.logo h1 {
position: absolute;
clip: rect(0 0 0 0); /* 相當于整塊切割了 */
}
這種做法與其他的一些隐藏做法相比優勢在于具有更強的普适性,任何元素和場景都可以無障礙使用(我們前文有記錄過一些隐藏元素的方案,但是像vibility: hidden;,display: none,text-indent: 足夠到螢幕外的負值這些最終都會導緻螢幕閱讀裝置無法讀取)。
同時元素原本的行為特征也被保留,比如原本能夠被focus的元素,即使剪裁了依舊能夠繼續focus,再利用”無依賴絕對定位”的特性可以實作一種替換預設按鈕樣式的hack操作。文中提供了一個使用關聯label替代input的送出按鈕做法:
.clip {
position: absolute;
clip: rect(0 0 0 0);
}
<form>
<input type="submit" id="someID" class="clip">
<label for="someID">送出</label>
</form>
以上,書中有一種”可通路隐藏”的叫法我覺得挺不錯的,并且在如何進行隐藏的方案中,color: transparent是移動端推薦的做法,但是在PC端IE8浏覽器并不支援。
作者對clip的總結:
①clip隐藏僅僅是決定哪部分可見,非可見部分無法響應點選事件;
②視覺上隐藏,但是元素尺寸依然是原本尺寸;IE/FF浏覽器下抹去了不可見區域尺寸對布局的影響比如生成的滾動條,Chrome則保留了影響。
本文完~
學習更多技能
請點選下方公衆号