Styling in sass gets even more powerful when using custom selectors that are

Using these mixins makes it easy to work with BEM syntax in sass 3.3.2:

=b($name)
  .#{$name}
    @content

=e($name)
  &__#{$name}
    @content

=m($name)
  &--#{$name}
    @content

+b(menu)
  +e(item)
    color: grey
  +e(item)
    +m(alert)
      color: red

With this setup, we get the desired result:

.menu__item {color: grey;}
.menu__item--alert {color: red;}

However, issues arise when dealing with block level modifiers:

+b(menu)
  +m(theme-1)
    +e(item)
      color: blue

The CSS output is:

.menu--theme-1__item {color: blue;}

But what is actually needed is:

.menu--theme-1 .menu__item {color: blue;}

An attempt was made to determine the context of an element using parent selectors within the mixin, but it did not fully solve the issue.

Update A workaround was discovered by adding a context argument to the element mixin:

=e($name, $context:null)
  @if $context
    &
      +b($context)
        &__#{$name}
          @content
  @else
    &__#{$name}
      @content

Now, the mixin can be called as follows:

+b(menu)
  +m(theme-1)
    +e(item, nav)
      color: blue

This results in:

.menu--theme-1 .menu__item {color: blue;} 

Answer №1

Responding to a question that is 2 years old - a bit of a long shot :) But hopefully it can also be beneficial to someone else.

To make your Element mixin more reliable, you should enhance it by checking if the parent selector has a modifier.

You will need to create two functions:

  • one function to verify if a selector includes a modifier
  • another function to extract the block name from that selector

@function _bem-selector-has-modifier($selector) {
  $selector: _bem-selector-to-string($selector);

  @if str-index($selector, $bem-modifier-separator) or str-index($selector, ':') {
    @return true;
  } @else {
    @return false;
  }
}


@function _bem-get-block-name($selector) {
  $selector: _bem-selector-to-string($selector);
  $modifier-separator: '--';

  $modifier-start: str-index($selector, $modifier-separator) - 1;

  @return str-slice($selector, 0, $modifier-start);
}

Then, you just have to implement this check in your element mixin

$bem-element-separator: '__';

@mixin element($element) {
  $selector: &;

  @if _bem-selector-has-modifier($selector) {
    $block: _bem-get-block-name($selector);

    @at-root {
      #{$selector} {
        .#{$block + '__' + $element} {
          @content;
        }
      }
    }
  } @else {
    @at-root {
      #{$selector +'__' + $element} {
        @content;
      }
    }
  }
}

Therefore, by calling element('item') within a modifier('with-modifier'), you should see a

.block--with-modifier .block__item
selector in your compiled CSS without needing to manually set the context.

The code provided is in SCSS format, but the concept remains consistent with SASS.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a challenge in setting up a tag search bar similar to Stack Overflow's?

First and foremost, I apologize for the awkwardly phrased question. The issue at hand is that when the tags exceed the container size, the search option becomes hidden. My goal is to have the search bar adjust dynamically, moving everything back inside the ...

Capture the beauty of Safari with images displayed in the input file element

I'm facing an issue with the file upload element on my website. Most browsers, like Chrome and FF, display the image name when a file is chosen. However, Safari seems to show a tiny thumbnail instead. My goal is to create a custom upload button that ...

`A dynamically captivating banner featuring animated visuals created with JQuery`

I am currently in the process of designing a banner for the top of my webpage, but I have yet to come across any code that meets all my requirements. To provide clarification, I have attached an illustration showcasing what I am aiming to achieve. 1) The ...

Struggling to properly position my dropdown menu without causing the div content to shift downward

<div id="header"> <a href="#" id="logo"></a> </div> <div id="nav_cont"> <ul id="nav"> <li id="main_btn"><a class="mainlink" href="#">Parent 01</a></li> <li id="communities_btn">< ...

Top solution for preventing text selection and image downloading exclusively on mobile devices

My plan is to use the following code to accomplish a specific goal: -webkit-touch-callout:none; -webkit-user-select:none; -khtml-user-select:none; -moz-user-select:none; -ms-user-select:none; user-select:none; -webkit-tap-highlight-color:rgba(0,0,0,0); I& ...

