Home >Web Front-end >CSS Tutorial >Structuring CSS Class Selectors with Sass

Structuring CSS Class Selectors with Sass

Joseph Gordon-Levitt
Joseph Gordon-LevittOriginal
2025-02-24 10:01:09672browse

Structuring CSS Class Selectors with Sass

Key Points

  • CSS naming conventions such as BEM and SMACSS rely heavily on CSS class selectors, and using Sass can make writing these selectors more modular and reusable.
  • Native selector nesting in Sass allows the creation of subclass names from original block names at the root level of the document, simplifying code and reducing the need for additional helpers like variables or mixin.
  • BEM mixin provides a friendly API that is easy to understand once you understand how BEM works, although the logic is hidden behind mixin, which may make generating new selectors and classes less obvious.
  • Humanified-BEM mixin is designed to improve code readability by hiding the Block-Element-Modifier terminology, but this may involve too much abstraction for some developers.

There are many CSS naming conventions. You may already know about BEM and SMACSS (the latter is more than just naming conventions). And OOCSS, which is more like a complete methodology. They all rely heavily on CSS class selectors because they are highly reusable.

Using Sass can help to write these selectors in a more modular way. With selector nesting and mixin, we can come up with fancy crazy solutions to build the required API. In this article, I will (re) introduce several of these methods, listing the pros and cons of each one I think.

Native selector nesting

Being able to nest selectors without having to repeat the original block name has been a long-term requirement in Sass. In Sass 3.3, this feature was finally introduced. During beta, a very strange syntax was first used, and later changed to a better syntax when the stable version went live. Natalie Weizenbaum explains the reasons behind the changes in this post.

Basically, the reference selector (&) can be used as part of the subclass name to create another class with the first class name from the root level of the document (which means @at-root is not required here) name.

This feature was quickly overused to write BEM selectors, such as very popular media objects:
<code>.foo {
  // .foo 的样式

  &-bar {
    // .foo-bar 的样式
  }
}</code>

The previous code will be compiled as:

<code>.media {
  // .media 块的样式

  &__img {
    // .media__image 元素的样式

    &--full {
      // .media__image--full 修改后的元素的样式
    }
  }

  &--new {
    // .media--new 修饰符的样式
  }
}</code>

Pros

<code>.media {}
.media__img {}
.media__img--full {}
.media--new {}</code>

It relies on native functions and does not require additional helpers such as variables or mixins.

    Once you understand how the reference selector (&) works, it's easy to master overall.
  • Disadvantages

It exposes the & syntax, which can be slightly confusing and even frightening if it is not familiar to developers who are familiar with Sass.

    Nesting is usually not printed in the root directory unless @at-root is used, which can be disturbing.
  • BEM mixin

Because the syntax generated by the class during the beta of Sass 3.3 was very ugly (@at-root #{&}__element), we soon saw some mixins here and there to hide the pain and provide a more friendly API .

<code>.foo {
  // .foo 的样式

  &-bar {
    // .foo-bar 的样式
  }
}</code>

You can use them like this:

<code>.media {
  // .media 块的样式

  &__img {
    // .media__image 元素的样式

    &--full {
      // .media__image--full 修改后的元素的样式
    }
  }

  &--new {
    // .media--new 修饰符的样式
  }
}</code>

We can also create a block mixin the same way, but it won't be as useful as a block, because the block is just a class name. Let's keep it simple. Although for some, modifiers and elements seem too long, we see some e and m in full bloom.

<code>.media {}
.media__img {}
.media__img--full {}
.media--new {}</code>

Pros

  • This version provides a friendly API that is easy to understand once you understand how BEM works.

Disadvantages

  • Logistics are hidden behind mixin, and generating new selectors and classes is not that obvious unless you know exactly what is going on.
  • Single letter mixins may not be a good idea because they make it difficult to understand what mixins are used for. b and m can represent a lot of things.

Humanified-BEM mixin

Recently, I read a new BEM-like approach by Anders Schmidt Hansen. The idea is to hide the Block-Element-Modifier term behind common words that make sense when reading aloud.

<code>@mixin element($element) {
  &__#{$element} {
    @content;
  }
}

@mixin modifier($modifier) {
  &--#{$modifier} {
    @content;
  }
}</code>

In this case, the point is to hide the code behind a well-named mixin so that the code looks like it is telling a story, so the new mixin is actually useful.

<code>.media {
  // .media 块的样式

  @include element("image") {
    // .media__image 元素的样式

    @include modifier("full") {
      // .media__image--full 修改后的元素的样式
    }
  }

  @include modifier("new") {
    // .media--new 修饰符的样式
  }
}</code>

Anders further uses is(..) and holds(..) mixin. The whole idea reminds me of my when-inside(..) mixin, which hides & behind a user-friendly mixin when the element styles according to its superior context.

<code>.media {
  // .media 块的样式

  @include e("image") {
    // .media__image 元素的样式

    @include m("full") {
      // .media__image--full 修改后的元素的样式
    }
  }

  @include m("new") {
    // .media--new 修饰符的样式
  }
}</code>

