我腦中飄來飄去的css魔幻屬性

最近看到一篇20 個CSS高級技巧彙總的彙總,感觸很深,不過我想,與技巧相比,有些常見css佈局難題,有時候更加讓咱們的平常開發變得躊躇沮喪吧。
在寫這一篇文章以前,本身還寫過一篇:我所不注意的那些CSS冷知識,但卻阻止了我作項目的速度,若是你看了,我相信你也會受益的。css

爲何此處li標籤內的p元素看起來獨自撐開了一行

這是我在segmentfault上看到的一個問題,之前本身遇到過,因此就很熱情洋溢的去回答了一下,難道遇到個本身會的,示例代碼是這樣的:
CSS:html

li{
    display: inline-block;
    text-align: center;
}
.left,.center,.right{
    width:300px;
    height:300px;
}
.left{
    background-color: #999;
}
.center{
    background-color: #ccc;
}
.right{
    background-color: #eee;
}  
HTML:
<ul>
    <li class="left">
        <p style="display: inline-block;">1</p>  
    </li>
    <li class="center"></li>
    <li class="right"></li>
</ul>

測試圖片
大概就是這樣子,其實文和圖有點不對應,代碼中第一個模塊他只寫了一個「1」,我爲了現象更加明顯,且好說明爲何,就打了一大段文字,如今咱們來講說爲何。先來一張圖,看懂vertical-align的幾個屬性,順便帶上圖片出處,文章講得還能夠,理解這張圖片,後面就好理解了。canvas

vertical-align屬性

inline-block的vertical-align 屬性默認是baseline對齊(深刻理解的送福利),也就是英文文字小寫字母a,b,c這類字母底部的那條線,由於這些是外國人發明的,因此以英文字母纔有針對性。inline-block擁有vertical-align屬性,其默認是基線對齊的,因此這三個inline-box須要基線對齊,而其基準線就是正常流中最後一個line box的基線,若是這個元素是空的,沒有內容,那麼這個基線就是最後這個元素的margin-bottom線;若是這個元素不爲空,那麼這個元素的基線就是元素裏面內容最後一行文字的基線;因此咱們一個一個來套,發現這三個li元素在一行,第一個有文字,其基線爲文字底部;最後一個沒有文字,其基線爲margin-bottom線,考試要考,劃重點,能夠本身爲元素設置margin-bottom試試,這就會形成第一個和二,三個錯行的感受,其實他兩是爲了基線對齊,因此多敲幾十個文字就能明顯看出其差異。因此最簡單的解決方案就是爲li添加vertical-align: 屬性不爲baseline,氣不氣,改變其縱向的對齊方式的默認屬性;爲啥非弄個折騰人勒。關於vertical-align,若是還想作這方面的深刻了解,能夠看看張大俠的分析segmentfault

img圖片撐不滿整個div,有空隙

直接上圖更直觀(箭頭所指):
撐不滿的div
相關css和html:瀏覽器

<style>
    body,div{margin: 0;padding: 0;}
    .test{
        background-color: yellowgreen;
    }
    img{
        width:260px;
        height:260px;
    }
</style>
<body>
<div class="test">
    <img width="130" height="130" src="https://user-gold-cdn.xitu.io/2017/12/10/160409cc0f090c6f">
</div>

</body>
其實這個問題,若是你單單這樣看,和我同樣涉世未深的話,是一眼看不出答案的,可是若是你在圖片後面多敲兩個文字,你就會發現,和上個問題,這又是一個有關於vertical-align屬性相關的問題。wordpress

<div class="test">
    <img width="130" height="130" src="https://user-gold-cdn.xitu.io/2017/12/10/160409cc0f090c6f"><span>abcd看文字</span>
</div>

