粉絲羣CSS小測第1期答疑文字版

1、CSS小測第一期題目

題目以下圖,一個很簡單也很經常使用的佈局:php

CSS基礎測試1

左右排布的列表,左側是標籤信息,右側是描述信息。css

在微信粉絲羣裏面發出題目後,總共收到了將近50人的回答,完整回答列表能夠參見此issues:github.com/zhangxinxu/…html

也歡迎關注這個github項目。前端

今天上午在B站進行了答疑直播,本文是整理後的文字版。css3

2、值得商榷的實現

1. 通配符reset的問題

很多回答出現了下面的CSS:git

* { padding: 0; margin: 0; }複製代碼

這是一直偷懶的CSS reset寫法,我我的是不推薦這種寫法的,一來帶來比較多的資源開銷,並且這些開銷徹底是沒有必要的,有種爲了幾棵樹砍掉整個森林的感受,在全部的HTML標籤中,默認有padding值的屈指可數,徹底沒有必要使用通配符進行重置;二來,對於有些元素,默認的margin屬性是有用的,比方說表單元素中的單選框和複選框,其默認margin值能夠和後面文字保持合理的間距,若是使用通配符重置,就會擠成一坨,閱讀體驗並很差。github

2. 容器定高的問題

有人在實現的時候,容器寫死了高度,實際開發的時候咱們不能保證需求會不會變更,比方說增長一個條目的數據。若是咱們的容器高度是定死的,那必然增長新條目的時候會出現佈局上的bug,會下降容錯性和可維護性,所以,避免定高。面試

3. 50%的問題

可能有將近1/3的人,在實現這種佈局的時候,都是dtdd寬度各佔50%,不管是左右浮動,flex佈局或者使用inline-block排列。瀏覽器

示意以下:安全

dt, dd{
    width: 50%;
}
dt{
    float: left;
}
dd{
    float: right;
    text-align: right;
}複製代碼

若是是應付這條題目呢,能夠說是勉強及格,可是若是放在實際開發中,則侷限性就會比較大。因爲dd標籤中的內容是動態的,可能就會出現長段的相似於備註這樣的選項,此時dd 50%寬度就會有問題,在在移動端,咱們顯示的寬度可能就只有300多像素,因而,佈局可能就會表現成這樣:

右側寬度過小了

並且根據個人測試,通常容器的寬度小於290像素,時間也會掉下來,由於,50%並非一個實際開發中的最佳取值,能夠調整下。比較好的作法是,左側安全寬度,右側自動分配剩餘空間。

4. absolute實現的問題

這是一個使用dd標籤進行絕對定位的案例:

dd絕對定位案例

使用dd標籤一個一個絕對定位,最大的問題在於,維護性太糟糕了,若是要新增一個條目必然要從新再寫一段CSS,若是這裏有20行數據,難道還要再增長20多個語句?

實際上,dd標籤絕對定位是可使用的,可是,沒有必要使用top進行一個一個定位,以下修改:

absolute絕對定位的實現

其餘那些洋洋灑灑的CSS都是多餘的,就下面這幾行足夠了,兼容性很是OK。

dl {
  border: 1px solid #000;
  position: relative;
}
dd {
  position: absolute;
  right: 0;
  margin: -1.2em 0 0 0;
}複製代碼

爲何有用,這裏不展開,《CSS世界》這本書的絕對定位部分有解答,有興趣能夠買一本看看。

5. relative實現的問題

relative定位有時候很是管用,只是這裏不太合適:

dd {
  position: relative;
  top: -20px;
}複製代碼

最大的問題在於relative元素定位的時候本來佔據的空間他是依然保留的,因而會留下一片空白區域。這裏,咱們能夠把top改爲margin-top效果就能夠了。

6. 左右浮動的問題

還有的實現是直接左右浮動,沒有定寬:

dt{
    float: left;
    clear: left;
}
dd{
    float: right;
    clear: right;
}複製代碼

這個方法要比左右各50%寬度要好一些,適用的場景要更廣一些。

