Reputation: 580
I'm trying to set up some login in my SCSS code to make a single class act differently depending on the type of element it's applied to. In this case, I want to make the class of shadow-#{$size}
apply a text-shadow to text elements (as outlined in a Sass Map/List) and apply a box-shadow to everything else.
I currently have my SASS Map laid out like so:
$text-type-map: (
h1,
h2,
h3,
h4,
h5,
h6,
p,
a,
span,
ul,
li
);
And I have my text-shadow
applying correctly on all elements in that map with a simple @each
loop:
@each $name, $size in $shadow-size-map {
@each $type in $text-type-map {
#{$type}.shadow-#{$name} {
text-shadow: 0px #{$size} rgba($dark, 0.5);
}
}
}
But when it comes to applying the logic to every element that is not in the list, I am having a bit of trouble.
My first thought on this was to apply a :not()
pseudo-selector. But the implementation for this has been a little tricky. The goal here would be to create something like this:
.shadow-#{$name}:not(h1):not(h2):not(h3) ect... {
box-shadow: 0px #{$size} rgba($dark, 0.5);
}
But I'm not really sure how to do that. I have tried using the map-keys()
SCSS function:
.shadow-#{$name}:not(map-keys($text-type-map)) {
box-shadow: 0px #{$size} rgba($dark, 0.5);
}
But that doesn't seem to be doing anything.
Does anyone know if there is a better way to implement this (like an @if / @else
function) or a way to make the :not()
selector work correctly - essentially listing all items within the Sass Map on a single line with each value in it's own :not()
.
Upvotes: 2
Views: 613
Reputation: 346
As long as the list is comma-separated (which the output of map-keys
should be) you can actually achieve this just by escaping the Sass list inside the :not
selector
.example:not(#{map-keys($text-type-map)}) {
color: red;
}
// output:
// .example:not(h1, h2, h3, h4, h5, h6, p, a, span, ul, li) {
// color: red;
// }
However, support for a selector list is a somewhat newer feature of :not
, and is not supported in IE and other odd browsers.
If you need that support, you will probably need to write a function to chain the not selectors:
@function not-chain($list) {
$output: '';
@each $selector in $list {
$output: $output + ':not(#{$selector})';
}
@return $output;
}
$exclude: map-keys($text-type-map);
.example#{not-chain($exclude)} {
color: red;
}
// output:
// .example:not(h1):not(h2):not(h3):not(h4):not(h5):not(h6):not(p):not(a):not(span):not(ul):not(li) {
// color: red;
// }
Upvotes: 2