Responsive Advertisement

SASS/SCSS #4: Parent selector - Advanced @mixin - @include

 

Welcome back to the series of articles on SASS/SCSS. If you love this topic, here is the link for you to follow other articles. Series about SASS/SCSS.

Table of contents:

  • Parent selector
  • Parent selector combined with BEM
  • Advanced @mixin - @include

Let’s go to the content!

Parent selector

If you are familiar with SASS/SCSS then you are no stranger to nested in SASS/SCSS. In this section we discuss the more advanced parts of nested. This is the usual way of writing from parent components to child components.

// index.scss

.card {

    background-color: #232323;

    .card__header {

        padding: 1rem;

    }

}

 

And the result for the above code will be:

/* index.css */

.card {

  background-color: #232323;

}

.card .card__header {

  padding: 1rem;

}

 

These are the basics. However, have you noticed that when you select child selectors with the same name as the parent selector, you need to repeat the name. In the example above we have the parent selector as “card” and the child selector as “card__header”. Both coincide as "card". Now we must have a way to minimize this duplication. Let's see how the above problem will be solved:

// index.scss

.card {

    background-color: #232323;

    position: relative;

    &::before {

        content: '';

        position: absolute;

        width: 20px;

        height: 10px;

    }

}

 

And the result will be:

/* index.css */

.card {

  background-color: #232323;

  position: relative;

}

.card::before {

  content: "";

  position: absolute;

  width: 20px;

  height: 10px;

}

 

Do you see what's happening? We have an "&" added. The "&" sign represents the currently selected selector. In this case is the class "card". We solved the repeat selector problem in SASS/SCSS. Let's continue to go through the other sections to see what more problems the selector can solve.

// index.scss

.card {

    background-color: #232323;

    position: relative;

    :not(&) {

        display: none;

    }

    &:nth-child(2) {

        background-color: red;

    }

    &__header {

        padding: 1rem;

    }

}

         

And the result we get will be:

/* index.css */

.card {

  background-color: #232323;

  position: relative;

}

:not(.card) {

  display: none;

}

.card:nth-child(2) {

  background-color: red;

}

.card__header {

  padding: 1rem;

}

 

True to theory, the "&" sign replaces the nearest selector containing it, this is a shorthand way of writing.

Note, if you combine "&selector" will give a different result, if you combine "& selector" will give a different result.

// index.scss

.btn {

    &:hover {

        background-color: green;

    }

 

    & .header {

        padding: 1rem;

    }

}

 

The result for the above difference will be:

/* index.css */

.btn:hover {

  background-color: green;

}

.btn .header {

  padding: 1rem;

}

 

 

The result will coincide with the way you combine “&” with the selector. Depending on each specific case, you should use the "&" sign appropriately.

Parent selector combined with BEM

First, we talk about what is the class naming standard according to the BEM standard? This is a naming rule of the form main__component—modifier. “Main” is the main component that covers everything inside. We can get as card, navigation, notification. "Component" will be the child components in the main part, can be header, body, title, description, ... To connect between the main part and the child, we use two "__" signs. “Modifier” is the different state of each component, for example, we have a success message, a failure message, … To add a modifier, we will use “—” oil to combine.

We've briefly gone over the BEM standard in class naming. We will combine the BEM standard and the parent selector to create the fastest and most efficient code.

// index.scss

.card {

    box-shadow: 0px 8px 8px 1px rgba(0, 0, 0, 0.1);

    &__header {

        width: 100%;

    }

    &__body {

        padding: 1rem;

    }

    &--success {

        background-color: green;

    }

    &--warning {

        background-color: yellow;

    }

}

 

Let's see the results we get:

/* index.css */

.card {

  box-shadow: 0px 8px 8px 1px rgba(0, 0, 0, 0.1);

}

.card__header {

  width: 100%;

}

.card__body {

  padding: 1rem;

}

.card--success {

  background-color: green;

}

.card--warning {

  background-color: yellow;

}

 

You see that if we know the parent selector we can name it according to the BEM criteria extremely simply and quickly.

Another note is that “&” will represent the current selector. Let's see the following example:

// index.scss