這裏的clear:right是多餘的,沒有任何做用。更好的寫法是這樣:

dt{
    float: left;
    clear: both;
}
dd{
    float: right;
}複製代碼

可是,若是把極端狀況考慮在內,單純的左右浮動啊,容易產生錯位的問題,例如,咱們右側的描述內容較多的時候:

內容較多時候的錯位問題

這就引出了下面一個比較重要的點,一個好的佈局實現,應該要能應付各類極端場景。

5. 有必要考慮極端內容

對於文本內容而言,所能出現的極端場景,包括下面三種:

  1. 文字內容不少;
  2. 連續的一串英文字符;
  3. 沒有文字內容。

若是本文的小測題是一道面試題的話,最終對候選人的評價最加分的不是用了什麼新技術,也不是用了什麼稀奇古怪的奇巧淫技,而是可否預知到可能遇到的場景並在代碼層面作好容錯處理。這不只能夠體現出足夠的開發經驗,還能體現出全局意識,以及很是重要的基本功。

咱們一個一個來。

首先是連續英文字符。這個簡單,咱們可使用word-break屬性:

word-break: break-all;複製代碼

其次是沒有文字內容。這個問題其實是開發的鍋,在內容輸出的時候,若是沒有數據,應該範圍「暫無」,或者「-」這樣的缺省信息,可是,多年的經驗告訴我,從內容輸出和呈現上,必定不要相信後臺開發人員,咱們本身必定要留一手,不然出現了佈局問題,報告單是提到前端這裏的。

咱們能夠這麼處理:

dd:empty::before {
  content '-';
  color: #999;
}複製代碼

這樣,即便dd標籤裏面沒有輸出任何文字,也會有字符佔位,這樣,佈局就很是穩固。

最後是文字內容不少,這樣就要靠佈局策略了。

3、比較好的實現

這個佈局比較好的實現是這樣子的:左側固定寬度,寬度足夠安全,右側自動填滿剩餘空間。

根據我多年的開發經驗,左側的標籤描述雖然也有動態特性,可是內容倒是產品經理決定的,不是用戶輸入的,所以,個數可控,不要擔憂會超過四個字,中文就有這個特性。所以,咱們能夠放心大膽地把左側dt標籤佔據空間設定爲5
em
。必定要使用em單位,不要使用px或者rem,這樣,不管容器的字號大小是多少,左側寬度都不會空間不足,很是彈性,容錯性很強。

而後,剩下的就是讓右側dd標籤內容寬度自動填滿剩餘空間。

方法不少。

1. dt標籤絕對定位

這是其中一我的的解答,代碼雖少,倒是很是棒的解答:

dt { position: absolute; }
dd {text-align: right; }複製代碼

可是,若是文字內容不少,則dd標籤裏面內容會和dt發生重疊:

重疊示意

因此,咱們加個5em大小的左margin就能夠了。

dt { position: absolute; }
dd {text-align: right; margin-left: 5em; }複製代碼

效果以下截圖:

絕對定位佈局效果截圖

此方法兼容性很是好,低版本IE瀏覽器也支持,但position:absolute元素的層疊順便比較高,若是頁面佈局複雜,出現了元素層疊的場景,則此方法須要斟酌下,由於極可能會增長佈局的複雜度(額外的z-index進行層級控制)。

2. Flex佈局實現

Flex佈局也能實現咱們想要的效果,代碼以下:

dl {
    display: flex;
    flex-wrap: wrap;
}
dt {
    width: 5em;
}
dd {
    width: calc(100% - 5em);
    text-align: right;
}複製代碼

效果以下截圖:

flex佈局效果截圖

關於Flex佈局,若是不瞭解,能夠參見我以前寫的文章:「寫給本身看的display:flex佈局教程」。

Flex佈局的優勢是佈局的呈現傻白甜,很好理解。不足就是會存在些許兼容性問題,在一些老舊的Android手機上。

3. Grid佈局實現

