整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

现代CSS:原生 CSS 嵌套综合指南

生 CSS 嵌套(Native CSS nesting)已经被所有现代桌面浏览器所支持!,但是请注意,移动端浏览器支持的还很有限。

1.原生 CSS 嵌套

原生 CSS 嵌套可以像 SASS、LESS 预处理器一样,将相关的选择器组合在一起,从而减少需要编写的规则数量,它可以节省打字时间,并使语法更易于阅读和维护。您可以将选择器嵌套到任意深度,但要小心不要超过两层或三层。嵌套深度没有技术限制,但它会使代码更难以阅读,并且生成的 CSS 可能会变得不必要的冗长。

.button {
   background-color: red;

   &.warning {
     background-color: blue;
   }

   & .icon {
      width: 1rem;
      height: 1rem;
   }
}

虽然原生 CSS 嵌套语法在过去几年中不断发展,使大多数 Web 开发人员感到满意,但不要指望所有 SCSS 代码都能像您期望的那样直接工作。

2.原生 CSS 嵌套规则

您可以将任何选择器嵌套在另一个选择器中,但它必须以符号开头,例如 &, .(类选择器)、#(ID选择器)、@(对于媒体查询)、:::+~>[。换句话说,它不能是对 HTML 元素的直接引用。下面的代码是无效的,不会对 input 元素选择器进行解析:

.parent {
  color: red;

  input {
    margin: 1em;
  }
}
/* Invalid, because "input" is an identifier. */

解决此问题的最简单方法是使用与号 ( &),它以与 Sass 相同的方式引用当前选择器。

2.1.& 符号的使用

.parent {
  color: red;

  & input {
    margin: 1em;
  }

  /* use pseudo-elements and pseudo-classes */
  &::after {}

  &:hover {}

  &:target {}
}
/* valid, no longer starts with an identifier */

或者,您可以使用其中之一:

  • > input:只对子元素生效
  • :is(input): 将选择器列表作为参数,并选择该列表中任意一个选择器可以选择的元素
  • :where(input):优先级总是为 0

它们都可以在这个简单的示例中工作,但是稍后您可能会遇到更复杂的样式表的特异性问题。

它还&允许您在父选择器上定位伪元素和伪类。例如:

p.my-element {

  &::after {}

  &:hover {}

  &:target {}
}

请注意,& 可以在选择器中的任何位置使用。例如:

.child1 {
  .parent3 & {
    color: red;
  }
}

这将转换为以下非嵌套语法:

.parent3 .child1 { color: red; }

您甚至可以在选择器中使用多个 & 符号:

ul {
  & li & {
    color: blue;
  }
}

这将以嵌套 <ul> 元素 ( ul li ul) 为目标,但如果您想保持理智,我建议不要使用它!

2.2.@ 符号的使用

嵌套媒体查询示例:

p {
  color: cyan;
  @media (min-width: 800px) {
    color: purple;
  }
}

3.原生 CSS 嵌套陷阱

3.1.场景一:父选择器包装在 :is() 中

原生 CSS 嵌套将父选择器包装在 :is() 中,这可能会导致与 Sass 输出的差异,比如以下嵌套代码:

.parent1, #parent2 {
  .child1 {

  }
}

当它在浏览器中解析时,它实际上变成以下内容:

:is(.parent1, #parent2) .child1 {

}

Sass 将相同的代码编译为:

.parent1 .child1,
#parent2 .child1 {

}

3.2.场景二:& 符号后置

您可能还会遇到一个更微妙的问题。考虑一下:

.parent .child {
  .grandparent & {}
}

原生 CSS 等效项是:

.grandparent :is(.parent .child) {}

这与以下错误排序的 HTML 元素匹配:

<div class="parent">
  <div class="grandparent">
    <div class="child">MATCH</div>
  </div>
</div>

MATCH变得有样式是因为 CSS 解析器执行以下操作:

它会查找所有元素,其所属类的child祖先也parent为DOM 层次结构中的任何点。

找到包含MATCH的元素后,解析器会grandparent在 DOM 层次结构中的任何位置再次检查它是否具有 — 的祖先。它找到一个并相应地设置该元素的样式。

