[譯] 前端項目中常見的 CSS 問題

快速摘要:近年來,跨瀏覽器的渲染和交互已經越發一致。不過,它仍然沒有達到徹底一致,有不少小問題會讓你出錯。除了這些問題以外,還有不一樣的屏幕尺寸、語言偏好和明顯的人爲錯誤等不肯定因素,咱們從中發現了許多會讓開發者出錯的小問題。css

在瀏覽器中實現用戶界面時,最好是儘量地減少這些差別和問題,以便 UI 呈現出預測的樣子。記住全部的這些差別是很困難的,因此我列舉了一系列常見問題以及解決方案。當你在作一個新項目的時候,能夠將其做爲一份方便的參考指南。 html

咱們開始吧。前端

1. 重置 buttoninput 元素的背景

添加按鈕時,重置它的背景,不然在跨瀏覽器時它的呈現會有所不一樣。下面的例子分別展現了 Chrome 和 Safari 中的同一個按鈕,後者默認會有一個灰色背景。git

(大圖預覽)github

重置背景能夠解決這個問題:web

button {
    appearance: none;
    background: transparent;
    /* 其它樣式 */
}

https://codepen.io/shadeed/pe...瀏覽器

查看 Ahmad Shadeed(@shadeed)在 Codepen 上的代碼 按鈕和輸入框app

2. Overflow: scrollauto

爲了限制一個元素的高度並容許用戶在其中滾動,添加 overflow: scroll-y。在 macOS 下的 Chrome 中,這看起來不錯,可是在 Windows 下的 Chrome 中,滾動條始終存在(即便內容很短)。這是由於 scroll-y 會無視內容,一直顯示滾動條。而 overflow: auto 只在須要的時候纔會顯示滾動條。less

左邊:macOS 下的 Chrome。右邊:Windows 下的 Chrome (大圖預覽)dom

.element {
    height: 300px;
    overflow-y: auto;
}

https://codepen.io/shadeed/pe...

查看 Ahmad Shadeed(@shadeed)在 Codepen 上的代碼 overflow-y

3. 添加 flex-wrap

要想讓一個元素表現得像彈性容器那樣,只需添加 display: flex。可是,若是沒有添加 flex-wrap ,那麼當屏幕尺寸縮小的時候,將會出現水平滾動條。

<div class="wrapper">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
</div>
.wrapper {
    display: flex;
}

.item {
    flex: 0 0 120px;
    height: 100px;
}

上面的例子在大屏幕下表現正常。在移動端下,瀏覽器將會出現水平滾動條。

左邊:出現水平滾動條,而且項目沒有換行。右邊:項目換行,呈兩行顯示 (大圖預覽)

解決方法很簡單。wrapper 應該在空間不足時讓項目換行。

.wrapper {
    display: flex;
    flex-wrap: wrap;
}

https://codepen.io/shadeed/pe...

查看 Ahmad Shadeed(@shadeed)在 Codepen 上的代碼 overflow-y

4. 當彈性項目數量不定時,不要使用 justify-content: space-between

對一個彈性容器應用 justify-content: space-between 時,它會爲元素分配空間,使它們互相之間的距離相等。咱們的例子中有 8 個卡片項目,看起來沒什麼問題。若是因爲某種緣由,項目的數量是 7 呢?第二行的元素看起來將會與第一行的不一樣。

包含 8 個項目的 wrapper (大圖預覽)

包含 7 個項目的 wrapper(大圖預覽)

https://codepen.io/shadeed/pe...

查看 Ahmad Shadeed(@shadeed)在 Codepen 上的代碼 overflow-y

在這種狀況下,使用 CSS 網格將會更加合適。

5. 長詞和連接

在手機屏幕上瀏覽文章的時候,一個長詞或者內聯連接可能會致使頁面出現水平滾動條。使用 CSS 的 word-break 能夠防止這個問題。

(大圖預覽)

.article-content p {
    word-break: break-all;
}

(大圖預覽)

詳情查看 CSS-Tricks

6. 透明漸變

