一些面試時(shí)關(guān)于 CSS 的問題

1. 水平垂直居中問題

這可以說是最經(jīng)典的問題了姆涩,水平垂直居中账忘,這個(gè)問題從入門前端一直到面試菠齿,甚至到工作之后都會時(shí)不時(shí)遇到佑吝,最近的面試也被問過這之類的問題,這里還是好好總結(jié)一番绳匀,以作備忘芋忿。HTML 部分:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>CSS居中</title>
</head>
<body>
<!-- <div class="grandfather"> -->
    <div id="parent">
        <div id="child"></div>
    </div>
<!-- </div> -->
</body>
</html>

方法一:

設(shè)置子元素 position 為 absolute 炸客,然后讓 top 和 left 都為 50%,再使 margin 為子元素的長和寬的負(fù) 1/2 即可:

說明: 這種方法局限性很大戈钢,不做推薦痹仙。
注意: 此處父元素得添加 postion:relative/absolute ,因?yàn)?absolute 定位是基于最近的設(shè)有 position 的父元素進(jìn)行定位殉了,如果父元素沒有設(shè)置 position 开仰,則其會基于 body 定位。但是如果 body 也沒有的設(shè)置 position 的話則基于視口高度計(jì)算位置:document.documentElement.clientHeight 薪铜≈诠可以試試去掉 parent 的 position 會發(fā)生很奇妙的事呢!
附加: 關(guān)于子元素 position 設(shè)置為 relative 而引發(fā)的問題隔箍。如果此時(shí)父元素的 position 為 absolute谓娃,那么不會有什么奇怪的現(xiàn)象發(fā)生;但是如果此時(shí)父元素的 position 為 relative 蜒滩,那么你會發(fā)現(xiàn)父元素會向上方移動一點(diǎn)距離,這又是為什么呢滨达??俯艰?這涉及到外邊距塌陷(margin-collapse)問題了捡遍,這點(diǎn)在后面的一些2. 外邊距問題中去解釋了(提前透露:父級向上移動了-50px)。
推薦指數(shù): ★

#parent {
    background-color: black;
    position: relative;     /*或者absolute*/
    height: 300px;
    width: 300px;
}

#child {
    background-color: #ccc;
    position: absolute;
    left: 50%;
    top: 50%;
    margin: -50px 0 0 -50px;
    height: 100px;
    width: 100px;
}

方法二:

CSS里面還有一種 display: table-cell 的屬性蟆炊,我們可以將父元素的 display 設(shè)置為 table-cell 屬性稽莉,然后將子元素的 display 設(shè)置為 inline 或者 inline-block ,此時(shí)便可以用我們熟悉的 text-align: center 和 vertical-align: middle 來使得子元素水平垂直居中了涩搓。

說明: 這種方法最適合子元素都為行內(nèi)元素(或者帶有行內(nèi)元素性質(zhì)的塊級元素)的布局污秆,故而可以根據(jù)情況選用。
推薦指數(shù): ★★★☆

#parent {
    background-color: black;
    display: table-cell;
    text-align: center;
    vertical-align: middle;
    height: 300px;
    width: 300px;
}

#child {
    background-color: #ccc;
    display: inline-block;
    height: 100px;  /*可以改為33.3%*/
    width: 100px;   /*可以改為33.3%*/
}

方法三:

方法一中只能解決子元素定大小問題昧甘,有時(shí)候子元素大小變化可以用以下方法解決:

說明: 這種方法非常棒良拼,兼容性也很不錯(cuò),強(qiáng)推充边!
附加: 關(guān)于子元素的 position 設(shè)為 relative 而使得垂直居中無效問題庸推。關(guān)于這個(gè)問題其實(shí)很好理解,因?yàn)榻奖琾ostion: relative 的移動是基于自身原本的位置嘛贬媒,top 、 bottom 肘习、 left 际乘、 right 都為 0 ,換句話說就是位置不動漂佩,然而脖含,你有見過塊級元素能夠 margin: auto 上下自動補(bǔ)齊的嗎罪塔!沒有吧~ 故而起作用的只有左右自動計(jì)算補(bǔ)齊而已,也就只有水平居中對齊了养葵!
推薦指數(shù): ★★★★★

#parent {
    background-color: black;
    position: relative;
    height: 300px;
    width: 300px;
}

#child {
    background-color: #ccc;
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;
    height: 33.3%;
    width: 33.3%;
}

方法四:

由于CSS3的來臨征堪,我們也應(yīng)該跟上時(shí)代的潮流,故而對上述方法有有所改進(jìn)关拒,在此我們可以嘗試一下 transform 元素的 translate 2D 平移佃蚜,讓其想著 X 、Y 軸負(fù)方向移動自身長度的一半距離即可達(dá)到效果夏醉。