Grid佈局實現是容錯性最強,語義最佳的方法,其最大的優勢是,左側的標籤描述文字,就是5個漢字,6個漢字,佈局依然堅挺。

代碼以下:

dl {
    display: grid;
    grid-template-columns: auto 1fr;
    grid-column-gap: 1em;
}
dd {
    text-align: right;
}複製代碼

效果以下截圖:

flex佈局效果截圖

關於Grid佈局,若是不瞭解,能夠參見我以前寫的文章:「寫給本身看的display:grid佈局教程」。

若是沒有兼容性方面的限制,則是最佳實現。

4. float浮動實現

有人就用了下面的方法實現,對說明對CSS基礎知識仍是比較瞭解的。

dt {
    width: 5em;
    float: left;    
}
dd {
    text-align: right;
    overflow: hidden;    
}複製代碼

關鍵是這裏的overflow:hidden,文字內容再多也不會浮動環繞,具體原理能夠見這篇文章「CSS深刻理解流體特性和BFC特性下多欄自適應佈局」。

效果以下截圖:

flex佈局效果截圖

此方法兼容性很不錯,直到IE7瀏覽器都支持,IE6不支持,若是要兼容IE6,能夠試試加一句_display:inline-block

5. 藉助原生流體特性實現

這個方法是我最後補充的沒有人提到的方法,是最最簡單的實現:

dd {
    margin: -1.5em 0 0 5em;
    text-align: right;    
}複製代碼

就結束了。

寬度自適應,字號大小自適應,文字個數自適應。

效果以下截圖:

flex佈局效果截圖

此方法兼容性最強,上至IE6瀏覽器都支持,代碼最少,各類優勢也都有,也不須要掌握什麼flex佈局,grid佈局,也不須要了解什麼BFC之類概念,就一個簡簡單單的margin屬性就搞定了,是實際項目開發中的最佳實現。然而,至少在答題的這波人中,卻沒人知道這個方法,什麼緣由呢?

總結一下

以上五種方法,雖然代碼是不一樣的,可是最終實現的效果倒是如出一轍的。

眼見爲實,您能夠狠狠的點擊這裏:CSS小測1比較好的5種佈局實現demo

demo頁面能夠調整容器的寬度和字號大小,咱們能夠看到全部5個佈局都表現良好,以下GIF錄屏示意:

各類自適應呈現

實現完整代碼以下:

/* 公共部分 */
dl {
    line-height: 1.5;
    margin: 0; padding: 10px;
    border: 1px solid #ccc;
    background-color: #fff; 
}
dd {
    word-break: break-all;    
    text-align: right;
    margin-left: 0;
}
dd:empty::before {
    content: '-';    
    color: #999;
}
/* absolute實現 */
dt {
    position: absolute;
}
dd {
    margin-left: 5em;    
}
/* flex實現 */
dl {
    display: flex;
    flex-wrap: wrap;
}
dt {
    width: 5em;
}
dd {
    width: calc(100% - 5em);
}
/* grid實現 */
dl {
    display: grid;
    grid-template-columns: auto 1fr;
    grid-column-gap: 1em;
}
/* float實現 */
dt {
    width: 5em;
    float: left;    
}
dd {
    overflow: hidden;    
}
/* 流體特性實現 */
dd {
    margin: -1.5em 0 0 5em;    
}複製代碼

5、關於粉絲羣、小測與直播

上週新建了一個粉絲羣,週三發小測題目,每週依次是CSS、DOM和JS,週六上午答疑,答疑方式是直播加羣聊。我估計下週就會羣滿,到時候想進來估計也進不來了。想入羣的能夠加我好友:zhangxinxu-job,申請信息「入羣」,最好帶上本身的姓名,方便我備註。

直播地址是:live.bilibili.com/21193211

答疑直播時間爲每週六上午10:00-11:00,有時候睡懶覺可能會延後一點。

入羣和直播都是免費的,若是你以爲有所收穫,想要表示感謝,能夠關注個人公衆號,或者買本個人《CSS世界》就能夠了。

(本文完)

相關文章
相關標籤/搜索