大胆尝试这些新的CSS属性,释放CSS的力量吧(一)

CSS/设计
236
0
0
2024-02-02

本文章系《Unleashing the Power of CSS》(释放CSS的力量,暂且这么翻译吧)一书的学习笔记,希望通本书的学习,系统的梳理下CSS相关的高级新特性。本篇文章是其第一部分,由于全书英文版,理解和阅读会有偏差,欢迎各位大佬们指正,我们一起共同提高。

开篇

在过去的几年里,CSS引入了许多新的改进功能,并且跨浏览器的努力提高了兼容性,使这门语言比以往任何时候都更加稳定!让我们回顾一下布局、响应式设计、元素样式、属性和选择器方面的这些增强功能,并且也来看一看即将推出的新功能。

现在,浏览器之间新功能的协调实施意味着我们几乎可以在它们出现的同时开始使用这些功能,这对于保持我们的样式表尽可能简单非常有帮助。现在,只需几个单行属性就可以替代多行的hacky解决方案。在某些情况下,新提供的功能甚至可能意味着我们可以删除以前需要的JavaScript解决方案,以解决旧限制!

新的和增强的属性

Custom Properties(自定义属性或变量)

随着Internet Explorer 11的生命周期进入尾声,现在是时候开始使用自定义属性了!自定义属性,也被称为“CSS变量”,允许我们定义可在样式表中重复使用的值。自定义属性可以作为属性的整个值或部分值使用,我们还可以在JavaScript中修改自定义属性。

aspect-ratio

一种新的属性可以消除“填充hack”,它是 aspect-ratio 。它按照其名称的意思,允许我们为元素定义一个纵横比。我所提到的 hack 通常用于保持视频嵌入的16:9比例。现在,通过这个属性和声明 aspect-ratio: 16/9 ,可以实现这个比例。它还是实现完美正方形的快速方法,使用 aspect-ratio: 1 即可。

这是一个代码演示,展示了如何使用 aspect-ratio 与旧属性 object-fit 结合使用,以保持一致的头像大小,无论原始图像的比例如何,而且不会扭曲图像。

Html部分

<ul class="avatar-list">
  <li>
    <figure>
      <img src='https://images.unsplash.com/photo-1640952131659-49a06dd90ad2?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE2NjkwNTE0MTQ&ixlib=rb-4.0.3&q=80&w=400' alt=''>
      <figcaption>Aaron Fizzle</figcaption>
    </figure>
  </li>
  <li>
    <figure>
      <img src='https://images.unsplash.com/photo-1544725176-7c40e5a71c5e?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE2NjkwNTE0MTQ&ixlib=rb-4.0.3&q=80&w=400' alt=''>
      <figcaption>Lily Sebastian</figcaption>
    </figure>
  </li>
  <li>
    <figure>
      <img src='https://images.unsplash.com/photo-1628157588553-5eeea00af15c?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE2NjkwNTE1MTU&ixlib=rb-4.0.3&q=80&w=400' alt=''>
      <figcaption>Devon Albian</figcaption>
    </figure>
  </li>
</ul>

Css部分

.avatar-list img {
  /* Make it a square */
  aspect-ratio: 1;
  /* Fit the image to it's container without distortion */
  object-fit: cover;
  /* Make the square round */
  border-radius: 50%;
  width: 100%; /* Make sure the image fills the container */
  height: 100%; /* Make sure the image fills the container */
}

* {
  box-sizing: border-box;
  margin: 0;
}

html {
  height: 100%;
}

body {
  min-height: 100%;
  font-family: system-ui, sans-serif;
  display: grid;
  place-content: center;
  background-color: mediumvioletred;
  padding-inline: 1rem;
}

/* Standard responsive image fix */
img {
  max-width: 100%;
}

.avatar-list {
  list-style: none;
  padding: 0;
  background: #fff;
  border-radius: 0.5rem;
  box-shadow: 0.25rem 0.25rem 0.5rem -0.15rem hsl(0 0% 0% / 30%);
  border: 1px solid hsl(0 0% 0% / 10%);
}

