[譯] 前端專案中常見的 CSS 問題

Chor發表於2019-06-19

原文Common CSS Issues For Front-End Projects
作者Ahmad Shadeed 發表時間:december 27, 2018
譯者:西樓聽雨 發表時間: 2019/01/01 (轉載請註明出處)

When implementing a user interface in a browser, it’s good to minimize those differences and issues wherever you can, so that the UI is predictable. Keeping track of all of those differences is hard, so I’ve put together a list of common issues, with their solutions, as a handy reference guide for when you’re working on a new project.

Let’s begin.

在瀏覽器中實現一個使用者介面時,我們最好儘可能地把差異點和問題最小化,這樣使用者介面就會更加可預測。不過要記住所有的差異點是非常困難的,所以我將一些常見的問題及其解決方法做成了一個清單,以便您在開發一個新專案時有一個方便的參考。好,我們開始!

1. 重設 button、input 元素的背景

When adding a button, reset its background, or else it will look different across browsers. In the example below, the same button is shown in Chrome and in Safari. The latter adds a default gray background.

在新增一個按鈕時,記得重設它的背景,不然在不同瀏覽器下它將呈現不同的效果。下面這個例子是同一個按鈕在 Chrome 和 Safari 中所展示出的樣子。後者多了一個預設的灰色背景。

img

Resetting the background will solve this issue:

重設它的背景可以解決這個問題:

button {
  appearance: none;
  background: transparent;
  /* Other styles */
}
複製程式碼

演示地址:codepen.io/shadeed/pen…

2. Overflow: scroll vs. auto

To limit the height of an element and allow the user to scroll within it, add overflow: scroll-y. This will look good in Chrome on macOS. However, on Chrome Windows, the scroll bar is always there (even if the content is short). This is because scroll-y will show a scroll bar regardless of the content, whereas overflow: auto will show a scroll bar only when needed.

要固定一個元素的高度,並允許使用者進行滾動檢視,可新增overflow: scroll-y。這在 macOS 版的 Chrome 下是沒有問題的。然而,如果是在 Windows 下的話,滾動欄就會一直存在(即便元素的內容很短)。這是因為 scroll-y 不管元素的內容如何都會顯示出滾動欄,如果使用 overflow: auto 的話就只會在必要的時候才展示出滾動欄。

img

(左邊:macOS 版的 Chrome;右邊:Windows 下的 Chrome)

.element {
    height: 300px;
    overflow-y: auto;
}
複製程式碼

演示地址:codepen.io/shadeed/pen…

3. 新增 flex-wrap

Make an element behave as a flex container simply by adding display: flex. However, when the screen size shrinks, the browser will display a horizontal scroll bar in case flex-wrap is not added.

要使一個元素變成 flex 容器,只需新增 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;
}
複製程式碼

The example above will work great on big screens. On mobile, the browser will show a horizontal scroll bar.

上面這個例子在大螢幕下效果會不錯;但在移動端的話,瀏覽器就會展示出一個水平滾動欄。

img

The solution is quite easy. The wrapper should know that when space is not available, it should wrap the items.

解決方法非常簡單:讓 wrapper 知道當空間不夠用時,應該對元素進行換行排列。

.wrapper {
    display: flex;
    flex-wrap: wrap;
}
複製程式碼

演示地址:codepen.io/shadeed/pen…

4. 如果元素的數量是動態的話,不要使用 justify-content: space-between

When justify-content: space-between is applied to a flex container, it will distribute the elements and leave an equal amount of space between them. Our example has eight card items, and they look good. What if, for some reason, the number of items was seven? The second row of elements would look different than the first one.

如果把 justify-content: space-between 應用在一個 flex 容器上,它將會把它的元素按照等距的間隔來排列。在我們的例子中有 8 張卡片元素,看上去效果不錯。但如果因為某些原因,他們的數量變成了 7 會怎樣?——第二行的元素顯示效果就會與第一行不一樣。