當使用透明起點和終點添加漸變的時候,在 Safari 下會呈現一片漆黑。這是由於 Safari 沒法識別關鍵字 transparent。經過使用 rgba(0, 0, 0, 0) 來替代它,咱們能夠達到預期的效果。注意下面的截圖:

頂部: Chrome 70。底部:Safari 12 (大圖預覽)

.section-hero {
    background: linear-gradient(transparent, #d7e0ef), #527ee0;
    /* 其它樣式 */
}

應該替換爲:

.section-hero {
    background: linear-gradient(rgba(0, 0, 0,0), #d7e0ef), #527ee0;
    /* 其它樣式 */
}

7. CSS 網格佈局中關於 auto-fitauto-fill 差別的誤解

在 CSS 網格佈局中,repeat 函數能夠在不使用媒體查詢的狀況下建立響應式列布局。爲此,可使用 auto-fill 或者 auto-fit

.wrapper {
    grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
}

(大圖預覽)

簡而言之,auto-fill 將會在不擴展列寬度的狀況下對它們進行排列,而auto-fit 則會在存在空列的時候使其寬度塌陷爲 0。Sara Soueidan 寫了一篇不錯的文章討論過這個問題。

8. 當視窗高度不足時將元素固定在屏幕頂部

若是你在視窗不夠高的時候將一個元素固定在屏幕頂部,會發生什麼事呢?很簡單:它將佔用屏幕空間,最終致使可供用戶瀏覽網站的垂直區域變得很小、很不舒服,影響他們的體驗。

@media (min-height: 500px) {
    .site-header {
        position: sticky;
        top: 0;
        /* 其它樣式 */
    }
}

上面的代碼中,咱們讓瀏覽器只在視窗高度等於或大於 500 像素的時候才固定頂部。

還有一點很重要:使用 position: sticky 的時候,除非指定 top 屬性,不然它不會生效。

(大圖預覽)

https://codepen.io/shadeed/pe...

查看 Ahmad Shadeed(@shadeed)在 Codepen 上的代碼 overflow-y

9. 爲圖片設置 max-width

添加圖片時,定義 max-width: 100%,這樣圖片會在屏幕較小的時候改變大小。不然瀏覽器將會顯示水平滾動條。

img {
    max-width: 100%;
}

10. 使用 CSS 網格定義 mainaside 元素

CSS 網格可用於定義佈局中的 main 部分和 aside 部分,這是 CSS 網格的絕佳用途。問題是,即便 aside 是空的,它的高度也會和 main 的高度相等。

要修復這個問題,可讓 aside 元素與其父元素的起點對齊,這樣它的高度就不會擴展了。

.wrapper {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    grid-gap: 20px;
}

// align-self 將會讓 aside 元素與其父元素的起點對齊。
aside {
    grid-column: 1 / 4;
    grid-row: 1;
    align-self: start;
}

main {
    grid-column: 4 / 13;
}

(大圖預覽)

https://codepen.io/shadeed/pe...

查看 Ahmad Shadeed(@shadeed)在 Codepen 上的代碼 overflow-y

11. 給一個 SVG 添加 fill

使用 SVG 時,若是在 SVG 內部添加 fill,有時候它可能不會如預期的那樣生效。要修復這個問題,要麼移除 SVG 自身的 fill 屬性,要麼覆蓋 fill: color

舉個例子:

.some-icon {
    fill: #137cbf;
}

若是 SVG 有一個內聯 fill 的話,這段代碼將不會生效。應該替換爲:

.some-icon path {
    fill: #137cbf;
}

12. 使用僞元素

不管什麼時候,我都很喜歡使用僞元素。僞元素爲咱們提供了一種建立假元素的方法,主要用來裝飾,同時又無需將其添加到 HTML 中。

使用它們的時候,開發者可能會忘記作下面的事情:

  • 添加 content: "" 屬性,
  • 在沒有定義 display 屬性的狀況下設置它們的 widthheight

下面的例子中,咱們有一個標題,其標記是一個僞元素。必須給元素添加 content: "" 屬性,同時還要爲它設置 display: inline-block ,以使 widthheight 像預期的那樣生效。

(大圖預覽)

13. 使用 display: inline-block 時奇怪的空隙

給兩個或兩個以上的元素設置 display: inline-block 或者 display: inline ,將會致使它們之間產生一個微小的空隙。緣由是瀏覽器會將元素看成字詞去解釋,從而給每一個元素之間添加一個字符的空隙。

下面的例子中,每一個項目的右側都有一個 8px 的空隙,可是使用 display: inline-block 而產生的小空隙將會使其變爲 12px,這不是咱們想要的效果。

li:not(:last-child) {
    margin-right: 8px;
}

(大圖預覽)

經過給父元素設置 font-size: 0 能夠簡單地解決這個問題。

ul {
    font-size: 0;
}

li {
    font-size: 16px; /* 應該在這裏從新設置字體大小,由於它會從父元素繼承 `font-size: 0`。*/
}


(大圖預覽)

https://codepen.io/shadeed/pe...

查看 Ahmad Shadeed(@shadeed)在 Codepen 上的代碼 overflow-y

14. 分配一個標籤元素給一個輸入框時,添加 for="ID"

使用表單元素時,確保全部的 label 元素都分配到了一個 ID。這將提升它們的可訪問性,點擊的時候,相關的輸入框將得到焦點。

<label for="emailAddress">Email address:</label>
<input type="email" id="emailAddress">

(大圖預覽)

15. 交互式 HTML 元素的字體不生效

給整個文檔設置字體的時候,字體並不會應用於諸如 inputbutton selecttextarea 這些元素上。默認狀況下,它們並不會繼承文檔字體,由於瀏覽器給它們應用了系統字體。

要修復這個問題,直接設置字體屬性:

input, button, select, textarea {
    font-family: your-awesome-font-name;
}

16. 水平滾動條

有些元素的寬度可能會致使出現一個水平滾動條。

要找到問題的根源,最簡單的方法就是使用 CSS outline。Addy Osmani 寫了一個方便的腳本 。將其添加到瀏覽器的控制檯,頁面上全部元素的輪廓都會顯示出來。

[].forEach.call($$("*"), function(a) {
    a.style.outline =
    "1px solid #" + (~~(Math.random() * (1 << 24))).toString(16);
});

(大圖預覽)

17. 壓縮或拉伸圖片

用 CSS 調整一張圖片的大小時,若是縱橫比與圖片的寬高不一致,則圖片會被壓縮或拉伸。

解決方法很簡單:使用 CSS 的 object-fit。它的功能和給背景圖片設置 background-size: cover 相似。

img {
    object-fit: cover;
}


(大圖預覽)

object-fit 並不是百試百靈。一些圖片必須在不裁剪或者不調整大小的狀況下顯示,而且某些平臺會強制用戶以特定的尺寸裁剪或上傳圖片。例如,Dribbble 規定上傳的縮略圖尺寸爲 800 x 600 像素。

18. 爲 input 添加正確的 type

input 使用正確的 type。這將改善移動端的用戶體驗,並使用戶更容易訪問。

這是部分 HTML:

<form action="">
    <p>
        <label for="name">Full name</label>
        <input type="text" id="name">
    </p>
    <p>
        <label for="email">Email</label>
        <input type="email" id="email">
    </p>
    <p>
        <label for="phone">Phone</label>
        <input type="tel" id="phone">
    </p>
</form>

每一個輸入框分別獲取焦點時,看起來是這樣的:


(大圖預覽)

19. RTL 佈局中的手機號碼

在一個從右到左的佈局中添加諸如 + 972-123555777 的手機號碼時,加號將會位於號碼末尾。要修復這個問題,能夠從新指定手機號碼的方向。

p {
    direction: ltr;
}

(大圖預覽)

結論

這裏提到的全部問題都是我在前端開發工做中最常遇到的。個人目標是在開發 web 項目時按期檢查這份清單。

你在 CSS 中有沒有常常遇到什麼問題呢?歡迎在評論區分享!

相關文章
相關標籤/搜索