Sass 中的情况并非如此,它编译为:

.grandparent .parent .child {} 上面的 HTML 没有样式化,因为元素类不遵循严格的grandparent、parent、 和child顺序。

3.3.场景三:字符串替换

Sass 使用字符串替换,因此如下所示的声明是有效的,并且与类的任何元素相匹配 .btn-primary

.btn {
  &-primary {
    color: blue;
  }
}

但是原生 CSS 嵌套会忽略&-space选择器。

4.CSS 预处理器还需要吗?

从短期来看,现有的 CSS 预处理器仍然至关重要。Sass 开发团队宣布,他们将支持 .css 文件中的原生 CSS 嵌套,并按原样输出代码。他们将一如既往地编译嵌套 SCSS 代码,以避免破坏现有代码库,但当全球浏览器支持率达到 98% 时,他们将开始输出 :is() 选择器。

我猜想,PostCSS 插件等预处理器目前会扩展嵌套代码,但随着浏览器支持的普及,就会取消这一功能。当然,使用预处理器还有其他很好的理由,比如将部分代码捆绑到一个文件中,以及对代码进行精简。但如果嵌套是你唯一需要的功能,你当然可以考虑在较小的项目中使用原生 CSS。

总结

CSS 嵌套是最有用、最实用的预处理器功能之一。浏览器供应商努力创造了一个与 CSS 非常相似的原生 CSS 版本,以满足网络开发人员的需求。虽然两者之间存在细微差别,而且在使用(过于)复杂的选择器时可能会遇到不寻常的特殊性问题,但很少有代码库需要进行彻底修改。

原生嵌套可能会让你重新考虑是否需要 CSS 预处理器,但它们仍能提供其他好处。Sass 和类似工具仍然是大多数开发者工具包的重要组成部分。

们经常在检测网站加载速度的过程中,遇到了以下问题:从样式表中删除无效规则,并延迟不用于首屏内容的CSS加载,以减少网络活动消耗的不必要字节。

尽管看起来CSS文件的大小只有几KB甚至没有1 MB,但不要仅仅因为文件大小而感到困惑。所有这些事情加起来可能会使您的网站变慢,因此建议从样式表中删除未使用的CSS和无效规则,使样式表文件更精简,最小化并完善它,以便在速度较慢的连接上更快地加载。速度更快的网站更有可能获得更高的排名,因此,您应该非常非常认真地考虑网站的加载时间。

什么是未使用的CSS规则?

未使用的CSS或“无效规则”不过是未在您的网页上使用的CSS代码。如果删除此代码,它将使CSS文件更精简,更轻便,并在某种程度上帮助缩短页面的加载时间。

让我们举一个例子来理解这一点。

假设您的样式表中包含以下CSS代码

.red_highlight_box {
  padding: 10px;
  background-color: black;
  color: white;
  cursor: pointer;
  max-width: 85%;
  margin: 0 auto;
  border-bottom: 2px solid white;
  //border-radius: 10px;
  font-family: 'Secular One', Arial, Helvetica, sans-serif; 
}

上面的代码用于类名“ red_highlight_box”。您可能不会在网站的主题中使用此类,并且网站上任何现有的页面也不会使用该类。

在这种情况下,上面的代码是未使用的CSS或无效规则或“膨胀代码”。它什么也没做,只是减慢了网站速度,您绝对应该考虑一劳永逸地将其从样式表文件中删除。

请注意

注释掉未使用的CSS与完全删除它是不同的。当您注释掉未使用的CSS代码时,该代码仍然存在,并增加了文件大小。未使用的css清理的目标是减小CSS文件的文件大小,以便更快地加载,呈现在用户浏览器中。因此,不建议注释掉不必要的CSS代码,您应该从CSS文件中永久删除多余的代码。

想象一下,如果您从网站的每个页面调用了5个样式表,并且这些样式表中的每一个都充满了无效规则和代码,而这些规则和代码根本没有在您网站的HTML中使用。如果您使用廉价的模板网站,这是很正常的,因为CSS包含主题“可能”需要的所有内容。HTML模板的开发人员已经考虑了所有可能性,小部件,部分,字体,样式,背景色,因此编写了满足所有可能性的代码。