img

img

演示地址:codepen.io/shadeed/pen…

In this case, using CSS grid would be more suitable.

其實在這種場景下,使用 grid 佈局會更加合適。

5. 長詞和長鏈

When an article is being viewed on a mobile screen, a long word or inline link might cause a horizontal scroll bar to appear. Using CSS’ word-break will prevent that from happening.

在移動裝置螢幕上檢視一篇文章時,長詞或長鏈可能會導致水平滾動欄的出現;使用 word-break 可以防止這個問題發生。

img

.article-content p {
    word-break: break-all;
}   
複製程式碼

img

Check out CSS-Tricks for the details.

具體細節請檢視 CSS-Tricks

6. 漸變中的透明色

When adding gradient with a transparent start and end point, it will look black-ish in Safari. That's because Safari doesn’t recognize the keyword transparent. By substituting it with rgba(0, 0, 0, 0), it will work as expected. Note the below screenshot:

當新增用 transparent 作為漸變的開始或結束點的漸變時,在 Safari 中會顯示成烏黑的效果。這是因為 Safari 並不能識別 transparent 關鍵字。把它替換成 rgba(0, 0, 0, 0) 就好了。仔細看下面的截圖:

img

.section-hero {
  background: linear-gradient(transparent, #d7e0ef), #527ee0;
  /*Other styles*/
}
複製程式碼

This should instead be:

應該這樣寫:

.section-hero {
  background: linear-gradient(rgba(0, 0, 0,0), #d7e0ef), #527ee0;
  /*Other styles*/
}
複製程式碼

7. 關於Grid佈局中 auto-fitauto-fill 之間的區別的誤解

In CSS grid, the repeat function can create a responsive column layout without requiring the use of media queries. To achieve that, use either auto-fill or auto-fit.

在 CSS 的 Grid 佈局中,repeat 函式可以用來建立響應式的分欄佈局,而不需要藉助媒體查詢來實現。要實現這種效果,可以使用 auto-fillauto-fit

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

img

In short, auto-fill will arrange the columns without expanding their widths, whereas auto-fit will collapse them to zero width but only if you have empty columns. Sara Soueidan has written an excellent article on the topic.

簡單點講就是,auto-fill 在排列每一欄時不會擴充套件他們的寬度,而 auto-fit 則會把他們收縮成 0 寬度——如果那一欄是空元素的話。關於這個話題,Sara Soueidan 寫了一篇非常不錯的文章

8. 在瀏覽器視窗高度不夠時將元素固定在頂部

If you fix an element to the top of the screen, what happens if the viewport is not tall enough? Simple: It will take up screen space, and, as a result, the vertical area available for the user to browse the website will be small and uncomfortable, which will detract from the experience.

如果你把一個元素固定在螢幕頂部,當視窗的高度不足時會發生什麼?很簡單:它會佔用螢幕空間,而且會造成使用者瀏覽你網站的可用垂直方向的空間變小,造成使用者不適,這樣就會導致體驗退化。

@media (min-height: 500px) {
    .site-header {
        position: sticky;
        top: 0;
        /*other styles*/
    }
}
複製程式碼

In the snippet above, we’re telling the browser to fix the header to the top only if the viewport’s height is equal to or greater than 500 pixels.

上面這段程式碼中,我們告訴瀏覽器只在視窗的高度大於等於 500 個畫素時才將頭部固定顯示。

Also important: When you use position: sticky, it won’t work unless you specify the top property.

另外要注意一點:在你使用 position: sticky 的時候,如果不指定 top 屬性是不會有效果的。

img

演示地址:codepen.io/shadeed/pen…

9. 設定圖片的 max-width

When adding an image, define max-width: 100%, so that the image resizes when the screen is small. Otherwise, the browser will show a horizontal scroll bar.

在新增圖片時,將其 max-width 設定為 100%,這樣在螢幕較小時,圖片的尺寸就會收縮,否則就會出現一個水平滾動欄。

img {
    max-width: 100%;
}
複製程式碼

10. 使用 CSS Grid 佈局來定義 main、aside 元素

CSS grid can be used to define the main and aside sections of a layout, which is a perfect use for grid. As a result, the aside section’s height will be equal to that of the main element, even if it’s empty.

CSS Grid 佈局可以用來定義一個佈局中的 main 和 aside 區域,這非常適用於 grid。不過這樣的結果是,aside 區域的高度會和 main 元素保持一致,即便 aside 是空元素。

To fix this, align the aside element to the start of its parent, so that its height doesn’t expand.

要解決這個問題,將 aside 元素保持與其父元素的開始位置對齊即可,這樣他的高度就不會自動擴充套件了。

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

// align-self will tell the aside element to align itself with the start of its parent.
// align-self 可以告訴 aside 元素保持與其父元素對對齊。
aside {
  grid-column: 1 / 4;
  grid-row: 1;
  align-self: start;
}

main {
  grid-column: 4 / 13;
}
複製程式碼

img

演示地址:codepen.io/shadeed/pen…

11. 為 SVG 新增 fill

Sometimes, while working with SVGs, fill won’t work as expected if the fill attribute has been added inline in the SVG. To solve this, either to remove the fill attribute from the SVG itself or override fill: color.

在使用 SVG 時,如果 fill 屬性是內聯在其上的的話,有個時候會得不到想要的效果。要解決這個問題,要麼將 fill 屬性從 SVG 上移出,要麼用 fill: <顏色值> 來覆蓋。

Take this example:

看下下面這個例子:

.some-icon {
    fill: #137cbf;
}
複製程式碼

This won’t work if the SVG has an inline fill. It should be this instead:

如果這個 SVG 上有內聯的 fill 的話,這樣是沒用的,應該這樣寫:

.some-icon path {
    fill: #137cbf;
}
複製程式碼

12. 使用偽元素

I love to use pseudo-elements whenever I can. They provide us with a way to create fake elements, mostly for decorative purposes, without adding them to the HTML.

我喜歡儘可能地使用偽元素。他們可以用來建立虛假元素——大多數時候作為裝飾效果用,且不用新增東西到 HTML 中。

When working with them, the author might forget to do one of the following:

在使用他們的時候,編寫者可能經常會忘記做下面這些事:

  • add the content: "" property,

    新增 content: "" 屬性。

  • set the width and height without defining the display property for it.

    設定了 widthheight ,卻沒有定義其 display 屬性。

In the example below, we have a title with a badge as a pseudo-element. The content: "" property should be added. Also, the element should have display: inline-block set in order for the width and height to work as expected.

下面這個例子中,有一個標題,它前面的標記就是一個偽元素。需要新增 content: "" 才會有作用;另外,如要要讓他的 widthheight 生效,還需要設定 display: inline-block

img

13. 當使用 display: inline-block 時,元素間隔的怪異現象

Setting two or more elements to display: inline-block or display: inline will create a tiny space between each one. The space is added because the browser is interpreting the elements as words, and so it’s adding a character space between each one.

將兩個或多個元素設定為 display: inline-blockdisplay: inline 時,會在他們之間製造出一個小的空間。這個空間的出現,是因為瀏覽器把這些元素解釋成了單詞,所以會在他們之間新增一個字元的間距。

In the example below, each item has a space of 8px on the right side, but the tiny space caused by using display: inline-block is making it 12px, which is not the desired result.

下面這個例子中,每個元素的右邊都擁有 8px 的空間,但如果使用的是 display: inline-block 的話,這個小空間就會變成 12px ,這並不是所期望的結果。

li:not(:last-child) {
  margin-right: 8px;
}
複製程式碼

img

A simple fix for this is to set font-size: 0 on the parent element.

要修復這個問題,一個簡單的方法就是將它父元素的 fotn-size 設定為 0

ul {
    font-size: 0;
}

li {
    font-size: 16px; /*The font size should be reassigned here because it will inherit `font-size: 0` from its parent.*/
    /* 這裡之所以重新設定了字型大小,是它會整合父元素的字型大小 */
}
複製程式碼

img

演示地址:codepen.io/shadeed/pen…

14. 為 Label 元素新增 for="ID" 屬性

When working with form elements, make sure that all labelelements have an ID assigned to them. This will make them more accessible, and when they’re clicked, the associated input will get focus.

在使用表單元素時,確保所有的 label 元素都設定了指向目標表單元素 ID 的 for 屬性。這可以使得表單元素更具可訪問性,在點選這些 label 的時候,對應的表單元素就可以獲得聚焦。

<label for="emailAddress">Email address:</label>
<input type="email" id="emailAddress">
複製程式碼

img

15. 字型屬性不會影響到互動式元素

When assigning fonts to the whole document, they won’t be applied to elements such as input, button, select and textarea. They don’t inherit by default because the browser applies the default system font to them.

如果把字型設定到整個文件上,input、button、select 及 textarea 元素並不會受影響,他們預設不會繼承字型,因為瀏覽器對他們應用了預設的系統字型。

To fix this, assign the font property manually:

要解決這個問題,需要手動地為他們設定字型屬性:

input, button, select, textarea {
  font-family: your-awesome-font-name;
}
複製程式碼

16. 水平滾動欄

Some elements will cause a horizontal scroll bar to appear, due to the width of those elements.

某些元素會由於自身的寬度問題導致水平滾動欄的出現。

The easiest way to find the cause of this issue is to use CSS outline. Addy Osmani has shared a very handy script that can be added to the browser console to outline every element on the page.

要找出這這個問題原因,最簡單的方法就是使用 CSS 的 outline 屬性。Addy OSmani 分享了一段指令碼,它可以直接放到瀏覽器的 console 中執行,以此 outline 出頁面的每個元素。

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

img

17. 圖片的擠壓和拉伸

When you resize an image in CSS, it could be compressed or stretched if the aspect ratio is not consistent with the width and height of the image.

在使用 CSS 來重定義圖片的尺寸時,如果其長寬比與設定的不一致,就會導致其出現擠壓或拉伸的效果。

The solution is simple: Use CSS’ object-fit. Its functionality is similar to that of background-size: cover for background images.

解決方法非常簡單:使用 CSS 的 object-fit 就可以了。它的作用類似於針對背景圖片的 background-size: cover

img {
    object-fit: cover;
}
複製程式碼

img

Using object-fit won’t be the perfect solution in all cases. Some images need to appear without cropping or resizing, and some platforms force the user to upload or crop an image at a defined size. For example, Dribbble accepts thumbnails uploads at 800 by 600 pixels.

使用 object-fit 並不是在所有情況下都合適。有些地方可能要求圖片不經裁切或縮減尺寸,另外有些平臺也會強制使用者上傳符合規定尺寸的圖片,例如,Dribble 就只接受 800 x 600 的縮圖。

18. 為 input 元素新增正確的 type 屬性

Use the correct type for an input field. This will enhance the user experience in mobile browsers and make it more accessible to users.

為 input 元素新增正確的 type 屬性可以增強移動端的使用者體驗,讓使用者獲得更多的可訪問性。

Here is some HTML:

下面是一段 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>
複製程式碼

This is how each input will look once it’s focused:

下面顯示的就是每個元素聚焦後的效果:

img

19. RTL 佈局中的電話號碼

When adding a phone number like + 972-123555777 in a right-to-left layout, the plus symbol will be positioned at the end of the number. To fix that, reassign the direction of the phone number.

當在右到左佈局中新增像+ 972-123555777這樣的手機號碼時,加號會被置於號碼的末尾。要解決這個問題,需要重新設定號碼的 direction 屬性。

p {
    direction: ltr; // left-to-right,左到右 ——譯註
}
複製程式碼

img

相關文章