Make LESS remove useless IDs when compiling

社会主义新天地 提交于 2019-12-13 02:00:14

问题


One feature I really love with LESS is nested rules. It makes the stylesheet much cleaner that way and you can find an element very quickly.

I was wondering if there's an option when compiling to optimize selectors. For example...

#global {
  /* Styles here maybe */

  .container {
    /* Styles here maybe */

    #sidebar {
      /* Styles here maybe */

      .title {
        font-weight: bold;
      }
    }
  }
}

will be compiled to #global .container #sidebar .title { font-weight: bold; }.

But the first two selectors are useless, since #sidebar should be unique in my page.

Is there a way to ask LESS to compile this to #sidebar .title { font-weight: bold; } instead?


回答1:


Your assumption is wrong that multiple IDs in CSS are redundant. Imagine, as an example, a site where the CMS generates the page type into the output, like that it's the contact page:

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

According to your logic, the following piece of CSS would be a candidate for 'optimization':

#contact #content {
   background:red;
}

Now however, your home page has <body id="home"> of course in this imaginary CMS. And suddenly the content of your homepage has a red background because you decided to erroneously optimize that #contact selector out of the CSS, while it most certainly shouldn't have a red background according to this rule.

So no, LESS cannot do this because it would break code. If you don't want the selectors, don't use them and don't put them in your code.




回答2:


Other answers, including the accepted one, have explained convincingly why LESS cannot simplify your nested selectors in the way you want.

Actually, SASS has the ability to do this:

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

The @at-root directive essentially ignores all the higher nesting selectors. I don't know if LESS has something similar. The above compiles into simply

#sidebar {
    .title {
        font-weight: bold;

But there is a deeper issue here, starting with the fact that you "love" nested rules in LESS. Stop loving them quite so much. I don't know about you, but most people love nested rules because they think it's cool to exactly mimic the hierarchical structure of their HTML. The SASS docs even claim this as a benefit:

Sass will let you nest your CSS selectors in a way that follows the same visual hierarchy of your HTML.

So people with HTML such as

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

write LESS like

.foo {
    ul {
        li.item {

This is a horrible, horrible idea, It makes the structure of CSS completely dependent on the structure of the HTML. If you change one nesting level in the HTML, your CSS breaks. Often this approach is combined with a lot of rules defined against tag names such as ul instead of class names, which aggravates the dependency, so changing the ul to ol in the HTML breaks the rules again. Or it's combined with rules based on Bootstrap classes such as col-md-6, so if you ever change that to col-md-4 things break again.

CSS rules should be orthogonal to the HTML. They represent a different dimension. They represent styling concepts which are applied selectively throughout and across the HTML.

I am guessing that you wrote

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

because you are adopting this mistaken idea of mirroring the HTML structure in your LESS. Then, you notice that this compiles down to having selectors which contain multiple IDs, which you imagine must be inefficient (although, actually, the degree of inefficiency is minimal). You yourself are writing extraneous nesting levels in your LESS, then complaining that they may be slowing down performance!

Worse, you've hard-wired assumptions about the HTML structure into your CSS. It's of no consequence that the sidebar happens to fall inside a .container which is inside a global element. So don't write them. Perhaps at some point you decide to change the container class to container-fluid. Boom, instantly your CSS breaks. What is the point of conditionalizing the fact that the title should be bold on it being contained with a container class, which in any case is a layout-related class that has (or should have) nothing to do with styling? If you're going to duplicate your HTML structure in your CSS using preprocessor nesting, just go back to writing inline styles. At least that way you'll only have one file to change when you change your HTML around.

When designing CSS, you should think just as hard about the design of the rules as you do about the design of classes and methods when writing JS. In this case, you need to ask yourself, "What characterizes the situation where I want some title to be bold? What drives that? What is the nature of boldness? What am I indicating by boldness? What is the semantic notion indicated by boldness?"

Let's say that you want all titles to be bold. Then you simply say that:

.title { font-weight: bold }

Let's say that you want a title to be bold only when it's in the sidebar. Then you simply say that:

#sidebar .title { font-weight: bold; }

My suggestion here is to go cold turkey. Stop using nesting during a withdrawal period. Write rules with the minimum number of selector components. Refactor your classes to have semantic names (such as title-emphasis). Once you're "sober", you can go back to cautiously using LESS's nesting capability when it is useful, such as perhaps for hover:

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

This is actually useful and saves you from writing #boo twice, and groups the rules in an easy-to-understand way.



来源:https://stackoverflow.com/questions/25937510/make-less-remove-useless-ids-when-compiling

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!