.btn {

    & .header {

        padding: 1rem;

        & .title {

            font-size: 1.5rem;

        }

    }

}

 

And the result will be:

/* index.css */

.btn .header {

  padding: 1rem;

}

.btn .header .title {

  font-size: 1.5rem;

}

 

The ampersand "&" inserted in any scope will represent the selector in that scope. As the example above we see that the same sign "&", but the results are completely different. Depending on the scope, the sign “&” is standing.

Advanced @mixin - @include

In part one of my SASS/SCSS series I covered the basic usage of @mixin - @include. Includes using no arguments, having arguments, and setting arguments to default value. In this article we go through another way to use arguments in @mixin - @include. Let's come to the following example:

// index.scss

@mixin btn($arguments...) {

    @each $arg in $arguments {

        @debug $arg

    }

};

 

.btn {

    @include btn(border, width, height)

// scss\index.scss:4 Debug: border

// scss\index.scss:4 Debug: width

// scss\index.scss:4 Debug: height

}

 

In the above problem we are dealing with a case where when we don't know the exact number of arguments we receive for a @mixin we can use $variable-name…. This means we can take as many arguments as we want. In the above wallet in class “.btn” we get three arguments and we print it in terminal via @debug. And we see that the results we get are the same as the arguments we passed in.

However, for receiving many arguments we still find it not enough, we only get one value, so we cannot solve a specific problem. Receiving multiple arguments at @mixin and passing arguments at @include makes for a great combination.

// index.scss

@use 'sass:meta';

@mixin btn($arguments...) {

    @each $key, $val in meta.keywords($arguments) {

        @debug $key - $val        

    }

};

 

@include btn(

    $border: 20px,

    $width: 20px,

    $height: 20px

)

// scss\index.scss:5 Debug: border-20px

// scss\index.scss:5 Debug: width-20px

// scss\index.scss:5 Debug: height-20px

 

As you can see above, we have made some changes in receiving arguments in @mixin and @include. For @include we no longer use merely the value passed. We have $key: value. We use @use to use the library as “meta” in SASS.

Note that if we pass arguments of the type $key: value without using "meta" we will not be able to get the values ​​of the type $key, $value in that argument.

Next we use “meta.keywords(arguments)” to get the key, value pair. In the end we get the results we want.

Going through the above problem, we know how to use multiple arguments in @mixin - include. So let's apply the knowledge we have just learned to real problems to solve the problem.

We will create buttons with different modifiers like success, warning, danger, info. Characteristic for each button will be a different color. The properties that make up a button will be the same. And we only use one @mixin and get multiple arguments to solve this problem. Let's do it step by step.

First, to handle receiving multiple arguments and separate them into key and value counters, we must use "sass:meta", to use meta.keywords. Next we will get key, value pairs to use to create modifers for buttons.

// index.scss

@use 'sass:meta';

@mixin btn($arguments...) {

    @each $key, $value in meta.keywords($arguments){

        .btn--#{$key}{

            background-color: #{value};

        }

    }

}

 

Now we will build common properties for a button and use @include to create modifiers for the button.

// index.scss

.btn {

    padding: 0.5em 1em;

    font-size: 0.75rem;

    border-radius: 20px;

    @include btn(

        $warning: yellow,

        $success: green,

        $danger: red,

        $info: blue

    )

}

 

Now let's see what the result will be:

/* index.css */

.btn {

  padding: 0.5em 1em;

  font-size: 0.75rem;

  border-radius: 20px;

}

.btn .btn--warning {

  background-color: value;

}

.btn .btn--success {

  background-color: value;

}

.btn .btn--danger {

  background-color: value;

}

.btn .btn--info {

  background-color: value;

}

 

Awesome! We have created a class “btn” that shares the buttons and has a modifier for each type of button. This is a small application problem in practice. You can apply these multiple arguments to solve more problems.

Conclusion

We have just learned and applied “&” to make the selector problem easier. At the same time, we also combine “&” with the BEM standard. I also went through advanced @mixin - @include.

If you have any ideas, feel free to comment below. Thank you for joining with me. Having a good day!


Đăng nhận xét

0 Nhận xét