编译时让 LESS 移除无用的 ID

Posted

技术标签:

【中文标题】编译时让 LESS 移除无用的 ID【英文标题】:Make LESS remove useless IDs when compiling 【发布时间】:2014-11-14 06:15:09 【问题描述】:

我真正喜欢 LESS 的一个功能是嵌套规则。这样可以使样式表更加简洁,并且您可以非常快速地找到一个元素。

我想知道在编译优化选择器时是否有一个选项。比如……

#global 
  /* Styles here maybe */

  .container 
    /* Styles here maybe */

    #sidebar 
      /* Styles here maybe */

      .title 
        font-weight: bold;
      
    
  

将编译为#global .container #sidebar .title font-weight: bold;

但是前两个选择器没用,因为#sidebar 在我的页面中应该是唯一的。

有没有办法让 LESS 将其编译为 #sidebar .title font-weight: bold;

【问题讨论】:

你的提议不正确;这样的选择器对于排除外部 ID 不存在但内部 ID 存在的页面或状态很有用。 此外,指定多个 ID 可能会提升规则的优先级,以防还有一个 #myTitle font-weight: 300; 属性(只有一个 ID)。当您与像我这样痴迷于 ID 的开发人员一起工作时,拥有这些会很有用。 LESS 不能假设#sidebar 在给定页面中总是以#global .container #sidebar 出现,即使它在该页面中是唯一的,这就是它不尝试删除前两个选择器的原因默认。但真正的问题是,你为什么要首先将它嵌套在那里?这似乎更像是一个创作错误,而不是预处理器限制。 您还在为几毫秒甚至十分之一秒的 CSS 性能优化而烦恼吗?你还有什么好担心的吗?除了正如其他海报所提到的那样,它背后的某个地方是不可能的、一个坏主意、危险的和语义破坏性的? @SamuelBolduc 别担心,这只是一个错误的假设。我实际上赞成这个问题,因为我非常怀疑你是第一个或最后一个考虑这个问题的人。这个问题有充分的根据,问得也很好,你学到了一些东西。也许其他人也会:) 【参考方案1】:

您的假设是错误的,即 CSS 中的多个 ID 是多余的。想象一下,作为一个例子,CMS 将页面类型生成到输出中的站点,就像它是联系页面一样:

<body id="contact">
  <section id="content">Blah</section>
</body>

根据您的逻辑,以下 CSS 将成为“优化”的候选者:

#contact #content 
   background:red;

但是,现在,您的主页当然有 &lt;body id="home"&gt; 在这个虚构的 CMS 中。突然,你的主页内容变成了红色背景,因为你决定错误地优化 CSS 中的 #contact 选择器,而根据这条规则,它肯定不应该有红色背景。

所以不,LESS 不能这样做,因为它会破坏代码。如果您不想要选择器,请不要使用它们,也不要将它们放入您的代码中。

【讨论】:

如果您需要外部规则集来做其他事情,或者将内部规则集移出。【参考方案2】:

其他答案,包括接受的答案,已经令人信服地解释了为什么 LESS 不能以您想要的方式简化嵌套选择器。

其实SASS有能力做到这一点:

#global 
    .container 
        @at-root #sidebar 
           .title 
               font-weight: bold;

@at-root 指令基本上忽略了所有更高的嵌套选择器。我不知道LESS是否有类似的东西。以上简单编译成

#sidebar 
    .title 
        font-weight: bold;

但这里有一个更深层次的问题,首先是您“喜欢”LESS 中的嵌套规则。别那么爱他们了。我不了解你,但大多数人喜欢嵌套规则,因为他们认为完全模仿 html 的层次结构很酷。 SASS 文档甚至声称这是一种好处:

Sass 将允许您以遵循 HTML 相同视觉层次结构的方式嵌套 CSS 选择器。

所以人们用 HTML 之类的

<div class="foo">
    <ul>
        <li class="item">

少写点喜欢

.foo 
    ul 
        li.item 

这是一个可怕的、可怕的想法,它使 CSS 的结构完全依赖于 HTML 的结构。如果您更改 HTML 中的一个嵌套级别,您的 CSS 就会中断。通常,这种方法与针对标记名称(例如 ul 而不是类名称)定义的许多规则结合使用,这会加剧依赖性,因此将 HTML 中的 ul 更改为 ol 会再次破坏规则。或者它与基于 Bootstrap 类的规则(例如 col-md-6)结合使用,所以如果你将其更改为 col-md-4,事情就会再次中断。

CSS 规则应该与 HTML 正交。它们代表不同的维度。它们代表样式概念,这些概念可选择性地应用在整个 HTML 中。

我猜你写的

#global 
    .container 
        #sidebar 
           .title 
               font-weight: bold;

因为您采用了在 LESS 中镜像 HTML 结构的错误想法。然后,您注意到这编译为包含多个 ID 的选择器,您认为这一定是低效的(尽管实际上,低效程度是最小的)。您自己在 LESS 中编写了无关的嵌套级别,然后抱怨它们可能会降低性能!

更糟糕的是,您将有关 HTML 结构的假设硬连接到 CSS 中。侧边栏恰好落在 .container 内,而 global 元素内则没有任何影响。所以不要写它们。也许在某个时候您决定将container 类更改为container-fluid。繁荣,您的 CSS 立即中断。将标题应该加粗以包含在container 类中这一事实有什么意义,在任何情况下,该类都是与样式无关(或应该与样式无关)的布局相关类?如果您要使用预处理器嵌套在 CSS 中复制 HTML 结构,只需返回编写内联样式即可。至少这样,当您更改 HTML 时,您只需更改一个文件。

在设计 CSS 时,您应该像在编写 JS 时考虑类和方法的设计一样认真考虑规则的设计。在这种情况下,您需要问自己:“我希望某个标题加粗的情况有什么特点?是什么驱动?加粗的本质是什么?我用加粗表示什么?加粗表示的语义概念是什么? ?”

假设您希望所有标题都是粗体。那你就这么说吧:

.title  font-weight: bold 

假设您希望标题仅在侧边栏中为粗体。那你就这么说吧:

#sidebar .title  font-weight: bold; 

我的建议是去冷火鸡。在退出期间停止使用嵌套。使用最少个选择器组件编写规则。重构您的类以具有语义名称(例如title-emphasis)。一旦你“清醒”了,你可以在有用的时候谨慎使用 LESS 的嵌套功能,比如悬停:

#boo 
    color: red;
    &:hover 
        color: blue;
    

这实际上很有用,让您不必写两次#boo,并且以易于理解的方式对规则进行分组。

【讨论】:

以上是关于编译时让 LESS 移除无用的 ID的主要内容,如果未能解决你的问题,请参考以下文章

小程序中实时将less编译成wxss

less入门

Less/Sass编译工具

如何在 Visual Studio 2015(预览版)中保存时编译 .less 文件

less

less