I'm making my own plugins that makes multiple media queries automatically by writing single @include
line in SCSS.
So when I type @include medias($bp-values, width);
, the output should be like this:
@media all and (min-width: 564px) {
width: 200px;
}
@media all and (min-width: 768px) {
width: 300px;
}
@media all and (min-width: 992px) {
width: 400px;
}
@media all and (min-width: 1200px) {
width: 500px;
}
And this is the code:
$breakpoints: (
564,
768,
992,
1200
);
$bp-values: (
width: (
200px, 300px, 400px, 500px
),
font-size: (
20px, 30px, 40px, 50px
)
);
@function gridnum($m, $v) {
@return map-get($m, $v);
}
@mixin medias($map, $key) {
$myList: map-get($map, $key);
@each $value in $myList {
$number: index($myList, $value);
$grid: gridnum($breakpoints, $num);
@if $value == $num {
@media all and (min-width: $grid + px) {
#{$key}: $value;
}
} @else {
@warn "There is an error to make @media queries.";
}
}
}
What I need is to get the $values
of $breakpoints
for setting it as prefixes of @media queries' width.
But the code doesn't run, and I get this:
Error: Undefined variable: "$num".
Most idle solution would be to merge 2 $maps in single @each directive, but seems like SCSS doesn't support this.
Is there any ways to fix this problem?
In my opinion you did not understand very well the difference between maps and lists.
The list is an array
of values:
$breakpoints: (
564,
768,
992,
1200
);
or
$breakpoints: 564, 768, 992, 1200;
or
$breakpoints: 564 768 992 1200;
So this @return map-get($m, $v);
will get you always errors because $breakpoints
is not a map.
The maps have keys and values:
$breakpoints: (
xs: 564,
md: 768,
lg: 992,
xl: 1200
);
To help you in your project, maybe it is better to write a map of nested maps:
$myMap:(
xs:(
min-width: 564px,
width: 200px,
font-size: 20px
),
md:(
min-width: 768px,
width: 300px,
font-size: 30px
),
lg:(
min-width: 992px,
width: 400px,
font-size: 40px
),
xl:(
min-width: 1200px,
width: 500px,
font-size: 50px
)
);
It is more clear the correlation to every values. Now we can write a @mixin to get those values:
@mixin medias($map, $key) {
@each $keyMap, $valueMap in $map {
@media all and (min-width: map-get($valueMap, min-width)) {
#{$key}: map-get($valueMap, $key);
}
}
}
And now we can include it!
@include medias($myMap, width);
This is the result you asked for:
@media all and (min-width: 564px) {
width: 200px;
}
@media all and (min-width: 768px) {
width: 300px;
}
@media all and (min-width: 992px) {
width: 400px;
}
@media all and (min-width: 1200px) {
width: 500px;
}
I posted your new sass file, much more understandable, I think
$myMap:(
xs:(
min-width: 564px,
width: 200px,
font-size: 20px
),
md:(
min-width: 768px,
width: 300px,
font-size: 20px
),
lg:(
min-width: 992px,
width: 400px,
font-size: 20px
),
xl:(
min-width: 1200px,
width: 500px,
font-size: 20px
)
);
@mixin medias($map, $key) {
@each $keyMap, $valueMap in $map {
@media all and (min-width: map-get($valueMap, min-width)) {
#{$key}: map-get($valueMap, $key);
}
}
}
@include medias($myMap, width);