Creating a responsive layout with two nested div elements inside a parent div, all styled

I'm currently facing an issue with using padding in my CSS to make the two divs inside a parent div responsive at 50% each. However, when combined, they exceed 100%. I suspect this is due to the padding, but I'm unsure how to resolve it. .column ...

Differences in rendering with Google Chrome when zooming in or out

After creating some code, I observed a peculiar issue. At 500% zoom, the DOWNLOAD button aligns perfectly with the left wall without any gap. However, upon reducing the zoom to 250%, a green background segment becomes visible. To witness this anomaly, refe ...

`How to perfectly place multiple text blocks and images using CSS`

Check out this screenshot to see the issue I'm facing: Here is the HTML code: <div class="parent_process"> <div class="first_process"><img src="images/exprimer-besoin-telephonie.png"/><span style="width:18%">You fi ...

What is the best way to maintain the position of components (such as a Card component) when one is expanded in a Material-UI and ReactJS project

Currently, I am working with an expandable Card component from Material-UI and using flex for aligning the components. However, when one card expands, it affects the positioning of the other components in the row: https://i.stack.imgur.com/vGxBU.png What ...

Change the background color according to the user's input text

I want to create a text box where users can input color keywords like blue, lime, or black. When they click submit, I want the background color of the page to change accordingly. This is what I have so far: <label for="color">Color: </label> ...

Assessing the performance of YUi and BackBone

As I embark on a new project, one of the crucial decisions to make is regarding the architecture. Currently, I am contemplating the selection of front-end components. I plan to utilize HTML5, CSS3, and Javascript for this purpose. When it comes to choos ...

What is the best way to use JavaScript to conceal a section of a form div?

After receiving some code from a certain platform and implementing it to hide part of my form div element, I noticed that the element hides and unhides quickly when running in a browser. This rapid hiding and showing behavior occurs when clicking on the bu ...

Implement CSS to globally style material.angular's mat-card by customizing the background color

Looking for a way to globally change the background of mat-card on material.angular.io. I attempted adding the following code snippet to styles.css with no success. mat-card { background-color: purple; } ...

Warnings are appearing after compiling assets

When I run the command npm run prod to compile assets, I encounter the following message: WARNING Compiled with 2 warnings warning in ./resources/sass/app.scss Module Warning (from ./node_modules/postcss-loader/src/index.js): Warning (1973:3) Error in ...

Adjust the width of the column to only contain fixed content and not span the entire page

Check out my solution on Plunkr to see the issue I'm facing: Plunkr I'm dealing with a layout that includes a menu on the left and page contents on the right. My goal is to have the menu fixed in place so that it doesn't move when the page ...

Modify the Div background color by accessing the HEX value saved in a JSON file

(I made a change to my code and removed the br tag from info2) Currently, I have successfully implemented a feature using jQuery that reads color names and hex values from a JSON file, populates them in a drop-down select menu (which is working fine). Now ...

What makes text-decoration a crucial element of the foreground design?

<span>Educating children on unlocking their creative and intellectual potential through the world of Computer Science.</span> Here is the HTML code provided above along with the corresponding CSS: span { text-decoration: underline; color: red ...

You are unable to move the image to the top of the screen after zooming it with CSS

I implemented an image viewer component with interactive buttons for rotating, zooming in, and zooming out. Upon clicking a button, CSS transform is applied to the image. However, I encountered an issue where, when zooming the image, it cannot be scrolled ...

Displaying various charts in a single view without the need for scrolling in HTML

How can I display the first chart larger and all subsequent charts together in one window without requiring scrolling? This will eventually be viewed on a larger screen where everything will fit perfectly. Any recommendations on how to achieve this? Here ...

The div is set to a position of absolute, causing the overflow-y property to be set to auto. As a

I am facing an issue with a div that has absolute positioning nested inside other divs. If you take a look at the code snippet below from http://jsfiddle.net/d8GYk/, you'll notice the styling properties applied to the div. <div style="position: ...