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

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

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.css

Let’s begin.html

在瀏覽器中實現一個用戶界面時,咱們最好儘量地把差別點和問題最小化,這樣用戶界面就會更加可預測。不過要記住全部的差別點是很是困難的,因此我將一些常見的問題及其解決方法作成了一個清單,以便您在開發一個新項目時有一個方便的參考。好,咱們開始!java

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.git

在添加一個按鈕時,記得重設它的背景,否則在不一樣瀏覽器下它將呈現不一樣的效果。下面這個例子是同一個按鈕在 Chrome 和 Safari 中所展現出的樣子。後者多了一個默認的灰色背景。github

img

Resetting the background will solve this issue:web

重設它的背景能夠解決這個問題:瀏覽器

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

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

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.less

要固定一個元素的高度,並容許用戶進行滾動查看,可添加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
相關文章
相關標籤/搜索