讓人恍然大悟的效果圖:
恍然大悟的效果圖
這下你應該就懂了,下面的空隙的距離實際上等與1個line-height的底邊與baseline之間的間距。仔細觀察,圖片的底邊是和a的下邊緣是在一條水平線上的,而不是和‘看’字下邊緣一條水平線上的。因此爲何上面說這又是一個和vertical-align屬性相關的問題。先說解決方案
針對於父元素div:佈局

  • 設置行高足夠小,好比.test{line-height:0},至於這麼小嗎,其實高度小於top線和baseline線之間的距離的距離就好了,至於到底多小,這和font-size是相關的,其目的就是沒有多餘的高度拿來給baseline下面的空間用(我的理解);
  • 上面說了設置line-height最小和font-size相關,因此,還有的方法,就是直接設置字體大小爲0,.test{font-size:0;},道理你應該懂;

針對於圖片div:測試

  • 上面說了這是一個和vertical-align屬性相關的問題,因此設置vertical-align屬性不爲baseline也能夠解決,好比img{vertical-align:top;},固然也能夠是數字,好比img{vertical-align:-10px;},這個數值絕對不是正值,其數值應該是大於bottom線和line-height的底邊距離的;
  • 最後一種,就是vertical-align是一個對塊狀元素無效的屬性,僅針對於內聯元素有效的,固然inline-block也有效.因此img{display:block;}也能夠解決問題。

也許到這裏,你和我同樣,有疑惑,爲何vertical-align是一個對塊狀元素無效的屬性,設置img爲塊級元素,其和div就能夠完美在一塊兒,而一個內聯元素放在塊狀元素裏,就非得有隔閡。開始,我也是有這個疑問的,我的理解就是塊狀元素裏面裝了一個內聯元素,若是塊狀沒有顯示的設置高度,其高度是由裏面的最高的lineboxes組成的,這個div其實就是有兩個lineboxes組成,圖片linebox和<span>,其實還有一個linebox就是div自身的innerText(''),這不過這裏內容爲空,若是你把span去掉,你就更能理解這個隱身的linebox,因此就像是兩個內聯元素在一塊兒,須要baseline對齊。因此網上有人說設置img{font-size:0;},是很是錯誤的,img元素很特殊,他不可是內聯元素,他仍是一個置換元素(下面會講),它的高度不是文字內容撐開的,是其置換的圖片高度撐開的,因此設置font-size是無效的。字體

浮動不按想要的方式浮

浮動常出現的形式
像上圖那樣的形式,盒子由導航欄和右側一個搜索框或者登陸名什麼的一塊兒組成,這也是咱們經常使用浮動的方式來解決這樣的佈局。
說浮動前,先說三點概念:
1.浮動最初出現的意義是爲了解決文字環繞圖片這種在雜誌報紙中常會出現的佈局樣式; (看下圖)
2.浮動與絕對定位能實現相同的效果,但的區別是,浮動未脫離正常文檔流,但絕對定位脫離了正常文檔流;
3.浮動能帶來靈活的佈局,但同時也帶來了父元素高度塌陷的缺點(看下圖),因此清除浮動是使用浮動前的必修課,後面會說到;
文字環繞
高度塌陷帶來的佈局混亂
如今看一下高度塌陷相關的代碼:flex

<div class="test">
    <img width="130" height="130" src="https://user-gold-cdn.xitu.io/2017/12/10/160409cc0f090c6f">
    1.浮動最初出現的意義是爲了解決文字環繞圖片這種在雜誌報紙中常會出現的佈局樣式;<br>
    2.浮動與絕對定位能實現相同的效果,但的區別是,浮動未脫離正常文檔流,但絕對定位脫離了正常文檔流;<br>
    3.浮動能帶來靈活的佈局,但同時也帶來了父元素高度塌陷的缺點,因此清除浮動是使用浮動前的必修課,後面會說到;<br>
    <br>
    </div>
    <div class="blank"></div>
    <div>
    <div class="box">
        <span class="dot"></span>
        我是下面一個div的文字。
    </div>
        <div class="blank"></div>
    <div class="box">
        <span class="dot"></span>
        我是再下面一個div的文字。。
    </div>
        <input  width="260" value="輸入一段文字"/>
    </div>
      
    .test {
    background-color: yellowgreen;
    font-size: 18px;
    vertical-align: top;
    }
    .test span {
        background-color: bisque;
    }
    .blank {
        line-height: 20px;
        height: 20px;
    }
    img {
        width: 260px;
        height: 260px;
        float: left;
    }
    input {
        border: 1px solid red;
        height: 24px;
        margin-left: 30px;
    }
    .box {
        background: black;
        color: white;
        padding-left: 20px;
        line-height: 10px;
    }
    .box .dot {
        display: inline-block;
        width: 4px;
        height: 4px;
        background: white;
        vertical-align: bottom;
    }

