新年里 CSS 更易编写

大家好,这里是大家的林语冰。持续关注,坚持阅读,每天一次,进步一点

免责声明

本文属于是语冰的直男翻译了属于是,略有删改,仅供粉丝参考。英文原味版请传送 A Few Ways CSS Is Easier To Write In 2023

本期共享的是 —— 去年 CSS 引入了某些前沿新功能,辅助我们编写更精简、更灵活的 CSS,从此远离“代码屎山”。

我们生活在 CSS 的“样式复兴时代”,新的功能、技术和想法日新月异,此“开元盛世”自 CSS3 以来见所未见。当我们的技术一日千里时,我们很容易“挨踢蕉绿”,但也很容易因为近未来的创新而感到鸡冻,而 CSS 生态的沧桑巨变只用了不到一年的时间。虽然 CSS 的复杂性是一个热度不减的谈资,但有大佬认为去年的现代化 CSS 实际上使 CSS 更易编写。

CSS 变得更易编写,而不是变得非同寻常”。

这并非因为某些令人鸡冻的新功能引发“样式革命”,比如级联图层或全新的色彩空间,而是因为一大坨新功能“梦幻联动”,使 CSS 的风格更精简、有弹性,甚至有点防御性编程的味道。

高效风格组

禁止直接使用逗号分隔符将 :hover/:focus 状态链式多选,推荐使用全新的 :is() 伪类,重构为更可读的单行代码:

/* 今年之前的传统写法 */
a:hover,
a:focus {
}

/* 去年之后的现代化写法 */
a:is(:hover, :focus) {
}

这里的“更具可读性”并非因为该写法更高效,而是更符合读者的直觉和人体工程学。

当然了,:is() 伪类绝对可以成为更高效的选择器,已经关注的老粉不用猴急,我们日后再说。

居中

居中是一道回头率超高的前端面试题,对不?可以这样说,将元素与其父容器的中心对齐的“传统方案”水到渠成。我们使用了 margin: auto 将元素从各个方向内推,直到它垂直居中。

这仍是一个有效的居中方案,因为 margin 的简写涉及每个方向。但假设当我们处于默认的水平左写书写模式下时,我们只需要沿内联方向工作,比如左右。这就是“传统方案”鞭长莫及的盲区。

/* 传统写法 */
margin-left: auto;
margin-right: auto;

也许“外边距坍塌”十分头大。更重要的是,这需要放弃通用的 margin 简写,并专门针对其两个组成属性,再多写一行代码。但是,由于逻辑属性的概念,我们可以享受 margin 类型的另外两种简写:

  • 一种用于块方向
  • 一种用于内联方向

因此,重新审视只需内联方向居中的场景,我们现在可以通过下列方案保持效率:

/* 现代化写法 */
margin-inline: auto;

该示例实现了从物理属性到逻辑属性的微妙转变,这一简单事实意味着,该示例与抛出 margin: auto 一样有效,并且能够适应写入模式的变化。如果页面突然发现自己处于垂直从右到左模式,当内联方向向上下而非左右流动时,它仍然会自动将元素在内联方向居中。

一般情况下调整写作模式

我已经给逻辑属性的优点疯狂点赞。实际上,自 Flexbox(弹性盒模型)和 CSS Grid(网格布局)以来,逻辑属性对我们今天编写 CSS 方式的影响,可能比任何其他 CSS 功能都要大。

传统上,我们可能会为“正常”书写方向编写一组样式,然后使用 [dir="rtl"],或其他方案在 HTML 级别上定位书写模式。但今天,凡是过往,皆为序章,我们使用逻辑属性卷土重来。这样,布局就会遵循书写模式!

在更改写入模式时,我们通常可能需要重置物理边距,如下所示:

/* 传统写法 */
body {
  margin-left: 1rem;
}

body[dir='rtl'] {
  margin-left: 0; /* 重置左边距 */
  margin-right: 1rem; /* 应用右边距 */
  text-align: right; /* 文本排列到另一边 */
}

只要我们使用逻辑属性,就不再出现一大坨“代码屎山”:

/* 现代化写法 */
body {
  margin-inline-start: 1rem;
}

修剪多余的间距

我确信大家已经在 <nav> 导航标签里使用过无序列表的链接,来实现项目的主要或全局导航。

<nav>
  <ul>
    <li><a href="/follow">关注</a></li>
    <li><a href="/like">点赞</a></li>
    <li><a href="/star">收藏</a></li>
  <ul>
</nav>

在这种需求下,我确信您大概率被要求并排显示这些链接,而不是像无序列表那样顺其自然地垂直堆叠。我们中某些已经编写多年样式的老玩家可能已经形成肌肉记忆,可以将这些列表项的 display 属性从默认的 block 元素更改为 inline-box 元素,同时保留块元素的盒模型属性:

/* 传统写法 */
li {
  display: inline-block;
}

这些列表项之间需要空间。毕竟,它们不再占用其父级的全部可用宽度,因为 inline-block 元素的宽度只与它们包含的内容、以及边框、填充、边距和偏移量一样宽。传统上,这意味着,像我们对居中所做的那样应用 margin,但只有在我们想要的内联方向上应用 margin 属性,可能是 margin-left/margin-right/margin-inline-end

假设我们正在使用逻辑属性,并希望在内联方向的项目列表末尾有一个边距:

/* 传统写法 */
li {
  display: inline-block;
  margin-inline-end: 1rem;
}

粉丝请注意,现在我们对所有列表项都有 margin。最后一个列表项实际上不需要 margin,因为它后面没有其他项目了。

新年里 CSS 更易编写

大多数情况下,这简直酷毙了,但该方案使布局变得容易受到影响。如果产品经理让我们在 <nav> 标签旁边显示另一个元素,总不能打一架吧?突然间,我们正在处理多余的间距,这可能会影响我们决定如何设计新元素的样式。这是技术负债的一种形式。

最好搞定此问题,并不留后患地解决间距问题。我们可以使用更现代化的功能,比如 :not() 伪类。这样,我们就可以将最后一个列表项排除在 margin 需求之外。

/* 现代化写法 */
li {
  display: inline-block;
}

li:not(:last-of-type) {
  margin-inline-end: 1rem;
}

粉丝请注意,以后我们还有更精简的现代化写法。我们可以使用 margin-trim 属性,当应用于父元素时,它会像做头发一样剪掉多余的间距,有效地折叠边距,防止子元素与父元素的边缘齐平。

/* 更精简的现代化写法 */
ul {
  margin-trim: inline-end;
}

li {
  display: inline-block;
  margin-inline-end: 1rem;
}

粉丝请注意,margin-trim 目前是实验性功能,在我疯狂码字的此时此刻,该功能能且仅能被 Safari 浏览器支持。是的没错,这些最前沿的现代化特性,可能不完全是您想直接交付甲方、落地生产的东东。仅仅因为某些东东很“时髦”,并不意味着它是 KPI 的“银弹”!

事实上,可能有一个更好的解决方案,没有任何大坑,而且它就在近在眼前:Flexbox。将无序列表转换为灵活的容器,会覆盖列表项的默认块级流式布局,而不更改其显示,为我们提供所需的并排布局。另外,我们还可以读写 gap 属性,我们可能会将其视为内置 margin-trimmargin,因为它只应用子级之间的空间,而不是应用它们的方方面面。

/* 不是最时髦,但是最精简 */
ul {
  display: flex;
  gap: 1rem;
}

这就是我大爱 CSS 的原因。CSS 就像为你写诗,因为有一大坨方案可以表达同一件事,其中某些方案比其他方案更优雅。但“最好”的方案是符合你的心智模型的方案。如果结果如你所愿,那就不用怕其他人先质疑、再质疑。

粉丝请注意,删除有序列表和无序列表上的列表样式是常见需求,比如 list-style-type: none,但这会产生副作用,Safari 浏览器剥离了列表项的默认可访问角色。一种“修复方案”是将角色添加回 HTML <ul role="list> 中。还有另一种方案,允许我们通过删除具有空引号值的列表样式类型,来保留 CSS:

ul {
  list-style-type: '';
}

保持比例

我们过去几乎没有什么选择来保持元素的物理比例。举个栗子,如果我们想要一个完美的正方形,我们可以依赖元素 width/height 显式声明的固定像素单位:

/* 传统写法 */
height: 500px;
width: 500px;

或者,也许我们需要元素的大小稍微弯曲,因此我们更喜欢相对单位。在这种需求下,像百分比这样的值就很头大,因为像 50% 这样的值是相对于元素的父容器的大小,而不是元素本身的大小。然后,父元素需要固定尺寸或其他完全可预测的尺寸。这几乎是一个无限循环,试图通过设置另一个包含元素的比例,来维持一个元素的 1:1 比例。

所谓的“Padding Hack”确实是一个聪明的解决方案,而不是真正的“奇技淫巧”,而是 CSS 盒模型大师级命令的展示。

如果我们将元素的高度强制为零(height: 0;),且没有任何边框,那么填充将是盒模型中影响高度的唯一部分,我们将得到正方形”。—— C.C.

无论如何,这需要一大坨巧妙的“代码屎山”才能实现。CSS 工作组提出了一个更优雅的解决方案:aspect-ratio 属性。

/* 精简写法 */
aspect-ratio: 1;
width: 50%;

现在,无论元素的宽度如何响应其周围环境,我们都有一个完美的正方形,这为我们提供了更简单有效的规则集,并且更能适应变化。

卡片悬停效果

在卡片上设置悬停效果的样式传统上是一个复杂的过程,我们将元素包装在 <a> 标签中,并挂钩到其悬停时相应的卡片样式。但是 :has() 伪类现在从 Firefox 121 开始在所有主要浏览器中都普遍支持!我们可以将链接作为子元素放置在卡片中,并在卡片悬停时将其设置为父元素。

/* 传统写法 */
a.card-link:hover > .card {
}

/* 现代化写法 */
.card:has(:hover, :focus) {
}

完结撒花

这些只是 CSS 去年提供的新工具,私以为这些东东对我今天编写样式的方式影响颇大。我可以想到本文尚未提及的其他功能,但日后再说。这些功能包括但不限于:

  • 字符长度单位 ch
  • text-wrap: balance
  • Cascade Layers(级联图层)
  • 容器查询
  • <selectmenu> 标签
  • CSS 嵌套语法(SCSS/LESS 已死?)
  • 更多前沿技术日后再说……

我知道有一段时间,我们中的某些人先质疑、再质疑现在的 CSS 的心智模型是否“猪脑过载”,并认为 CSS 的学习曲线比万里长城还陡峭。但私以为随着 CSS 变量和 CSS 嵌套语法等原生特性的普及,我们以后即使不借助 SCSS/LESS 等工具,也能灵活地使用给力的 CSS,这某种意义上也降低了前端工程化的技术熵,将我们从技术负债中解放出来。

本期话题是 —— 你觉得哪个 CSS 的新特性未来可期?欢迎在本文下方群聊自由言论,文明共享。

《前端 9 点半》每日更新,持续关注,坚持阅读,每天一次,进步一点

谢谢大家的点赞,掰掰~

新年里 CSS 更易编写

原文链接:https://juejin.cn/post/7332767759431548966 作者:人猫神话

(0)
上一篇 2024年2月9日 上午10:31
下一篇 2024年2月9日 上午10:41

相关推荐

发表回复

登录后才能评论