I'm having trouble to avoid having duplicate code.
I have an element which can have size modifiers to alter the appearance of the element: sm, md, lg. Let's say my element is called .element
and my size modifier classes are called .size-sm
, .size-md
and .size-lg
.
These size classes are not required, however. In this case the element should use the properties from the md class as a default. In other words: .element
and .element.size-md
should give the same results.
My Sass Map is as followed:
$elementSizes: (
sm: (
fontSize: 0.875rem,
height: 42px,
),
md: (
fontSize: 1rem,
height: 48px,
),
lg: (
fontSize: 1.125rem,
height: 54px,
),
);
My loop is currently as followed:
.element {
@each $size, $values in $elementSizes {
@if $size == md {
&,
&.size-#{$size} {
font-size: map-get($values, fontSize);
height: map-get($values, height);
}
} @else {
&.size-#{$size} {
font-size: map-get($values, fontSize);
height: map-get($values, height);
}
}
}
}
As you can see, I check if the object of the loop is called 'md' and then also apply its values to the parent element using the &
. But it requires for me to have all properties applied twice, which I want to avoid. There is absolutely no difference between the properties applied in the if or in the else.
Any help in trying to optimize this is appreciated!
You have multiple possibilities to do this. For example:
1. With append()
@use 'sass:list';
.element {
@each $size, $values in $elementSizes {
$selector: "&.size-#{$size}";
@if $size == md {
$selector: list.append("&", $selector, $separator: comma);
}
#{$selector} {
font-size: map-get($values, fontSize);
height: map-get($values, height);
}
}
}
2. With a ternary operator
.element {
@each $size, $values in $elementSizes {
$default: if($size == md, "&,", "");
#{$default}&.size-#{$size} {
font-size: map-get($values, fontSize);
height: map-get($values, height);
}
}
}