Pros

  • This approach helps improve the readability of the code, just like we started naming our state classes using the leading is- (promoted by SMACSS).
  • Still stick to a specific approach (BEM in this case), but makes it easier for developers to use.

Disadvantages

  • More mixins, more auxiliary tools, and more things to learn in order to obtain a more stable learning curve. Not everyone likes to deal with a lot of mixins to write simple things like CSS selectors.
  • This may be too abstract for some people; not everyone likes to read code like they do in English. It depends on the situation.

Final Thoughts

Remember that using any of these techniques will prevent the selector code base from being searchable because the selector does not actually exist before being generated by Sass. Adding comments before selectors can solve this problem, but why not just write the selectors right from the beginning?

If you care about having a searchable code base, please do not use the new Sass feature to BEM all selectors (.b { &__e { } }).

— Kaelig (@kaelig) March 12, 2014

Anyway, friends, here are the most popular ways I know to write CSS selectors in Sass, between me and you, I don't like them. And it's not just because of the search problem, it's not a big problem for me.

I can see the problem they are trying to solve, but sometimes simplicity outweighs DRY. Repeating the root selector is not a big deal, it not only makes the code easier to read, because it is less nested, but also closer to CSS.

Sometimes simpler than DRY.

— Hugo Giraudel (@HugoGiraudel) May 19, 2015

FAQs about using SASS structured CSS class selectors

What is the meaning of using SASS structured CSS class selectors?

Using SASS structured CSS class selectors is essential for maintaining a clean, ordered and efficient stylesheet. SASS (on behalf of Syntacly Awesome Stylesheets) is a CSS preprocessor that allows developers to use variables, nested rules, mixins, and functions to make CSS more dynamic and reusable. With a structured class selector, you can create style hierarchies, making it easier to understand the relationship between different elements and their styles. This can greatly improve the maintainability and scalability of CSS code.

How to use wildcard selector in SASS?

Wildcard selector, also known as a universal selector, can be used in SASS to select any element that matches a specific pattern. For example, you can use the wildcard selector "*" to select all elements. However, SASS does not directly support wildcard class names. If you want to select an element whose class name starts with a specific string, you need to use a workaround, such as using an attribute selector. For example, you can use the selector [class^="prefix-"] to select all elements whose class names start with "prefix-".

Can I use the @extend directive with the class selector in SASS?

Yes, the @extend directive can be used in SASS with class selectors. The @extend directive allows one selector to inherit the style of another selector. This is useful for reducing redundancy in CSS code. For example, if you have two classes that share many of the same styles, you can define those styles in one class and then use the @extend directive to apply these styles to another class.

How to organize CSS code more efficiently using SASS?

SASS provides some features that can help you organize your CSS code more effectively. One of the features is nesting, which allows you to nest CSS selectors in other selectors, reflecting the HTML structure. This can make your CSS code easier to read and maintain. Another feature is variables, which allows you to define reusable values. This is useful for maintaining consistency in styles such as colors, fonts, and spacing.

What are the best practices for using SASS structured CSS class selectors?

There are several best practices to use SASS structured CSS class selectors. One best practice is to make the selector as specific as possible. This can help prevent the style from accidentally affecting other elements. Another best practice is to use meaningful class names to describe the purpose or function of an element. This can make your CSS code easier to read and maintain. Additionally, it is best to use a consistent naming convention for your class, such as BEM (block, element, modifier) ​​to make it easier to understand the relationship between different classes.

How to reuse CSS code using mixin in SASS?

mixin in SASS is a way to define styles that can be reused throughout the stylesheet. mixin is defined using the @mixin directive followed by a name and a CSS code block. You can then include mixin in any selector using the @include directive (submitted by the name of the mixin). This is useful for reducing redundancy in CSS code and making it easier to maintain.

Can I generate CSS code using functions in SASS?

Yes, SASS supports functions and can be used to generate CSS code. Functions in SASS are defined using the @function directive followed by a name and code block. The function can accept parameters and return a value that can be used in your CSS code. This is useful for creating complex styles that depend on specific conditions or calculations.

How to organize CSS code using the @import directive in SASS?

The @import directive in SASS can be used to import other SASS files into SASS files. This is useful for organizing CSS code into separate files, each focusing on a specific part of the website style. For example, you can create separate SASS files for header styles, footer styles, and main content styles, and then import them all into the main SASS file.

How to use the & operator to reference the parent selector in SASS?

The & operator in SASS can be used to reference the parent selector in nested rules. This is very useful for creating pseudo-classes or pseudo-element selectors. For example, if you have a nested rule for a:hover inside a .link rule, you can use the & operator to create a selector .link:hover.

How to create responsive styles using the @media directive in SASS?

The @media directive in SASS can be used to create media queries, allowing you to apply different styles based on the characteristics of the device that is viewing the page, such as its width or height. This is very useful for creating responsive designs that fit different screen sizes. You can use the @media directive in the selector to apply styles only if the media query criteria are met.

The above is the detailed content of Structuring CSS Class Selectors with Sass. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn