9

原生CSS嵌套使用

 9 months ago
source link: https://www.fly63.com/article/detial/12599
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

更新日期: 2023-12-07阅读: 122标签: 

如果您是使用 css 预处理器的前端开发人员,那么您可能遇到或使用过嵌套功能。这是一个很受欢迎的功能,对我来说,它是让我继续使用 CSS 预处理器的功能之一。

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

除了您的兴奋和专注之外,没有任何先决条件可以遵循。

CSS 中的嵌套一直是许多开发人员期待已久的功能之一。我们曾经依赖 Sass 或 Less 等 CSS 预处理器。让我快速回顾一下:

考虑以下示例。我们有一个嵌套在选择器中的图标.nav__item。

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

以上是有效的 Sass 代码。编译后,它在浏览器中将如下所示:

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

通过本机 CSS 嵌套,相同的 CSS 将按原样工作。下图显示了原生 CSS 嵌套和浏览器 DevTools 之间的比较。

657142bd13065.jpg

请注意浏览器显示 CSS 的方式(几乎)与在 CSS 中显示的方式相似。

如果这个 CSS 是在 Sass 中编译的,浏览器将显示如下:

657142c2d0c8f.jpg

CSS 嵌套的好处

我认为嵌套 CSS 有用有一些正当理由:

  • CSS 更容易阅读。
  • 将风格分组在一起。
  • 确定特定样式的范围。
  • 设计没有类或 ID 的 html 元素。

CSS 嵌套规则

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

首先,您需要了解 & 符号&。在多种情况下需要使用此符号。

嵌套没有类或 ID 的元素

657142c98d81a.jpg

在此示例中,该<a>元素通过.nav__item. 为了使 CSS 有效,可以选择使用 & 符号。

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

/* Same as: */
.nav__item a {
}

您还可以选择不使用“&”:

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

/* Same as: */
.nav__item a {
}

请注意,这是最近的更新,称为“宽松 CSS 嵌套”。它适用于最新的 Chrome Canary 和 Safari 技术预览版。查看Adam Argyle 撰写的关于轻松嵌套的文章

将元素与类嵌套

657142d395654.jpg

采用与前面相同的示例,但假设该<a>元素具有 HTML 类。

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

/* Same as: */
.nav__item .link {
}

这里不需要使用&符号。类名可以正常工作。

嵌套 CSS 组合器

CSS 原生嵌套的好处之一是使用组合器。让我们举几个例子。

在下面的示例中,我想选择具有相同类的每个元素,该类.nav__item前面有另一个具有相同类的元素。为此,我使用了相邻的同级选择器

657142dca05ec.jpg

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

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

神奇的事情发生在第二次重复“&”符号时。在这里,浏览器会理解我想使用相邻的同级选择器。让我给你看一张图来说明这一点:

657142e415d9f.jpg

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

.nav__item {
  > a {
    padding: 1rem;
  }
}
.nav__item {
  & a {
    color: blue;
  }
}

这是最初的 CSS 嵌套规范所要求的。在Safari TP 179+Chrome Canary 120中,嵌套元素不再需要 & 符号。

结果,进行了以下工作:

.nav__item {
  a {
    color: blue;
  }
}

唯一的问题是您必须回退到规范的先前版本,其中必须包含&&符号。

嵌套示例:活动、焦点、悬停

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

657142ebcd869.jpg

通过 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 中是如何渲染的。

657142f393775.jpg

我对 CSS 嵌套的 DevTools UX 有一些想法,并将在本文后面讨论它们。

嵌套示例:帖子内容

尝试 CSS 嵌套的第一个示例是设计帖子正文内容的样式。想象一篇包含正文标题、文本、图像、引文等的文章

6571431307df8.jpg

我们倾向于将标题设计为如下所示:

.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 */
    }
  }
}

在某些情况下,CMS 可能会将一个<p>元素包装在另一个元素中,出于样式目的,您只需对直接 <p>元素进行样式设置。

.post-content {
  /* Select the direct <p> elements */
  > p {
    /* base styles */
  }
}

