防御式CSS是什么?这几点属性重点防御

很多时候,我们希望有一种方法可以避免某种CSS问题或行为的发生。我们知道,网页内容是动态的,网页上的东西可以改变,从而增加了出现CSS问题或奇怪行为的可能性。

防御式 CSS是一个片段的集合,可以帮助我编写受保护的CSS。换句话说,就是将来会有更少的bug出现。

1.Flexbox 包裹

CSS flexbox 是目前最有用的CSS布局功能之一。在一个包装器上添加 display: flex,让子项挨着排序。

问题是,当空间不足时,那些子项默认不会被包裹成一个新的行。我们需要用 flex-wrap: wrap 来改变这一行为。

下面是一个典型的例子。

.options-list {
    display: flex;
}

当空间较少时,会出现水平滚动。这应该是预料之中的,实际上并不是一个 “问题”。

.options-list {
    display: flex;
    flex-wrap: wrap;
}

使用flexbox时,一般的经验法则是允许包裹,除非你想要一个滚动的包裹。这是另一回事,但尽量使用 flex-wrap 来避免意外的布局行为(在我们的例子中,是水平滚动)。

2.间距

我们开发者需要考虑不同的内容长度。这意味着,间距应该添加到组件中,即使它看起来不需要。

在这个例子中,我们在右边有一个section标题和一个操作按钮。目前,它看起来还不错。但是,如果标题再长一些,会发生什么呢?

注意到文本太靠近按钮了吗?这里,你可能会考虑多行换行,但现在,我们先关注距。

如果标题有空格和文本截断,我们不会看到这样的问题。

.section__title {
    margin-right: 1rem;
}

3.长内容

在构建布局时,考虑到长的内容是很重要的。正如你在前面所看到的,当章节的标题太长时就会被截断。这是可选的,但对于某些UI来说,考虑到这一点很重要。

对我来说,这是一种防御性的CSS方法。在 “问题 “真正发生之前就去解决它,这很好。

这里有一份人名清单,现在看起来很完美

然而,由于这是用户生成的内容,我们需要小心如何防御布局,以防某些内容太长。请看下图:

在这种布局中,一致性非常重要。为了实现这一点,我们可以使用 text-overflow和它的好友来简单地截断名称。

4. 防止图像被拉伸或压缩

在无法控制图片高宽比的情况下,如果用户上传的图片与高宽比不符,最好提前考虑并提供解决方案。

在下面的例子中,我们有一个带有照片的卡片组件。它看起来不错。

当用户上传一个不同大小的图像时,它将被拉伸。这可不是什么好事。看看图像是如何被拉伸的!

最简单的修复方法是使用CSS object-fit

.card__thumb {
    object-fit: cover;
}

在项目层面上,我倾向于为所有图像添加 object-fit,以避免出现意外的结果。

5.锁定滚动链接

你是否曾经打开一个模态并开始滚动,然后当你到达终点并继续滚动时,模态下面的内容(主体元素)会滚动?这就是所谓的滚动链。

默认情况下,当触及页面顶部或者底部时(或者是其他可滚动区域),移动端浏览器倾向于提供一种“触底”效果,甚至进行页面刷新。你可能也发现了,当对话框中含有可滚动内容时,一旦滚动至对话框的边界,对话框下方的页面内容也开始滚动了——这被称为“滚动链”。。

在过去的几年里,有一些黑科技来实现这一点,但现在,我们只需要使用CSS 即可,这要感谢overscroll-behavior CSS属性。

在下面的图中,可以看到默认的滚动链接行为。

为了提前避免这种情况,我们可以将其添加到任何需要滚动的组件中(例如:聊天组件、移动菜单…等)。这个属性的好处是,在有滚动之前,它不会产生影响。

.modal__content {
    overscroll-behavior-y: contain;
    overflow-y: auto;
}

6. CSS变量回退

CSS变量在网页设计中得到了越来越多的应用。我们可以应用一种方法,在CSS变量值因某种原因为空的情况下,以一种不破坏体验的方式使用它们。

通过 JS 输入CSS变量的值时特别有用。下面是一个例子:

.message__bubble {
    max-width: calc(100% - var(--actions-width));
}

变量 –actions-widthcalc() 函数中被使用,其值来自 JS。假设 JS 由于某种原因失败了,会发生什么?max-width 会被计算为零。

我们可以提前避免这种情况,在 var() 中添加一个回退值。

.message__bubble {
    max-width: calc(100% - var(--actions-width, 70px));
}

这样,如果变量没有定义,就会使用回退 (70px)。这种方法可以在变量可能失败的情况下使用。

7.使用固定宽度或高度

破坏布局的常见情况之一是对一个有不同长度内容的元素使用固定的宽度或高度。

固定高度

我经常看到主内容部分有固定的高度,而内容却大于这个高度,这就导致了布局的破坏。如下所示:

.main {
    height: 350px;
}

为了避免这种情况出现,可以使用 min-height 代替 height:

固定宽度

你有没有见过按钮,它的标签离左右边缘太近?这是由于使用了固定宽度。

.button {
    width: 100px;
}

如果按钮的标签大于100px,它将靠近边缘。如果它太长,文本会泄露出来。这是不好的!

为了解决这个问题,我们可以简单地用 min-width 代替 width

.button {
    min-width: 100px;
}

8.忘记 background-Repeat

很多时候,当使用一张大的图片作为背景时,我们往往会忘记考虑设计在大屏幕上观看时的情况。该背景将默认重复。

这在笔记本屏幕上大多不会看到,但在大屏幕上很常见。

为了提前避免这种行为,请确保使用重置 background-repeat

.hero {
    background-image: url("..");
    background-repeat: no-repeat;
}

9.垂直媒体查询

有时,我们很想建立一个组件,只通过调整浏览器的宽度进行测试。根据浏览器的高度进行测试可以发现一些有趣的问题。

这里有一个我见过多次的例子。我们有一个带有主要和次要链接组件。次要链接应该位于旁白部分的最底部。

考虑一下下面的例子。主导航和次导航看起来还不错。在我看到的这个例子中,开发者给二级导航添加了 position: sticky,这样它就可以粘在底部了。

然而,如果浏览器的高度较小,bug 就来了。注意这两个导航是如何重叠的。

通过使用CSS垂直媒体查询,我们可以避免这个问题。

@media (min-height: 600px) {
    .aside__secondary {
        position: sticky;
        bottom: 0;
    }
}

这样,只有当视口高度大于或等于600px 时,二级导航才会被粘在底部。好多了,对吗?

可能有更好的方法来实现这一行为(比如使用 margin-auto),但在这个例子中专注于垂直查询。

10. 使用 justify-content:space-between

在一个 flex 的容器中,我们可能会使用 justify-content 来使子项目之间有一定的间距。如果有一定数量的子项目,布局看起来会很好。然而,当它们增加或减少时,布局会看起来很奇怪。

考虑以下例子:

我们有一个有四个项目的 flex 容器。每个项目之间的间距不是 gapmargin,它之所以存在是因为容器有 justify-content: space-between

.wrapper {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
}

当项目的数量少于4个时,将发生以下情况:

这并不是好事。对此有不同的解决方案:

  • margin
  • flexbox gap(谨慎使用)
  • padding(可应用于每个子元素的父元素)
  • 增加空的元素,作为间隔。

为了简单起见,我使用 gap

.wrapper {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
}

11. 图片上的文字

当在图片上放置文本时,必须考虑到图像无法加载的情况。文本会是什么样子。下面是一个例子:

文本看起来是可读的,但当图像加载失败时,它的可读性变得很差。

我们通过给