說明: 畢竟技術(shù)向新的方向發(fā)展爽锥,可以多嘗試一下新技術(shù),推薦畔柔。
注意: 由于瀏覽器的支持性問題氯夷,使用的時(shí)候可以檢測 CSS 支持性,也可以通過 Autoprefixer CSS online 來寫兼容性代碼靶擦。
附加: 關(guān)于 CSS3 開啟 GPU 硬件加速提升網(wǎng)站動畫渲染性能問題腮考。這一點(diǎn)不知道對此位置平移轉(zhuǎn)換有沒幫助,不過當(dāng)做是拓展來介紹了玄捕,在此我就不詳細(xì)說了踩蔚,推薦看 CSS3 頁面渲染加速
推薦指數(shù): ★★★★

#parent {
    background-color: black;
    position: relative;
    height: 300px;
    width: 300px;
}

#child {
    background-color: #ccc;
    position: absolute;     /*或者relative*/
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    height: 33.3%;
    width: 33.3%;
}

方法五:

這個(gè)是另外一種 CSS3 的解決方法(我比較喜歡)枚粘,即 flex 布局馅闽。通過設(shè)置父元素的 display 屬性為 flex,然后設(shè)置其 align-content 和 justify-content 來使得子元素能夠水平垂直居中馍迄。

說明: 這個(gè)方法在布局上非常靈活福也,在不考慮兼容的情況下,強(qiáng)烈推薦此方法進(jìn)行布局攀圈。這真的是個(gè)非常棒的布局方法暴凑!
注意: 由于瀏覽器的支持性問題,使用的時(shí)候可以檢測 CSS 支持性赘来,也可以通過 Autoprefixer CSS online 來寫兼容性代碼现喳。
附加: 關(guān)于flex的詳細(xì)介紹可以參考阮老師的博客: Flex 布局語法篇 Flex 布局實(shí)例篇
推薦指數(shù): ★★★★☆

#parent {
    background-color: black;
    display: flex;
    display: -webkit-flex;  /*Safari*/
    align-content: center;
    -webkit-align-items: center;
    justify-content: center;
    -webkit-justify-content: center;
    height: 300px;
    width: 300px;
}

#child {
    background-color: #ccc;
    height: 33.3%;
    width: 33.3%;
}

2. 外邊距問題

現(xiàn)象描述

第一種情形是犬辰,當(dāng)你在一個(gè) div 元素內(nèi)插入一個(gè)塊級子元素嗦篱,然后設(shè)置其 margin-top 值,這是你會發(fā)現(xiàn)并不是子元素在父元素內(nèi)撐開了一段距離幌缝,而是父元素向上撐開了一段距離默色。

原以為:                            實(shí)際上:
       body                                body
--------------------               --------------------
      parent                                *
    -----------                             | 50px
         *                                  *
         | 50px                           parent
         *                             -----------
       child                               child
    -----------                        -----------
      parent                              parent
--------------------               --------------------
       body                                body

另一種情況是,當(dāng)你在 div 元素內(nèi)插入多個(gè)塊級元素,你給其中相鄰的兩個(gè)設(shè)置 margin-top 和 margin-bottom 腿宰,你會發(fā)現(xiàn),他們之間的距離為相對應(yīng)的 margin-top 和 margin-bottom 中的最大值缘厢,當(dāng)設(shè)置第一個(gè)塊級元素的 margin-top 屬性則會像第一種情形那樣吃度,父級框移動了。

原以為:
        parent
------------------------
          | 10px
        childA
          | 10px ==> | 30px
          | 20px ==> |
        childB
          | 20px
------------------------
        parent

實(shí)際上:
        body
--------------------------
          | 10px
        parent
    ----------------
        childA
          | max(10px, 20px) ==> 20px
        childB
          | 20px
    ----------------
        parent
--------------------------
        body

問題分析

詳細(xì)解答在官方文檔的 8.3.1 合并 margin 這一節(jié)贴硫,太長了椿每,我就不復(fù)制了,但是簡單來說可以用W3C上的話來總結(jié):

外邊距合并指的是英遭,當(dāng)兩個(gè)垂直外邊距相遇時(shí)间护,它們將形成一個(gè)外邊距。
合并后的外邊距的高度等于兩個(gè)發(fā)生合并的外邊距的高度中的較大者挖诸。

