tinyshare微博账号
前端项目共有的CSS问题 一月 29, 2019

当浏览器应用一个用户交互界面时,一种很好的方式是可以最小化差异和问题,UI是可预测的。想要追踪到所有的差异是比较困难的,所以我将这些共同问题整理成一个列表,为你在做新项目时提供一个简单易用的参考指南。

1.重置button和input元素的背景

当我们添加button时,重置button的背景,或者在不同浏览器上展示不一样。下面这个例子中展示了相同的button在Chrome和Safari的效果,后者默认有一个灰色的背景。

图片

重置button的背景就可以解决这个问题。

button {
  appearance: none;
  background: transparent;
  /* Other styles */
}

2.Overflow: scroll vs. auto

要限制元素的高度来让用户在元素内滑动,需要给该元素添加overflow: scroll-y。在macOS系统的Chrome上看起来还好,但是在Windows系统的Chrome上滚动条会一直存在(即使内容很少)。这是因为scroll-y不管内容的多少都会显示一个滚动条,而overflow: auto只有在需要的时候才会显示滚动条。

图片

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

3.添加 flex-wrap

想让一个元素显示成一个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;
}

上面这个例子在大屏幕上显示的正常,在手机端会显示一个横向的滚动条。下图中,左边显示一个横向的滚动条,且子元素没有被包裹;右边的子元素被包裹成两行。

图片

解决方案很简单,包裹容器应该知道什么时候没有空隙,这时就要让子元素换行。

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

4.不要在flex item个数是动态的时候使用justify-content: space-between

当一个flex容器应用justify-content: space-between时,它会分散元素,并为它们分配一个相同的间距。我们的例子有八个卡片元素,它们看起来显示很正常。但是当我们的子元素是七个呢?第二行的元素看起来会和第一行不一样。下图分别是八个元素和七个元素显示的效果。

图片 图片 这种情况下,用CSS grid会更合适。

5.长字符串和链接

当一个文章在手机屏幕上显示的时候,一个长的词或链接也许会引起横向滚动条的出现。使用CSS的 word-break 可以防止这种情况产生。

图片

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

图片

6.透明渐变

当添加一个由透明色开始或结束的渐变,在Safari上看起来像黑色的,因为Safari不识别关键字transparent。下图中分别是Chrome 70和Safari 12。

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

图片

使用rgba(0, 0, 0, 0)替换,就会像正常的显示。

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

7.CSS Grid中 auto-fit 和 auto-fill 区别的误解

在CSS Grid中,repeat函数不需要使用媒体查询就可以创建一个响应式列布局。为了实现这个效果,需要使用 auto-fill 或 auto-fit。

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

图片

简单地说,auto-fill会整理这些列而不会拓展它们的宽度,而auto-fit只在没有空的列时才将它们的宽度置为0。Sara Soueidan写了一篇关于这个话题很不错的文章

8.当viewport不够高时,将元素固定在屏幕顶部

如果你把一个元素固定在屏幕顶部,当viewport不够高时会发生什么呢?很简单,它会占用屏幕空间,结果是垂直方向浏览网站的可用空间会变小,看着很不舒服,很大程度降低了用户体验。

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

上面这段代码,可用让浏览器在viewport高度大于等于500px的时候才将header固定到顶部。同样重要的是,只有声明了top属性之后,position: sticty 才会起作用。

图片

9.为图片设置 max-width

当添加一个图片时,定义 max-width: 100%,这样当屏幕小的时候,图片可以自适应尺寸。否则,浏览器就会显示一个横向的滚动条。

img {
    max-width: 100%;
}

10.使用CSS Grid来定义main和aside元素

CSS grid可以用来定义一个布局中的main和aside块,这是grid中的一个完美的用处。这种布局的结果是,aside块的高度会和main元素的高度一致,即使main元素是空的。

为了解决这个问题,将aside元素与父元素的开始对齐,这样它的高度就不会扩大。

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

/* align-self 会告诉adise元素,让它跟父元素的开始对齐 */
aside {
  grid-column: 1 / 4;
  grid-row: 1;
  align-self: start;
}

main {
  grid-column: 4 / 13;
}

图片

11.给SVG添加 fill

有时在使用SVG时,如果SVG已经内联声明了fill属性,CSS里的fill就不会正常工作了。要解决这个问题,要么去掉SVG的fill属性,要么覆盖fill: color。

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

如果SVG定义了fill属性,上面这个不会起作用。应该用下面这个替换掉。

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

12.使用伪元素

任何可以使用伪元素的时候,我都会使用它。它为我们提供了一种创建多数情况是为了装饰作用的伪元素的方法,而不需要添加真的HTML。

在使用它时,开发者可能会忘了做下面这些事:

  • 添加 content: "" 属性;
  • 不定义display时,设置width和height。

下面的例子中,有一个标题使用伪元素作为标记。应该添加 content: "" 属性,而且为了让 width 和 height 起作用,还需要设置 display: inline-block。

图片

13.使用 display: inline-block 时,诡异的间距

将两个或多个元素设置成 display: inline-block 或 display: inline 会让每两个元素间创建一个小空白。这个小空白是由于浏览器将这些元素解析成字,在它们之间添加一个字符的空白。

下面例子中,每个元素在右侧有一个8px的空白,但是由于设置了 display: inine-block,这个空白变成了12px。

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

图片 一个简单的解决方法,是对父元素设置 font-size: 0,再单独对子元素设置字体大小。

ul {
    font-size: 0;
}

li {
    font-size: 16px;
}

图片

14.当一个label标签映射到一个输入框时,为它设置 for="ID"

当使用form元素时,确保所有的 label 元素都有一个映射的ID。这可以让它们更易理解,当它们被点击时,相关联的输入框会获得焦点。

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

图片

15.在交互性HTML元素上字体不起作用

当字体关联到整个文档,它们不会被应用到input、button、select和textarea等这些元素上。它们不会继承默认值,因为浏览器会将系统默认字体应用到它们上面。

为了解决这个问题,需要手动设置字体属性。

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

16.水平滚动条

由于一些元素的宽度,会产生横向的滚动条。发现这个问题原因最简单的方法是用CSS轮廓线。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 不是所有场景下最好的解决方法。一些图片展示的时候不需要裁剪或改变大小,还有一些平台会强制用户按照设定好的尺寸上传或裁剪图片。

18.为 input 添加正确的 type

为 input 字段使用正确的 type,可以改善手机浏览器端的用户体验,对用户更加友好。

<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.从右向左布局的手机号码

当在一个从右向左布局中添加 +972-123555777 这样的手机号码时,加号会被定位到数字的末尾。要解决这个问题,再给手机号码分配一个方向。

p {
    direction: ltr;
}

图片 结论

上面提到的问题是我在前端开发工作中遇到过的一些相同的问题,我的目标是要在做新的web项目时,保留一个规律的列表。