Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SASS: Check element type inside element type

Tags:

html

css

sass

Is it possible to check for element types inside element types? This looks like a common question to me, but I could not find this on Stack Overflow.

For example:

h1, h2, h3, h4 {
    margin-top: 20px;
    margin-bottom: 20px;
    color: red;

    & h2 {
        margin-top: 0;
    }
}

I know the same thing works with classes like:

.test,
.test-two {
     color: red;

     &.test {
         color: blue;
     }
}

In this case, I could overwrite .test within the parent classes. The same thing just won't work with element types in the example above.

PS: I am not trying to get this HTML fixed (it is just an example), but find a way to nest element types.

Thank you in advance!

like image 757
Stacker Avatar asked Nov 08 '22 04:11

Stacker


1 Answers

What you've written here isn't a great way to go about what it sounds like you are trying to do. In your first snippet here:

.test,
.test-two {
     /* ... Other shared styles ... */
     color: red;

     &.test {
         color: blue;
     }
}

It sounds like what you are trying to do with this is to overwrite the test class' color after it was set with some of the other properties it shares with a different selector. Consider, however, that what you have written will compile to:

.test,
.test-two {
    color: red;
}

.test.test,
.test-two.test {
    color: blue;
}

So, now you have a compound class selector with two of the same classes on it, which is unnecessary. Then there is another selector here that most likely you do not even need. You want to avoid adding needless specificity and outputting ineffective or useless code. In this example, the CSS that you should want to see after compilation is this:

.test,
.test-two {
    /* ... Other shared styles ... */
    color: red;
}

.test {
    color: blue;
}

Nice low specificity selectors take take advantage of selector precedence in the cascade. In SCSS, you would just write the exact same thing. There is really no benefit whatsoever to trying to phrase this as a nested selector when doing so will either produce worse code, or be unnecessarily convoluted. However, if there is some reason that you feel that section needs nesting, an easy way to do it would be to use @at-root. Like so:

.test,
.test-two {
    color: red;

    @at-root {
        .test {
            color: blue;
        }
    }
}

You can go to the documentation for @at-root if you'd like to learn more about that.

That brings me to the substance of your question. Again, the way you want to overwrite styles primarily is to use selector precedence, not to start engaging in ever increasing levels of specificity, which over complicates and bulks the code, leads to overuse of !important, and starts a specificity selector war that results in needlessly long selectors that have poor performance.

So in this snippet here:

h1, h2, h3, h4 {
    margin-top: 20px;
    margin-bottom: 20px;
    color: red;

    & h2 {
        margin-top: 0;
    }
}

If all you are trying to do is overwrite the h2 style, then the CSS you should want to see post-compile is this:

h1, h2, h3, h4 {
    margin-top: 20px;
    margin-bottom: 20px;
    color: red;
}

h2 {
    margin-top: 0;
}

However, what you are currently doing will look like this post-compile:

h1, h2, h3, h4 {
    margin-top: 20px;
    margin-bottom: 20px;
    color: red;
}

h1 h2,
h2 h2,
h3 h2,
h4 h2 {
    margin-top: 0;
}

Just like in the first example, there is probably not a good reason to nest these selectors like this. Either do this (same as the desired CSS output):

h1, h2, h3, h4 {
    margin-top: 20px;
    margin-bottom: 20px;
    color: red;
}

h2 {
    margin-top: 0;
}

or if you insist on using nesting, you could use @at-root just like I did in the first example:

h1, h2, h3, h4 {
    margin-top: 20px;
    margin-bottom: 20px;
    color: red;
    
    @at-root {
        h2 {
            margin-top: 0;
        }
    }
}

Hopefully this is helpful. If I am off-base on what your desired goal is I would be happy to revise my answer if you provide more details.

like image 63
Stephen M Irving Avatar answered Nov 15 '22 06:11

Stephen M Irving