這樣就清楚了汁尺!下面說說我的理解(很實(shí)用):

  1. Case 1:
    父親與兒子并排站(沒邊界嘛,父親位置不定)多律,兒子說:我站在相對前方目標(biāo) 1m 的地方痴突,問:父親站在離前方目標(biāo)多遠(yuǎn)處?
    顯然是 1m 的地方嘛狼荞!因?yàn)槟繕?biāo)不明確(父親也是相對嘛)辽装,故而父親同樣也是站在相對前方 1m 處。
  2. Case 2:
    ChildA: 我站在距離 ChildB 1m 的位置相味。
    ChildB: 我站在距離 ChildA 1m 的位置拾积。
    問: ChildA、ChildB距離多遠(yuǎn)丰涉?
    根據(jù)相對性拓巧,這不就是 1m 嘛!
    依次類比昔搂,很相似吧(沒邊界擋著 == 站在同一起跑線)玲销! (σ???)σ..:*☆ 哎喲不錯(cuò)哦!U贤斜!

問題解決

其實(shí)分析時(shí)已經(jīng)表明了,因?yàn)槎颊驹谕黄鹋芫€逛裤,故而大家都不分先后瘩绒,要讓它們分開,設(shè)置點(diǎn)障礙就行了带族,如:
情況 1:
Method 1: 給父元素添加 border: 1px solid #xxxxxx(劃分界限锁荔,父子沒并排站,兒子前方有了目標(biāo))蝙砌。
Method 2: 給父元素添加 overflow: hidden 屬性(相當(dāng)于父級給自己定了一個(gè)隱藏邊界)阳堕。
Method 3:讓父元素為絕對定位(因?yàn)橄喈?dāng)于讓父元素站在一個(gè)定點(diǎn)跋理,子元素的前方目標(biāo)明確了,是父親相對自己距離為 0恬总,距離也就拉開了)前普。
Method 4:為父元素聲明浮動(浮動會脫離文檔流,此時(shí)瀏覽器會給頂元素位置壹堰,即所能達(dá)到的最左上方)拭卿。

個(gè)人推薦: Method 2。

這個(gè)情況可以說是前一個(gè)情況的完整版贱纠,其實(shí)整體上就是BFC問題(前者也是)峻厚,BFC的詳細(xì)內(nèi)容我就不細(xì)說了,推薦 BFC 神奇背后的原理谆焊。
情況 2:
首先得讓父級元素按照情況 1中方式處理惠桃,其次是處理子元素。
Method 1:自己計(jì)算好相鄰元素的距離懊渡,然后直接設(shè)置刽射。
Method 2:給每個(gè)子元素添加一個(gè) wrapper ,使得每個(gè)子元素都是 BFC 區(qū)域剃执。

個(gè)人推薦: Method 2誓禁。

3. 奇怪的布局問題

現(xiàn)象描述

當(dāng)你在 div 元素內(nèi)插入多個(gè)行內(nèi)塊級元素,你給其中任意一個(gè)或者多個(gè)設(shè)置 margin-top 想要使得它/它們表現(xiàn)得與眾不同肾档,可是摹恰,到頭來所有元素都會移動,而且唯一準(zhǔn)確的只有所設(shè)值最大的那個(gè)子元素怒见,其他子元素則混淆俗慈。

(注:所有子元素高度為 height: 50px)
原以為:
                      parent
----------------------------------------------------
        | 50px        childB               | 25px
      childA                            childC
----------------------------------------------------
                      parent

實(shí)際上:
                      parent
----------------------------------------------------
        | 50px          | 50px + 25px      | 50px - 25px
      childA          childB            childC
----------------------------------------------------
                      parent

問題分析

其實(shí)這個(gè)問題和IFC問題很相似,也就是行內(nèi)元素基線的選擇問題遣耍。 IFC 的介紹中有這么一段話:

IFC ( Inline Formatting Contexts )直譯為"內(nèi)聯(lián)格式化上下文"闺阱,IFC 的 line box(線框)高度由其包含行內(nèi)元素中最高的實(shí)際高度計(jì)算而來(不受到豎直方向的 padding/margin 影響)
IFC 中的 line box 一般左右都貼緊整個(gè) IFC ,但是會因?yàn)?float 元素而擾亂舵变。

這就說到很明白了酣溃。由于這里是 display: inline-block 故而,其線框高度包含了 margin 纪隙、 border 赊豌、 padding 、 content 绵咱,這樣就知道為什么其他元素的 margin 后的結(jié)果與預(yù)期不一致的問題了碘饼。(此處把 childC 的高度變?yōu)?300xp 則是以 childC 的基線為基準(zhǔn)定位其他兄弟元素,因?yàn)榇藭r(shí) childC “最高”)。

友情推薦: 什么是 BFC 艾恼、IFC 住涉、GFC 和 FFC

問題解決

