I'm unable to compile sass with the new $grid-breakpoint changes.
This worked just fine with 4.1. It now doesn't seem possible with 4.2
In my custom variable file that's included before everything BS4 I have the following:
$grid-breakpoints: (
xxs: 0,
xs: 480px,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px
);
As you can see, an additional custom breakpoint exists at 480px.
Previously 4.1 _variable.sass contained:
$grid-breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px
) !default;
@include _assert-ascending($grid-breakpoints, "$grid-breakpoints");
@include _assert-starts-at-zero($grid-breakpoints);
And my code overrode all the breakpoints and worked fine.
Now in 4.2 _variable.sass:
$grid-breakpoints: () !default;
// stylelint-disable-next-line scss/dollar-variable-default
$grid-breakpoints: map-merge(
(
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px
),
$grid-breakpoints
);
@include _assert-ascending($grid-breakpoints, "$grid-breakpoints");
@include _assert-starts-at-zero($grid-breakpoints);
And it gives the following errors:
WARNING: Invalid value for $grid-breakpoints: This map must be in ascending order, but key 'xxs' has value 0 which isn't greater than 1200px, the value of the previous key 'xl' !
WARNING: First breakpoint in `$grid-breakpoints` must start at 0, but starts at 480px.
WARNING: Invalid value for $container-max-widths: This map must be in ascending order, but key 'xs' has value 500px which isn't greater than 1140px, the value of the previous key 'xl' !
The def of map-merge() specifies that the order of $map1 will have precedence while $map2 will override values.
/**
* Merges two maps together into a new map. Keys in `$map2` will take
* precedence over keys in `$map1`.
*
* This is the best way to add new values to a map.
*
* All keys in the returned map that also appear in `$map1` will have the
* same order as in `$map1`. New keys from `$map2` will be placed at the end
* of the map.
*
* Like all map functions, `map-merge()` returns a new map rather than
* modifying its arguments in place.
*
* @example
* map-merge(("foo": 1), ("bar": 2)) => ("foo": 1, "bar": 2)
* map-merge(("foo": 1, "bar": 2), ("bar": 3)) => ("foo": 1, "bar": 3)
* @overload map_merge($map1, $map2)
* @param $map1 [Sass::Script::Value::Map]
* @param $map2 [Sass::Script::Value::Map]
* @return [Sass::Script::Value::Map]
* @raise [ArgumentError] if either parameter is not a map
*/
@function map_merge($map1, $map2) { /* stub */ }
Since, unlike the other maps that are merged, the order is important, $map2 should have precedence.
To achieve this I think the double application of map-merge() should take care of it:
$grid-breakpoints: () !default;
// stylelint-disable-next-line scss/dollar-variable-default
$grid-breakpoints-ordered: map-merge(
$grid-breakpoints,
(
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px
)
);
$grid-breakpoints: map-merge($grid-breakpoints-ordered, $grid-breakpoints)
Unless there's some other sass function that could handle this, I'm not sure of any better way.
Additionally the docs give a specific use example:
If you wanted just four grid tiers, you鈥檇 update the $grid-breakpoints ...
which is no longer true since by just defining fewer breakpoints, the default ones will be added back in on merge.
I have the same problem, i'm trying to compile with https://github.com/leafo/scssphp
Before the version 4.2 everything was ok, now i have the same mistakes as you.
The def of map-merge() specifies that the order of
$map1will have precedence while$map2will override values./** * Merges two maps together into a new map. Keys in `$map2` will take * precedence over keys in `$map1`. * * This is the best way to add new values to a map. * * All keys in the returned map that also appear in `$map1` will have the * same order as in `$map1`. New keys from `$map2` will be placed at the end * of the map. * * Like all map functions, `map-merge()` returns a new map rather than * modifying its arguments in place. * * @example * map-merge(("foo": 1), ("bar": 2)) => ("foo": 1, "bar": 2) * map-merge(("foo": 1, "bar": 2), ("bar": 3)) => ("foo": 1, "bar": 3) * @overload map_merge($map1, $map2) * @param $map1 [Sass::Script::Value::Map] * @param $map2 [Sass::Script::Value::Map] * @return [Sass::Script::Value::Map] * @raise [ArgumentError] if either parameter is not a map */ @function map_merge($map1, $map2) { /* stub */ }Since, unlike the other maps that are merged, the order is important,
$map2should have precedence.To achieve this I think the double application of map-merge() should take care of it:
$grid-breakpoints: () !default; // stylelint-disable-next-line scss/dollar-variable-default $grid-breakpoints-ordered: map-merge( $grid-breakpoints, ( xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px ) ); $grid-breakpoints: map-merge($grid-breakpoints-ordered, $grid-breakpoints)Unless there's some other sass function that could handle this, I'm not sure of any better way.
Have you solved in this way for now?
Have you solved in this way for now?
Nah, I solved it by changing the dep from ^4.1.0 to ~4.1.0 so it works in the build pipeline.
Easier than forking it for now.
Although, that code does fix it locally. It also needs to be done for the $container-max-widths as well:
$container-max-widths: () !default;
// stylelint-disable-next-line scss/dollar-variable-default
$container-max-widths-order: map-merge(
$container-max-widths,
(
sm: 540px,
md: 720px,
lg: 960px,
xl: 1140px
)
);
$container-max-widths: map-merge($container-max-widths-order, $container-max-widths);
/CC @MartijnCuppens
I think we need to ditch these built-in map-merges for regular Sass maps. It now feels over-engineered, and perhaps poorly documented for how folks can customize things.
With the usage of map-merge everywhere, we have the ability to easily add key-value pairs, but not to remove them. There's no option in Sass to do this, but you can replace a value or add new ones (with map-merge). This is an issue because if you want fewer key-value pairs in a Sass map, you'll see errors like those of https://github.com/twbs/bootstrap/issues/27927#issuecomment-450060013.
So, what if we remove all map-merge in our variables?
Let's consider an example where we look at our $grid-breakpoints.
$grid-breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px
) !default;
To replace all of the values, we redefine the keys' values:
$grid-breakpoints: (
xs: 0,
sm: 400px,
md: 800px,
lg: 1200px,
xl: 1600px
);
To replace individual key-value pairs, we use map-merge:
$grid-breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px
) !default;
$grid-breakpoints: map-merge($grid-breakpoints, (xl: 1600px));
To add additional values, we also use map-merge:
$grid-breakpoints: map-merge(
$grid-breakpoints,
(
xxl: 1600px,
xxxl: 1800px
)
);
To do a bit of everything, we can use replace the default values and use multiple map-merges:
$grid-breakpoints: (
xs: 300px,
sm: 500px,
md: 800px,
lg: 1100px,
xl: 1400px
);
$grid-breakpoints: map-merge(
(
xxs: 0
),
$grid-breakpoints
);
$grid-breakpoints: map-merge(
$grid-breakpoints,
(
xxl: 1600px,
xxxl: 1800px
)
);
Hi @mdo
following your instructions, we are trying this way:
$grid-breakpoints: (
xs: 360px,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px
);
$grid-breakpoints: map-merge((xxs: 0), $grid-breakpoints);
$grid-breakpoints: map-merge($grid-breakpoints, (xxl: 1440px, xxxl: 1680px, xxxxl: 1920px));
$container-max-widths: (
xs: 330px,
sm: 540px,
md: 720px,
lg: 960px,
xl: 1140px
);
$container-max-widths: map-merge((xxs: 0), $container-max-widths);
$container-max-widths: map-merge($container-max-widths, (xxl: 1380px, xxxl: 1620px, xxxxl: 1860px));
@import '../../scripts/vendor/bootstrap-4.2.1/scss/bootstrap.scss';
but these are the results:
WARNING: Invalid value for $grid-breakpoints: This map must be in ascending order, but key 'xxs' has value 0px which isn't greater than 1200px, the value of the previous key 'xl' !
WARNING: First breakpoint in
$grid-breakpointsmust start at 0, but starts at 360px.
WARNING: Invalid value for $container-max-widths: This map must be in ascending order, but key 'xxs' has value 0px which isn't greater than 1140px, the value of the previous key 'xl' !
Error: Invalid null operation: "null sub 0.02".
Can you help us, please? Thanks a lot.
Benedetto
@Bek81
Those weren't instructions, he was giving an example of how sass maps could work and how they could potentially work in the core _variables.scss file. Simply revert to 4.1 until it's resolved as there's no fix without modifying _variables.scss.
There's also no use in using the merge-map in your own definitions of the variables. The last example @bdo gave would have to have the extra xxs and xxl variables in like $breakpoints-before / $breakpoints-after which is way overly complicated.
The example I provided makes overriding the breakpoints nearly the same as 4.1, but still has the issue of not being able to remove breakpoints. Reverting to the way it was done in 4.1 without merge-map seems like it might be the best solution. The update provides no benefit other than being able to override a single break point or add one larger, most other cases you'd need to override each breakpoint manually anyway.
It's also possible to sort maps after merge, I tried with this gist and it worked without changing anything else : https://gist.github.com/Jakobud/a0ac11e80a1de453cd86f0d3fc0a1410#gistcomment-2327765
This is preventing us from upgrading to 4.2
Hi there,
what's the status of this "warning" issue?
I would suggest to just revert the new $grid-breakpoints declaration to what it was before, on the 4.1 version:
$grid-breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px
) !default;
the new approach uses:
$grid-breakpoints: map-merge(
(
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px
),
$grid-breakpoints
);
so when you try to update the variable using your custom.scss like this:
$grid-breakpoints: (
xs: 0,
ss: 380px,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px,
xx: 1440px
);
the _assert_ascending function will throw the following warning:
Invalid value for $grid-breakpoints: This map must be in ascending order, but key 'ss' has value 320px which isn't greater than 1200px, the value of the previous key 'xl' !
scss/_functions.scss 18:7 _assert-ascending()
Adding @debug $key; @debug $num; you can easily see what's going on.
scss/_functions.scss:11 Debug: xs
scss/_functions.scss:12 Debug: 0
scss/_functions.scss:11 Debug: sm
scss/_functions.scss:12 Debug: 576px
scss/_functions.scss:11 Debug: md
scss/_functions.scss:12 Debug: 768px
scss/_functions.scss:11 Debug: lg
scss/_functions.scss:12 Debug: 992px
scss/_functions.scss:11 Debug: xl
scss/_functions.scss:12 Debug: 1200px
scss/_functions.scss:11 Debug: ss
scss/_functions.scss:12 Debug: 320px
The ss value I've added in my custom.scss goes to end of the map so this function.
when compares $prev-num >= $num (1200px >= 320px) -> warning message
Note that this is just a warning so the CSS gets compiled.
Thanks!
If you really want to avoid this warning message you can (temporary and hacky fix) comment this line:
@include _assert-ascending($grid-breakpoints, "$grid-breakpoints");
_variables.scss lines 201 and 221
Most helpful comment
I think we need to ditch these built-in
map-merges for regular Sass maps. It now feels over-engineered, and perhaps poorly documented for how folks can customize things.With the usage of
map-mergeeverywhere, we have the ability to easily add key-value pairs, but not to remove them. There's no option in Sass to do this, but you can replace a value or add new ones (withmap-merge). This is an issue because if you want fewer key-value pairs in a Sass map, you'll see errors like those of https://github.com/twbs/bootstrap/issues/27927#issuecomment-450060013.So, what if we remove all
map-mergein our variables?Let's consider an example where we look at our
$grid-breakpoints.To replace all of the values, we redefine the keys' values:
To replace individual key-value pairs, we use
map-merge:To add additional values, we also use
map-merge:To do a bit of everything, we can use replace the default values and use multiple
map-merges:You can see all of this in this Sassmeister gist.