圖片一中,實現了文字環繞圖片那種想要的效果,而且後面的元素沒有上移錯位,其緣由是上面說過的,若是塊狀元素沒有顯示的設置高度,其高度由其元素內的最高的linebox決定,因此第一張圖片div的高度是比img高度高的,由於我重要的事情說了三遍,文字夠多。而第二張圖片,div高度只有144px,由於img是浮動的,他的linebox被浮動屬性破壞了,而文字又不夠多,因此就形成了所謂的高度塌陷,導致最後兩個div陷進了圖片所在的div中,要知道,這種狀況在正常塊狀元素佈局中是根本不會出現的。至於解決浮動引發的高度塌陷,我總結了兩條,分別是:

  1. 使用clear:both,常見的什麼clearfix;
  2. 觸發浮動元素父元素的BFC(塊狀格式上下文,爲解決盒子與盒子之間,內容不相符影響而生的概念);

清除浮動,相信你們都懂,而觸發bfc。

我說說我經常使用的幾條,網上講bfc的不少:

  • float屬性不爲none的元素
  • position(absolute,fixed)
  • display (table-cell,inline-block,flex等)
  • overflow屬性不爲visible

除了上面講的這些,我還遇到過有人問,爲何我用了浮動,但元素沒有浮在這一行,卻換了行,像下圖這樣
浮動不按想要的方式浮

<div>
    <div class="gr">我是導航欄的一些文字</div>
    <div class="fr">我想浮在右邊</div>
   </div>
   .gr{
      background-color: yellowgreen;
      margin:5px;
    }
    .fr{
      float:right;
      background-color: green;
    }

上面這種沒按想要的方式浮,是由於塊狀元素會不敢其內容長度有沒有一行的長度,其都會佔據一行的長度,後面的元素會自動換行。解決這個其最簡單的方式就是將fr元素放在gr元素前,爲何這樣就能夠,由於float破壞了div元素的塊狀屬性,但其未撐開父元素的高度,其浮動屬性爲right,默認從右側開始佈局,因此後面的div仍按正常的文檔流從最左端開始佈局。

有一種行內元素,又叫置換元素

若是你看上面一題代碼的時足夠細心,你會發現我給img設置了width和height兩個屬性值爲130,但因爲又在css屬性裏定義了寬高260,但最終表現出的寬高爲260。若是css不定義寬高呢?答案是多少,要不你試試,你慢慢試,我仍是先公佈答案:130.這裏咱們將會說一個css中的一個不爲人知的術語:置換元素,那什麼又是置換元素呢?

置換元素是指:瀏覽器根據元素的標籤和屬性,來決定元素的具體顯示內容。

例如:瀏覽器根據<img>標籤的src屬性顯示圖片。input元素根據標籤的type屬性決定顯示輸入框仍是按鈕。還有,還有近來很火的canvas。

置換元素有以下共同點:

  1. 置換元素通常內置寬高屬性,所以能夠設置其寬高;
  2. 置換元素與通常的行內元素相比,其能夠設置margin,padding,height,width等css屬性;

感受要寫的還有不少,事件根本不夠用,先睡了,未完待續 若是文中有任何不足和錯誤之處,還請及時指正。

相關文章
相關標籤/搜索