原生CSS如何嵌套使用?

目录
文章目录隐藏
  1. 介绍
  2. CSS 嵌套的好处
  3. CSS 嵌套规则
  4. 嵌套示例:Active, Focus, Hover
  5. 嵌套示例:Post Content
  6. 嵌套示例:卡片组件
  7. 嵌套示例:表单输入
  8. 在探索 CSS 嵌套时发现的错误
  9. 检测 CSS 嵌套支持
  10. 结语

我们在做前端开发时,经常会使用 CSS 预处理器以及预处理器中的嵌套特性。它一直是一个受欢迎的功能,我一直都在使用 CSS 预处理器。

今年所有的主流浏览器都支持原生CSS 嵌套:Chrome、Firefox 和 Safari。这是一个重要的 CSS 功能,这将使编写 CSS 更加容易。在本文中我将记录到目前为止我所学到的关于 CSS 嵌套的知识,并与您分享我的发现,包括使用案例和示例。

介绍

CSS 嵌套是许多开发人员期待已久的功能之一。我们曾经依赖于 CSS 预处理器,如 Sass 或 Less。让我们来回顾一下以前的做法:

请看下面的例子。我们有一个图标嵌套在选择器.nav__item中。

.nav__item {
  .icon {
    display: flex;
    padding: 1rem;
  }
}

以上是一个 Sass 语法的代码。编译后,它在浏览器中看起来像下面这样:

.nav__item .icon {
  display: flex;
  padding: 1rem;
}

使用原生 CSS 嵌套,相同的 CSS 将按原样工作。这里有一个图,显示了原生 CSS 嵌套和浏览器 DevTools 之间的比较。

原生 CSS 如何嵌套使用

请注意浏览器显示 CSS 的方式与 CSS 代码中的显示方式几乎一致。

如果这个 CSS 是用 Sass 编译的,浏览器会显示如下:

用 Sass 编译的

CSS 嵌套的好处

在我看来,嵌套 CSS 有一些很合理的理由,使其变得有用:

  • 更容易阅读 CSS
  • 风格一致
  • 确定特定样式的作用域
  • 对没有类或 ID 的 HTML 元素添加样式

CSS 嵌套规则

为了让你了解 CSS 嵌套,我将尝试提供不同 CSS 问题的案例,以及嵌套如何帮助解决这些问题。

首先,你需要学习与符号&。有多数情况下,这个符号是必要的。

嵌套没有类或 ID 的元素

CSS 嵌套规则

在这个例子中,<a>元素是通过.nav__item设置样式。要使 CSS 有效,使用&符号是可选的。

nav__item {
  & a {
    display: block;
    padding: 1.5rem 1rem;
  }
}

/* 等同于 */
.nav__item a {
}

您也可以选择不使用&符号:

.nav__item {
  a {
    display: block;
    padding: 1.5rem 1rem;
  }
}

/* 等同于 */
.nav__item a {
}

请注意这是一个最近的更新,被称为宽松的 CSS 嵌套。它适用于最新的 Chrome Canary 和 Safari 技术预览版。

使用类嵌套元素

使用类嵌套元素

以前面的例子为例,但假设<a>元素有一个 HTML 类。

.nav__item {
  .link {
    display: block;
    padding: 1.5rem 1rem;
  }
}

/* 等同于 */
.nav__item .link {
}

这里不需要使用&,只有类名称也正常生效。

嵌套 CSS 组合器

CSS 原生嵌套的一个好处是可以使用组合器。让我们来看一些例子。

在下面的例子中,我想选择.nav__item的每个元素,它前面有另一个具有相同类的元素。因此我使用了相邻兄弟选择器。

嵌套 CSS 组合器

在原生 CSS 嵌套中,我们可以使用&符号来模拟这种效果。请注意我重复使用了它两次。

.nav__item {
  & + & {
    border-left: 2px solid;
  }
}

魔术发生在第二次重复的&。在这里浏览器将理解我想使用相邻的兄弟选择器。让我给你看一个图表来说明这一点:

相邻的兄弟选择器

另一个例子是嵌套子组合器。它可以选择元素的直接子元素。

.nav__item {
  > a {
    padding: 1rem;
  }
}

嵌套示例:Active, Focus, Hover

:active:focus:hover是通过用户操作激活的 CSS 伪类。

嵌套示例:Active, Focus, Hover

使用 CSS 嵌套,可以一次嵌套它们以避免代码重复。让我们以:hover为例:

button {
  &:hover {
    background-color: var(--bg-color);
  }

  &:focus {
    outline: solid 2px;
  }
}

使用预处理器进行嵌套时的区别在于浏览器将像这样渲染它:

button:hover {
  background-color: var(--bg-color);
}

button:focus {
  outline: solid 2px;
}

让我们来看看原生 CSS 嵌套在 Chrome、Safari 和 Firefox 中是如何呈现的。

原生 CSS 嵌套在 Chrome、Safari 和 Firefox 中是如何呈现的

嵌套示例:Post Content

第一个尝试 CSS 嵌套的例子之一是对帖子的正文内容设置样式。想象一下,一篇文章有正文标题、文本、图像、引用等等。

嵌套示例:Post Content

标题

我们倾向于像下面这样设计标题:

.post-content h1,
.post-content h2,
.post-content h3,
.post-content h4 {
  /* styles here */
}

使用 CSS 嵌套,它更简单:

.post-content {
  h1,
  h2,
  h3,
  h4 {
    color: var(--heading-color);
    font-weight: var(--heading-font-bold);
    margin-bottom: var(--size-2);
  }
}

我们也可以使用:is()选择器来做同样的事情。

.post-content {
  :is(h1, h2, h3, h4) {
    color: var(--heading-color);
    font-weight: var(--heading-font-bold);
    margin-bottom: var(--size-2);
  }
}

段落元素

一个常见的情况是设置段落内部的链接样式。在这种情况下,CSS 的嵌套功能非常好用。

.post-content {
  & p {
    color: var(--color-black);

    & a {
      font-weight: bold;
      text-decoration: underline;
    }
  }
}

链接可能也需要悬停或焦点效果。

.post-content {
  & p {
    color: var(--color-black);

    & a {
      font-weight: bold;
      text-decoration: underline;

      &:hover {
        /* hover styles */
      }
    }
  }
}

我们还可以用在嵌套媒体查询。

.post-content {
  & p {
    /* base styles */

    @media (min-width: 400px) {
      /* do something */
    }
  }
}

帖子图片

帖子图包含一个图像和一个可选的<figcaption>来显示图像的描述。

帖子图片

在我的示例中,如果<figure>有标题,我需要对它进行不同的样式设置。可以通过嵌套 CSS :has() 实现。

.post-content {
  & figure {
    & img {
      /* the figure's image styles */
    }

    /* changes to the <figure> container, if it has a figcaption element */
    &:has(figcaption) {
      display: flex;
      align-items: start;
    }

    & figcaption {
      /* caption styling */
    }
  }
}

文章列表

文章列表

我需要为所有列表项添加边框,除了最后一个。为此,我使用了:not()选择器。

.post-content {
  li {
    &:not(:last-child) {
      border-bottom: 1px solid;
    }
  }
}

要使用:not(),我们需要在它前面附加一个&符号。

自定义标题间距

如果<h3><h4>之后是代码片段,我需要减少它们下方的间距。

自定义标题间距

.post-content {
  & h3 + [class*="language-"],
  & h4 + [class*="language-"] {
    margin-top: 0.5rem;
  }
}

嵌套示例:卡片组件

我将演示一个简单的卡片组件,它使用 CSS 嵌套来实现所需的样式。

嵌套示例:卡片组件

假设有一个默认或基本样式的.card元素,我将继续演示 CSS 嵌套的使用。

.card {
  /* default card styles */
}

如果容器宽度大于400px,我希望卡片成为一个 Flex 容器。

.card {
  /* default card styles */

  /* if the container width is 400px or bigger */
  @container card (min-width: 400px) {
    display: flex;
  }
}

嵌套示例:表单输入

一种常见的情况是对输入的占位符进行样式设置。问题是每个浏览器都有自己的前缀。

嵌套示例:表单输入

由于前缀样式需要一个双冒号,我们需要使用与号&,否则样式将中断。

input {
  --placeholder-color: #969696;
  /* other styles */

  &::-webkit-input-placeholder {
    color: var(--placeholder-color);
  }

  &::-moz-placeholder {
    color: var(--placeholder-color);
    opacity: 1;
  }

  &:-moz-placeholder {
    color: var(--placeholder-color);
  }
}

在探索 CSS 嵌套时发现的错误

使用不带&号的通用选择器

假设我们有一张卡片,我们想选择其中的所有元素。使用 CSS 原生嵌套,这应该可以工作:

.card {
  * {
    /* styles here */
  }
}

我发现这在 Chrome 稳定版中不起作用,但在 Chrome Canary 121、Safari 17.1 和 Firefox 119 中工作正常。

.card {
  & * {
    /* styles here */
  }
}

使用不带&号的自定义属性

在这个问题中,选择一个不带&号的自定义属性将不会呈现预期的结果。

.card {
  [data-type="featured"] {
    /* styles here */
  }
}

我发现这在 Chrome 稳定版中不起作用,但在 Chrome Canary 121、Safari 17.1 和 Firefox 119 中工作正常。

为了解决这个问题,我们需要附加一个&符号:

.card {
  &[data-type="featured"] {
    /* styles here */
  }
}

这两个 bug 都在 Chrome Canary 中的宽松 CSS 嵌套版本中得到了修复。

检测 CSS 嵌套支持

可以使用@supports来检查 CSS 嵌套支持。在我们的例子中,我们想检查浏览器是否识别&可以使用以下代码。

@supports selector(&) {
  .post-content {
    & h2 {
      /* styles here. */
    }
  }
}

对我来说,现在还在使用PostCSS嵌套插件,它将原生 CSS 嵌套编译为普通 CSS。一旦它可以安全的使用后,就可以不再使用插件了。

结语

CSS 嵌套是一个重要的功能,它将增强我们编写 CSS 的能力。目前使用嵌套是可行的,但需要注意受众情况,因为目前对支持程度仍然较新。

原文链接:点击这里

「点点赞赏,手留余香」

1

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
码云笔记 » 原生CSS如何嵌套使用?

发表回复