但实际上,您不会使用所有可能性。实践表明,在CSS文件中使用的所有可能性中,您将使用的可能性不到30%,因此,样式表中会有很多未使用的CSS规则,这将不必要地增加网站页面的加载时间。

使用Unused-CSS.Com从StyleSheets中删除未使用的CSS

有许多工具可用于合并CSS文件,最小化它们或从样式表中删除无效规则。但我强烈建议您使用Unused-Css.Com。实际上,它是我们删除多余CSS代码的唯一工具,而且至今还没有任何差错。我们已经在多个网站上对其进行了测试,并且得到的输出CSS文件从未出错过。

我们也尝试过Purify CSS,但是对于包含许多CSS代码的较大站点,输出的CSS文件是不正确的。一些CSS代码会从输出文件中删除,这些代码正在其他页面上使用。

进行此过程的最佳方法是不要从网站的样式表文件中手动删除未使用的CSS。因为,当您手动进行操作时,总是存在人为错误的可能性。手动检查每个类并查找在哪个页面或场景中使用它们也是非常费力。因此,我们就不要考虑手动删除多余的CSS代码了。

您需要一个在线工具,该工具将对整个网站进行爬网,考虑所有页面并仅提取每个页面中使用的CSS。一旦在整个站点的每个页面上提取了可用的CSS,它将对其进行组合,并为您提供最终的输出文件,即干净的CSS-避免肿的代码或无效规则。

这是您的操作方式。

  1. 在Unused-css.com上注册一个免费帐户。这项免费计划可让您仅清洁一个网站(最多100页)的CSS。
  2. 添加您的网站并设置扫描。他们的抓取工具将抓取您的整个网站和所有页面,因此请确保您的robots.txt或其他脚本不会以任何方式阻止抓取工具。
  3. 当他们的抓取工具完成对所有网站的抓取并优化了整个网站中使用的所有CSS文件后,您很快就会收到一封电子邮件。不用担心,所有这些文件都不会合并在一起,您可以根据自己的需要有选择地下载每个优化的CSS文件,然后决定将其与另一个文件合并。
  4. 登录到您的未使用CSS帐户,选择项目,您将在左侧栏中看到所有CSS文件。首先,在左侧边栏中,选择网站主题或HTML模板正在使用的CSS文件(该文件应位于左侧边栏底部的下方)。接下来,单击“下载CSS”,您将获得缩小的CSS文件,其中没有肿的代码或未使用的代码。
  5. 将此新的CSS文件上传到您网站的主题目录中。请勿删除原始CSS文件,而是上传此新CSS文件,然后从您的网站头部调用新的优化CSS文件。完成后,转到Google页面速度分析,然后再次运行诊断。在您的网站上使用随机页面,因为Unused-CSS.com扫描了整个网站并将所有正在使用的CSS类合并到一个文件中,所以完全没问题。您应该会看到警告– 删除未使用的CSS并从样式表中删除无效规则,这些内容不再显示在Google页面速度分析的“机会”部分下。

当然,您不必使用付费工具即可完成此操作。您可以使用Chrome开发人员工具并手动完成操作,也可以推迟未使用的CSS。

如果我的网站的主题更新怎么办?我是否必须再次删除未使用的CSS?

是的,如果您使用免费的模板,则必须一次又一次地执行此操作。这是因为当您的主题收到新的更新时,它将覆盖您的style.css文件中的代码。

这样,当主题有新更新时,它将不会覆盖没有膨胀代码的优化CSS文件。

我们的建议是不要使用免费的模板。推荐您使用定制网站,这样您就知道所有内容如何适合以及从哪个部分调用了哪些文件。

题描述:

web应用中,经常需要在图片上添加相应的链接,而且相对于传统的文字链接的方式,不仅美观,而且有更大的可点击区域。例如,京东网图书页面的一个简单布局:

 
  1. <a title="毕业歌" href="http://item.jd.com/11366857.html" target="_blank">
  2. <img width="130" height="130" src="http://www.hmttv.cn/uploadfile/2024/0808/20240808043620333.jpg">
  3. </a>