.avatar-list li {
  position: relative;
  padding: 3%;
  font-size: 1.35rem;
  font-size: clamp(0.8rem, 0.8rem + 2cqi, 1.5rem);
  color: hsl(0 0% 45%);
  letter-spacing: 0.03em;
}

.avatar-list li + li::before {
  content: "";
  position: absolute;
  top: 0;
  left: calc(15% + 1rem);
  right: 3%;
  border-top: 1px solid hsl(0 0% 0% / 15%);
}

.avatar-list figure {
  display: grid;
  grid-template-columns: 15% 1fr;
  align-items: center;
  gap: 1rem;
}

https://codepen.io/SitePoint/pen/oNaNaao

Individual Transform Properties(个体变换属性)

浏览器中还新增了各自的变换属性。Chrome 104进行的CSS变换具有独立的属性。这些属性是 scale , rotate 和 translate ,您可以使用它们来单独定义变换的各个部分。

并非所有的转换函数都有相应的个体属性,例如 skewX() 和 matrix() 。
.target {
  translate: 50% 0;
  rotate: 30deg;
  scale: 1.2;
}

Logical Properties(逻辑属性)

CSS的Logical Properties(逻辑属性)是一种用于处理文本和布局的属性,它们考虑了文本流的逻辑方向而不是物理方向。在CSS中,文档可以采用不同的书写模式,例如从左到右(LTR)的水平书写模式和从右到左(RTL)的水平书写模式,以及垂直书写模式。Logical Properties的目标是使样式更加灵活,适应不同的书写模式,而不需要为每种书写模式都编写不同的样式。

如果我们要为国际受众管理内容,则可以考虑使用逻辑属性。适用于大多数 CSS 2.1 属性,逻辑变体考虑了文本的编写模式和流。对于标准的英文文本,我们将“左/右”换成“内联”,用“top/bottom”换成“block”:

.element {
  margin-block: 2rem;
}

如上例所示,逻辑属性还提供了一次设置两边的简写,其中 margin-block 水平写入模式等效于 set margin-top 和 margin-bottom 。

新的选择器

近期对CSS最有影响力的三个变化是:is、:where和:has伪类选择器。以下是它们的概述:

:is() ,它用于选择满足括号内任何选择器的元素。这个伪类可以帮助你编写更简洁和可维护的 CSS 代码,尤其是当你需要同时匹配多个选择器时。例如, :is(#id, a, .class) 将具有一个 id 的特异性。

:where 是一个 CSS 伪类选择器,它与 :is 伪类选择器类似,可以用于选择满足括号内任何选择器的元素。它的语法也与 :is 相似,但有一个重要的区别::where 不会影响优先级。

与 :is 不同,:where 不会增加或改变样式规则的优先级。这意味着,无论你在样式表中的什么位置使用 :where,它都不会改变选择器的权重,不会增加特异性(specificity),也不会影响其他样式规则的优先级。

这使得 :where 在一些情况下非常有用,特别是当你需要选择一组元素,但不希望影响其他选择器的优先级时。例如,假设你有一个已经存在的 CSS 样式表,其中包含了一些具有不同权重和特异性的样式规则,但你希望添加一个新的规则,同时不改变其他规则的优先级,你可以使用 :where 来实现这一点。

/* 不使用 :where */
.btn {
  background-color: #3498db;
}

/* 使用 :where,不影响其他规则的优先级 */
:where(.btn-primary, .btn-secondary, .btn-danger) {
  background-color: #3498db;
  color: white;
}

:has() 是期待已久的“父选择器”,它允许检查父元素是否包含特定的子元素,并对父元素进行样式设置,或者扩展为复合选择器以对子元素进行样式设置。(本系列教程中有关于 :has() 的完整教程。)

这个演示利用 :where() 、 :is() 和 :has() 来创建一个作者简介组件,根据是否有头像来改变网格显示属性。

<aside class="bio">
  <img class="avatar" src='https://images.unsplash.com/photo-1554727242-741c14fa561c?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE2NzExNDcxMjM&ixlib=rb-4.0.3&q=80&w=400' alt=''>
  <h2>Jane Stylesheet</h2>
  <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsa quam aspernatur, nobis ex rem iure!</p>
</aside>

<aside class="bio">
  <h2>Bob Markup</h2>
  <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquam neque a blanditiis praesentium impedit.</p>
</aside>
* {
  box-sizing: border-box;
  margin: 0;
}

body {
  font-family: system-ui;
  padding: 3vw;
  background-color: mediumvioletred;
}

img {
  display: block;
  max-width: 100%;
}

:where(* + *) {
  margin-block-start: 1rem;
}

.bio :is(h2, p) {
  margin-block-start: 0;
}

.bio {
  background-color: white;
  display: grid;
  gap: 1rem;
  border-radius: 0.5rem;
  padding: 5%;
  box-shadow: 0 0 10px -2px hsl(0 0% 0% / 85%);
}

.bio:has(.avatar) {
  grid-template-areas: "avatar name" "avatar bio";
  grid-template-columns: min(25vw, 80px) 1fr;
}

.bio:has(.avatar) :not(.avatar) {
  grid-column: bio;
}

.bio .avatar {
  grid-area: avatar;
}

.avatar {
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 50%;
}

https://codepen.io/SitePoint/pen/WNaeJOy

:has() 在撰写本文时仅部分浏览器支持,因此上述演示目前仅适用于Safari 15.4+和Chrome/Edge 105+,以及启用 layout.css.has-selector.enabled 标志的Firefox 103。

增强的 :not()

最近,:not() 选择器已经增强,可以接受一个选择器列表,这使得 :not(nav a, footer a) 成为有效的语法。然而,与 :is() 和 :where() 不同,这个更新并没有使 :not() 对于无效的选择器更加宽容,因为需要保持向后兼容性支持。

焦点选择器

下面的两个新伪类都会影响焦点行为。当子元素处于焦点状态时,可以使用 :focus-within 选择器来为父元素设置样式,比如表单字段周围的容器。对于元素焦点样式,我们现在可以使用 :focus-visible ,它最近取代了 :focus 成为跨浏览器默认的元素焦点样式。

下面是 :focus-within 的一些关键点和与 :focus 的区别:

:focus-within 选择器:

  • 选择包含有焦点元素的祖先元素。
  • 当用户在页面上的某个元素上聚焦(例如,输入框或按钮),并且该元素是其祖先元素(例如,一个表单或一个包含该输入框的 div)内的子元素时,祖先元素将匹配 :focus-within。
  • 通常用于创建包含输入框的表单的外观,以在用户输入时改变整个表单的样式或行为。

:focus 选择器:

  • 选择当前具有焦点的元素。
  • 通常用于样式化或增强当前拥有焦点的元素,例如,更改输入框的边框颜色或文本区域的背景颜色。
  • 不会选择包含有焦点元素的父元素。

假设有以下 HTML 结构:

<div class="container">
  <input type="text" id="username" />
  <input type="password" id="password" />
</div>

现在,我们可以使用 :focus 和 :focus-within 来添加一些样式:

/* 当输入框具有焦点时,样式化输入框本身 */
input:focus {
  border: 2px solid blue;
}

/* 当包含有焦点输入框的容器具有焦点时,样式化整个容器 */
.container:focus-within {
  background-color: lightgray;
}

在上面的示例中,当用户点击输入框时,输入框自身会具有蓝色边框(使用 :focus 选择器),同时包含有焦点输入框的容器 .container 也会变为灰色背景(使用 :focus-within 选择器)。这使得用户在与表单交互时,不仅输入框本身被强调,整个表单容器也能够获得焦点的可视反馈。

总之,:focus-within 选择器用于选择包含有焦点元素的祖先元素,而 :focus 选择器用于样式化具有焦点的元素本身。这两个选择器可以一起使用,以创建更丰富的交互体验。

::marker

最后但并非最不重要的是,伪元素 ::marker 允许我们直接选择和样式化 <ul> 和 <ol> 元素上的列表项符号和编号,以及 <summary> 元素的“插入符号”。这意味着我们可以使用 ::marker 来仅改变列表的符号颜色!

元素样式的改进

accent-color

框架和设计系统最常见的改变之一是本地表单字段样式。在 accent-color 属性出现之前,甚至改变表单元素的颜色都是不可能的。现在,我们可以通过 accent-color 影响单选按钮和复选框的选中外观,以及范围输入和进度元素的填充状态。

下面是一个示例,演示了如何使用 accent-color 属性:

a {
  accent-color: blue;
}

在这个示例中,accent-color 属性应用于所有链接元素 (<a>),并将链接的强调颜色设置为蓝色。

color-scheme

如果我们想要根据用户的浅色或深色模式偏好来调整我们的界面,可以使用自定义切换和/或 prefers-color-scheme 查询,我们还应该添加color-scheme属性。这提供了一种选择,可以适应浏览器的UI元素,如滚动条、表单控件和CSS系统颜色。而 accent-color 让我们可以为一些元素选择自定义颜色, color-scheme 则要求浏览器进行更多的适应,例如要求文本输入和文本区域以浅色或深色主题显示。

建议将此应用于 :root 元素,并按照网站默认值的顺序列出这些值。换句话说,如果我们默认为浅色但支持深色,则列出 light dark 。如果我们默认为深色但支持浅色,则列出 dark light 。如果我们只支持 light 或 dark ,只需列出单个值即可:

:root {
  color-scheme: light dark;
}

例如,你可以这样定义一个明亮模式和一个暗模式的颜色方案:

/* 明亮模式 */
@media (prefers-color-scheme: light) {
  body {
    background-color: white;
    color: black;
  }
}

/* 暗模式 */
@media (prefers-color-scheme: dark) {
  body {
    background-color: black;
    color: white;
  }
}

Forced-color Modes (强制色彩模式)

为了完善关于颜色的主题,还有一个偏好查询和属性对需要讨论。在Windows上,一些用户需要“高对比度”主题,其中操作系统强制使用减少的调色板来代替我们定义的颜色。调色板填充系统颜色的值,替换背景、文本、按钮和链接颜色等内容,而像盒子阴影这样的样式则被删除。

如果我们有使用颜色的关键样式,比如产品颜色样本,我们可能需要在 forced-colors 属性旁边使用 force-color-adjust 查询。根据以下配对,我们原始的 .swatch 颜色将被保留:

@media (forced-colors: active) {
  .swatch {
    forced-color-adjust: none;
  }
}
强制使用颜色应该谨慎使用,只有在用户体验受到高对比度主题颜色交换的负面影响时才使用。如果您对高对比度主题不熟悉,请了解如何使用强制颜色进行样式设置。

Text Decoration

在文本装饰方面,我们现在有可用的 text-underline-offset 属性,它允许我们调整定义的 text-decoration 的位置,使其偏离原始位置。text-decoration-thickness 伴随属性允许我们控制 text-decoration 的描边粗细。结合使用这些属性,可以消除使用边框甚至伪元素来样式化链接下划线的hack。

以下样式规则将文本下划线向下偏移 2 像素:

a {
  text-decoration: underline;
  text-underline-offset: 2px;
}

结束

由于文章内容篇幅有限,今天的内容就分享到这里,文章结尾,我想提醒您,文章的创作不易,如果您喜欢我的分享,请别忘了点赞和转发,让更多有需要的人看到。同时,如果您想获取更多前端技术的知识,欢迎关注我,您的支持将是我分享最大的动力。我会持续输出更多内容,敬请期待。