要解決這個(gè)問題,想讓不同子元素呈現(xiàn)不同效果蒂萎,我們可以給每個(gè)子元素添加一個(gè) wrapper 秆吵,并讓 wrapper 以 BFC 的形式包裹子元素,然后你就可以肆無忌憚的改變每個(gè)子元素位置了N宕取(參考1. 水平垂直居中問題

/*wrapper style*/
.wrapper {
    display: inline-block;
    height: 100%;       /*讓 wrapper 基線對齊*/
    overflow: hidden;   /* BFC */
}

其他問題: 為什么其他子元素的 margin: mpx 不是在基線上位置向下移動 mpx 而是向上移動呢?(m > 0)
這個(gè)問題其實(shí)也很好說明主穗,由于此處默認(rèn)對齊方式是都是基于 bottom 的泻拦,故而都是在 bottom 這條起始線開始變化(可以打開瀏覽器看盒子模型), childB 由于沒有 margin 故而其底邊線為此時(shí)公用的底邊界忽媒,其他盒子在此基礎(chǔ)上有 margin-bottom 的開始向上移動(“最高”的盒子會撐高整個(gè)高度争拐,其它盒子只會上升 margin-bottom 值),因此會出現(xiàn)此現(xiàn)象晦雨。

此題代碼

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>CSS外邊距塌陷</title>
</head>

<style type="text/css">
    #parent {
        background-color: black;
        height: 500px;
        overflow: hidden;
        width: 500px;
    }

    #parent div {
        display: inline-block;  /*包含了 wrapper */
    }

    #childA {
        background-color: greenyellow;
        height: 100px;
        margin: 25px 0;
        width: 100px;
    }

    #childB {
        background-color: aliceblue;
        height: 100px;
        width: 100px;
    }

    #childC {
        background-color: orangered;
        height: 100px;
        margin: 50px 0;
        width: 100px;
    }

    .wrapper {
        height: 100%;
        overflow: hidden;
    }
</style>

<body>
    <div id="parent">
        <div class="wrapper">
            <div id="childA"></div>
        </div>
        <div class="wrapper">
            <div id="childB"></div>
        </div>
        <div class="wrapper">
            <div id="childC"></div>
        </div>
    </div>
</body>
</html>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末架曹,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子闹瞧,更是在濱河造成了極大的恐慌绑雄,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奥邮,死亡現(xiàn)場離奇詭異万牺,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)洽腺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進(jìn)店門脚粟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蘸朋,你說我怎么就攤上這事核无。” “怎么了藕坯?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵团南,是天一觀的道長。 經(jīng)常有香客問我堕担,道長已慢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任霹购,我火速辦了婚禮佑惠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己膜楷,他們只是感情好旭咽,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著赌厅,像睡著了一般穷绵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上特愿,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天仲墨,我揣著相機(jī)與錄音,去河邊找鬼揍障。 笑死目养,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的毒嫡。 我是一名探鬼主播癌蚁,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼兜畸!你這毒婦竟也來了努释?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤咬摇,失蹤者是張志新(化名)和其女友劉穎伐蒂,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體菲嘴,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡饿自,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了龄坪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片昭雌。...
    茶點(diǎn)故事閱讀 38,789評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖健田,靈堂內(nèi)的尸體忽然破棺而出烛卧,到底是詐尸還是另有隱情,我是刑警寧澤妓局,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布总放,位于F島的核電站,受9級特大地震影響好爬,放射性物質(zhì)發(fā)生泄漏局雄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一存炮、第九天 我趴在偏房一處隱蔽的房頂上張望炬搭。 院中可真熱鬧蜈漓,春花似錦、人聲如沸宫盔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽灼芭。三九已至有额,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間彼绷,已是汗流浹背巍佑。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留寄悯,地道東北人句狼。 一個(gè)月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像热某,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子胳螟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評論 2 351

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

  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案昔馋? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補(bǔ)...
    _Yfling閱讀 13,741評論 1 92
  • relative:生成相對定位的元素,通過top,bottom,left,right的位置相對于其正常位置進(jìn)行定位...
    zx9426閱讀 933評論 0 2
  • 一糖耸,浮動元素有什么特征秘遏?對父容器、其他浮動元素嘉竟、普通元素邦危、文字分別有什么影響? 浮動模型是一種可視化格式模型,浮動...
    DeeJay_Y閱讀 862評論 0 4
  • 1.浮動元素有什么特征陵且?對父容器、其他浮動元素个束、普通元素慕购、文字分別有什么影響? 何謂浮動元素?有什么特征茬底?所謂浮動...
    草鞋弟閱讀 809評論 0 1
  • 上一篇文章我們講了靜態(tài)代理的實(shí)現(xiàn)方式沪悲,并比較了聚合實(shí)現(xiàn)靜態(tài)代理和繼承實(shí)現(xiàn)效果的不同。今天我們來逐步實(shí)現(xiàn)動態(tài)代理阱表,并...
    偷星辰夜閱讀 900評論 0 0