In gruntfile
stylelint: {
all: ['app/styles/**/*.scss']
},
.stylelintrc
{
"plugins": [
"stylelint-selector-bem-pattern"
],
"rules": {
"plugin/selector-bem-pattern": {
"componentName": "[A-Z]+",
"componentSelectors": {
"initial": "^\\.{componentName}(?:-[a-z]+)?$",
"combined": "^\\.combined-{componentName}-[a-z]+$"
},
"utilitySelectors": "^\\.util-[a-z]+$"
}
}
}
/Users/jitendravyas/app-test/styles/components/_campaign-settings-integrations.scss
/* #define campaign-settings */
.campaign-settings__integrations {
#include flex;
}
.campaign-settings__integration {
border: 1px solid $color-green;
border-radius: 3px;
color: $color-green;
margin-right: $base-spacing-unit;
#include flex;
.check {
background: $color-green;
color: white;
#include vertical-center;
}
> div {
padding: $half-spacing-unit;
}
}
Not getting any error when I run stylelint. Stylelint is working with other rules.
I believe you have incorrectly defined your component name. As such, the linter is correctly skipping over the file.
You must use either a concise or verbose syntax:
/** #define campaign-settings */
or
/* postcss-bem-linter: define campaign-settings */
At the moment you appear to use an invalid form of the concise syntax i.e. your comment begins with /*, rather than /**.
Related
I am having trouble prepending the root class to my current selector in sass. I have the following code:
.cta-two-columns {
&__text-holder {
#at-root&#{__inner} {
// also tried #at-root __inner&{#}
// and many others like #at-root__inner
padding: rem(25px);
}
}
}
but this gives me the following:
.cta-two-columns__text-holder__inner {
padding: rem(25px);
}
I don't understand the above - what's the point of at-root as you may as well just do &__inneras it gave me the same as the two things I have shown I tried
how do I get
.cta-two-columns__text-holder .cta-two-columns__inner {
}
without having to resort to
.cta-two-columns {
&__text-holder {
.cta-two-columns__inner {
padding: rem(25px);
}
}
}
Or is this the only way to do it in sass?
#at-root doesn't really work like you may think in this case. #at-root will simply make the declaration outside the nest. To better understand, add another CSS declaration like below:
.cta-two-columns {
&__text-holder {
margin: 10px;
#at-root&#{__inner} {
padding: rem(25px);
}
}
}
This will produce the following CSS code:
.cta-two-columns__text-holder {
margin: 10px;
}
.cta-two-columns__text-holder__inner {
padding: rem(25px);
}
Simply imagine how the selector will be created without #at-root then make it outside.
Without it will produce this:
.cta-two-columns__text-holder {
margin: 10px;
}
.cta-two-columns__text-holder .cta-two-columns__text-holder__inner {
padding: rem(25px);
}
Then we simply omit .cta-two-columns__text-holder.
One idea to obtain what you want is to consider a variable where you can declare the main class then you will be able to nest as many element as you want:
$sel: '.cta-two-columns';
#{$sel}__text-holder {
#{$sel}__inner {
padding: rem(25px);
}
}
Will produce:
.cta-two-columns__text-holder .cta-two-columns__inner {
padding: rem(25px);
}
with more nested elements:
$sel: '.cta-two-columns';
#{$sel}__text-holder {
#{$sel}__outer {
#{$sel}__inner{
#{$sel}__wrap{
padding: rem(25px);
}
}
}
}
Will produce
.cta-two-columns__text-holder .cta-two-columns__outer .cta-two-columns__inner .cta-two-columns__wrap {
padding: rem(25px);
}
I have a project where legacy code has classes like
promo game-promo
I've got the chance to clean up the css by changing to scss but the issue I'm trying to cover is I'd like to nest promo and have game- prepend the parent.
.promo {
display: flex;
game-& {
color: black;
}
}
I'd have liked the above to work but it doesn't and wondering if anyone has come across any ways of achieving what I'm after?
.game-promo {
color: black;
#at-root .promo {
display: flex;
}
}
It seems its not possible so after re-jigging the code I have now got this.
You can't do what you're trying. The "&" is used to get the current selector, in your case : game-.promo or .game-.promo if you add the class selector but it can't work.
In your case, you can do :
.game-promo {
color: black;
.promo {
display: flex;
}
}
Or rename your classes name : (I give an example with inverting the logic of your names)
Parent with ".promo"
Child with ".promo-game"
So you could do :
.promo {
//properties
&-game {
//properties
}
}
It is possible but not very pretty (code on jsFiddle):
/** see https://gist.github.com/Bamieh/912a6f0b63cbb53f3ad0bd8df7171c6a */
#function parse-dotless($class) {
$this: quote($class);
#return if(str-slice($this, 0, 1) == ".", str-slice($this, 2, str-length($this)), $this);
}
.promo {
color:yellow;
#at-root .game-#{parse-dotless(&)} {
color: blue;
}
}
<span class="promo">Hello</span>
<span class="game-promo">World</span>
You cannot do exactly what your snippet states using only the & feature. Instead you could build modifier classes like this:
.btn {
&-primary {}
&-secondary {}
}
Which is translated to:
.btn-primary {}
.btn-secondary {}
In your code example, you can invert the rule names:
.promo {
display: flex;
&-game {
color: black;
}
}
Read more about the sass-ampersand
In my scss code I'm trying to make placeholder like:
%input__label {
color: red;
&_content {
color: blue;
}
}
And then extend it:
.input__label {
#extend %input__label;
}
When I'm trying to compile that code only input__label compiles, but input__label_content doesn't:
.input__label {
color: red;
}
(But for example with pseudo elements - &::after everything works fine)
Why is this hapenning? I'm using node v7.10.1 and node-sass v4.5.3.
Use a mixin instead of an extend:
#mixin input__label {
color: red;
&_content {
color: blue;
}
}
.input__label {
#include input__label;
}
The functionality to do it via extends is purposefully disallowed:
https://github.com/sass/sass/commit/face3172930b515ac2040e450d4db3ffe01c31b5
I'm trying to come up with a way to simplify some SCSS attribute selectors. What I end up with is:
[data-attr="opt1"] { ... }
[data-attr="opt2"] { ... }
[data-attr="opt3"] { ... }
What I'm hoping for is to be able to write something closer to:
[data-attr]
&="opt1" { ... }
&="opt2" { ... }
&="opt3" { ... }
via a mixin, or whatever. Can't come up with a solution though. Any clever ideas?
I've come to this idea:
#mixin attrVal($value) {
$attr: str-slice(#{&}, 2, -2); // $attr = "data-attr"
#at-root {
[#{$attr}="#{$value}"] {
#content;
}
}
}
[data-attr] {
#include attrVal('opt1') { width: 10px; }
#include attrVal('opt2') { width: 20px; }
#include attrVal('opt3') { width: 30px; }
}
Output (tested on sassmeister.com)
[data-attr="opt1"] { width: 10px; }
[data-attr="opt2"] { width: 20px; }
[data-attr="opt3"] { width: 30px; }
For this specific example there's no that huge simplification, but with this approach you're actually decoupling the attribute name from its value (in the aim of code reuse).
Is it possible to #extend a SCSS placeholder with nesting, and have that nesting reflected in the resulting class?
Given a nested placeholder:
%my-form-field {
...
&__label {
...
}
&__feedback {
...
}
}
I currently have to do the following:
.one-of-many-targets {
#extend %my-form-field;
&__label {
#extend %my-form-field__label;
}
&__feedback {
#extend %my-form-field__feedback;
}
}
But I'd like to be able to simplify this to:
.one-of-many-targets {
#extend %my-form-field;
}
... and have it resolve to:
.one-of-many-targets { ... }
.one-of-many-targets__label { ... }
.one-of-many-targets__feedback { ... }
Is there a different way to write my placeholder and #extends to make the SCSS cleaner, as in the 2nd example?
You can use a mixin instead:
#mixin my-form-field() {
width: 10px;
&__label {
width: 20px;
}
&__feedback {
width: 30px;
}
}
.one-of-many-targets {
#include my-form-field();
}
will generate:
.one-of-many-targets {
width: 10px;
}
.one-of-many-targets__label {
width: 20px;
}
.one-of-many-targets__feedback {
width: 30px;
}
You could try use selector.append()
See: https://github.com/sass/sass/issues/2808#issuecomment-574413393
Also see more info why parent selector didn't work as you expect in extend-only selectors: https://github.com/sass/sass/issues/2262#issuecomment-291645428