这种情况是几乎没有任何问题的,但是,如果在img标签之外,a标签之内再添加一层元素(如div或者p标签),在IE6,7下虽然能够正常显示链接,但是却无法点击。即使你给a标签的样式加上

cursor:pointer;设置相应的高度和宽度,设置为display:block,依然是无法点击的。如下所示的布局:

 
  1. <a href="http://blog.csdn.net/ohmygirl?viewmode=contents" target="_blank">
  2. <div class="a">
  3. <img src="test.jpg"/>
  4. </div>
  5. <div class="b">
  6. <img src="test.jpg"/>
  7. </div>
  8. </a>

对应的样式为:

 
  1. .a,.b{
  2. width:140px;
  3. height:140px;
  4. float:left;
  5. margin:10px 0 10px 10px;
  6. display:inline;
  7. }

在IE6 ,7下,右键点击可以显示“在新标签中打开链接”等选项,证明不是a链接无效。而且在两图片的margin的空白区域,是可以点击的,只有图片的区域却无法点击(也就是图片区域的连接失效了)

这是由于,在IE6,7中,由于触发了img标签的父元素的hasLayout属性,从而使得父元素(这里是div元素)自己的布局掩盖了a标签的链接。这一点,我们可以通过禁用img父元素的样式来证明:

 
  1. <a href="http://blog.csdn.net/ohmygirl?viewmode=contents" target="_blank">
  2. <div>
  3. <img src="test.jpg"/>
  4. </div>
  5. <div>
  6. <img src="test.jpg"/>
  7. </div>
  8. </a>

这种布局下:图片的区域是可以点击的。

具有hasLayout属性的标签(默认haslayout值为true):

<html> <body> <table> <tr> <td> <td> <img> <hr> <input> <button> <select> <textarea> <fieldset> <legend><iframe> <embed> <object> <applet> <marquee>

能够触发hasLayout的css属性(样式有):

display:inline-block;

float:left|right;

width(height):除了auto之外的值。

position:absolute;

zoom:1 显式开启hasLayout。

Ie7下触发hasLayout的样式属性还有:

min-width,min-height等。

关于haslayout的更多细节,也可以参考这篇文章:

http://www.jb51.net/web/77542.html

知道了原因,针对以上的问题,解决的方案有:

1.去掉img标签的元div元素,将父元素的样式迁移到img标签上,布局如下:

 
  1. <a href="http://blog.csdn.net/ohmygirl?viewmode=contents" target="_blank">
  2. <img class="a" src="test.jpg"/>
  3. <img class="b" src="test.jpg"/>
  4. </a>

2.保留div元素,但是去掉触发haslayout的width和height属性(实际上这样只是保留了空架子)。如下

 
  1. <a href="http://blog.csdn.net/ohmygirl?viewmode=contents" target="_blank">
  2. <div>
  3. <img class="a" src="test.jpg"/>
  4. </div>
  5. <div>
  6. <img class="b" src="test.jpg"/>
  7. </div>
  8. </a>

完整的测试代码如下:

 
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh" lang="zh">
  3. <head>
  4. <title>关于 hasLayout</title>
  5. <style type="text/css">
  6. html,body,div,p,a,img{
  7. margin:0;
  8. border:0;
  9. }
  10. .wrapper{
  11. width:312px;
  12. text-align:center;
  13. margin:0 auto;
  14. margin-top:100px;
  15. border:1px solid red;
  16. }
  17. .a,.b{
  18. width:140px;
  19. height:140px;
  20. float:left;
  21. margin:10px 0 10px 10px;
  22. display:inline;
  23. }
  24. </style>
  25. </head>
  26. <body>
  27. <div class="wrapper">
  28. <a href="http://blog.csdn.net/ohmygirl?viewmode=contents" target="_blank">
  29. <div class="a">
  30. <img src="test.jpg"/>
  31. </div>
  32. <div class="b">
  33. <img src="test.jpg"/>
  34. </div>
  35. </a>
  36. </div>
  37. </body>
  38. </html>

请在IE6,7下测试。