在此示例中,报价获得其自定义样式,并且<p>选择报价内的元素以将底部边距重置为零。

.post-content {
  & blockquote {
    /* custom quote styling */

    & p {
      margin-bottom: 0;
    }
  }
}

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

6571431b93a1b.jpg

在我的示例中,如果它有标题,我需要采用<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 */
    }
  }
}
65714321edce7.jpg

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

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

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

自定义标题间距

我需要减少下面的间距<h3>,<h4>如果其中之一后面跟着代码片段。

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

正如您在这个实际示例中所看到的,CSS 嵌套的使用非常简单,尤其是如果您有 CSS 预处理器经验的话。

嵌套示例:卡片组件

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

657143301fb2c.jpg

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

.card {
  /* default card styles */
}

嵌套容器查询

如果容器宽度大于400px,我希望卡片成为弹性容器。

.card {
  /* default card styles */

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

设置段落元素的样式

我想通过<h3>. 这样,我可以向<p>元素添加边距和填充。如果不存在,用户界面将不会有额外的间距。

.card__content {
  & h3 + p {
    border-top: 1px solid #000;
    padding-top: 0.5rem;
    margin-top: 0.5rem;
  }
}

当容器宽度为 400px 或更大时,.card__content元素也应该成为弹性容器。

.card__content {
  & h3 + p {
    border-top: 1px solid #000;
    padding-top: 0.5rem;
    margin-top: 0.5rem;
  }

  @container card (min-width: 400px) {
    display: flex;
    flex-direction: column;
    justify-content: center;
  }
}

嵌套示例:表单输入

常见的情况是设置输入占位符的样式。问题是每个浏览器供应商都有自己的前缀(哦,是 2023)。

6571433781187.jpg

由于前缀样式需要双冒号,因此我们需要使用 & 符号&,否则样式将被破坏。

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 嵌套直接编写前缀样式有什么区别。

/********** Option 1: native nesting **********/
input {
  &::-webkit-input-placeholder {
    color: var(--placeholder-color);
  }
}

/********** Option 2: without nesting **********/
input::-webkit-input-placeholder {
  color: var(--placeholder-color);
}

两者没有区别。两者具有相同的特异性(0, 1, 1)。

嵌套示例:通过其父元素设置元素的样式

我们可以使用原生 CSS 嵌套来根据子项所在的位置更改其样式。例如,如果.button元素位于.box父元素内,则它应该采用完整宽度。

6571433d40219.jpg
<div class="box">
    <h2>Get access to all features</h2>
    <p>Create an account now and get access to all exclusive features.</p>
    <a href="/offer" class="button">Create an account</a>
</div>
.button {
  .box & {
    width: 100%;
  }
}

/* equivalent to */
.box .button {
}

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

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

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

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

我发现这在 Chrome 稳定版中不起作用,但在 Chrome Canary 121、Safari 17.1 和 Firefox 119 中运行良好。

修复方法是附加一个 & 符号。

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

在此问题中,选择不带“&”符号的数据属性将不会呈现预期结果。

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

我发现这在 Chrome 稳定版中不起作用,但在 Chrome Canary 121、Safari 17.1 和 Firefox 119 中运行良好。

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

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

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

检测对 CSS 嵌套的支持

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

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

您可以探索其他选项来检测Bramus 的 Codepen中的支持。

对我来说,今天我将使用PostCSS 嵌套插件,它将原生 CSS 嵌套编译为普通 CSS。一旦可以安全使用,我就会放弃该插件。

用于 CSS 嵌套的 DevTools UX

我不太喜欢浏览器 DevTools 中 CSS 嵌套的当前 UX。

657143435d0e3.jpg

我写了一篇单独的文章,其中探讨了一些关于我希望如何在 DevTools 中进行 CSS 嵌套的建议。

CSS 嵌套是一项主要功能,它将增强我们编写 CSS 的方式。目前,可以使用嵌套,但您需要小心观众,因为支持仍然是新的。

我希望你学到了一些有用的东西。感谢您的阅读!

翻译来自:https://ishadeed.com/article/css-nesting

链接: https://www.fly63.com/article/detial/12599


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK