Sass Compatibility
-
&
SassScript -
Angle conversion
-
@at-root
directive -
call
function -
Forbid cross-media
@extend
-
Deep
@extend
-
Downward
@for
-
@error
directive -
Feature detection functions
-
Fixed
if
function -
inspect
function -
list-separator
function -
Map API
-
Media queries merge
-
Multi assignment
@each
-
Multi keys
map-remove
-
Negative indexes
-
Nested interpolations
-
random
function -
rebeccapurple
color -
Reserved function names
-
Selector manipulation functions
-
set-nth
function -
Shadow DOM styling
-
Spaces around minus symbol
-
String manipulation functions
-
transparent
color -
unique-id
function -
Variable scoping
&
SassScript
Description
The ability to use &
, the reference to the current selector, in SassScript.
This basically means that &
can be manipulated, inspected and updated manually.
Work-around
There is no known polyfill or work-around for this.
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
tests/ampersand_sassscript | ||||||
Support |
Angle conversion
§Description
Angles can be emitted in four different units:
- Degrees:
deg
- Radians:
rad
- Gradians:
grad
- Turns:
turn
Sass should be able to auto-convert angles from one unit to another.
Work-around
@function convert-angle($value, $unit) {
$convertable-units: deg grad turn rad;
$conversion-factors: 1 10grad/9deg 1turn/360deg 3.1415926rad/180deg;
@if index($convertable-units, unit($value)) and index($convertable-units, $unit) {
@return $value
/ nth($conversion-factors, index($convertable-units, unit($value)))
* nth($conversion-factors, index($convertable-units, $unit));
}
@error "Cannot convert `#{unit($value)}` to `#{$unit}`.";
}
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
spec/libsass-closed-issues/issue_666/angle | ||||||
Support |
@at-root
directive
Description
The @at-root
directive causes one or more rules to be emitted at the root of the document, rather than being nested beneath their parent selectors.
Work-around
There is no known polyfill or work-around for this.
Tests and support
call
function
Description
The call
function makes it possible to call a function dynamically, by referencing its name.
Work-around
Unfortunately, the call
function is not easily polyfilled.
You would have to create a function with a switch case for every existing function in the global scope;
Sass default functions such as quote
or invert
, and your own functions as well.
That’s a pain and kind of defeats the initial purpose.
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
spec/basic/60_call | ||||||
Support |
Forbid cross-media @extend
Description
As of today, the @extend
directive cannot be used across different media contexts.
Work-around
Use a mixin instead.
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
tests/cross_media_extend | ||||||
Support |
Deep @extend
Description
Deep extend names the situation where the @extend
directive is being used from a compound selector, for instance .a .b .c
.
Work-around
There is no known polyfill or work-around for this.
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
spec/libsass-closed-issues/issue_592 | ||||||
Support |
Downward @for
Description
For long, there was no way to have decrementing @for
loops. They could only go upward. No error was thrown, but it simply did not iterate.
Work-around
@for $i from -10 through -1 {
$i: abs($i);
// Do something
}
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
spec/libsass-closed-issues/issue_703 | ||||||
Support |
@error
directive
Description
The @error
directive throws the value of a SassScript expression as a fatal error, including a nice stack trace. It’s useful for validating arguments to mixins and functions.
Work-around
@if ($condition) {
@warn $error;
@return null;
}
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
tests/error_directive | ||||||
Support |
Feature detection functions
§Description
Feature detection functions include feature-exists
, variable-exists
, global-variable-exists
, function-exists
and mixin-exists
.
Work-around
There is no known polyfill or work-around for this.
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
spec/libsass-closed-issues/issue_702 | ||||||
spec/basic/55_variable_exists | ||||||
spec/basic/56_global_variable_exists | ||||||
spec/basic/57_function_exists | ||||||
spec/basic/58_mixin_exists | ||||||
Support |
Fixed if
function
Description
The if
function returns one of two values, depending on whether or not $condition
is true.
Just like in @if
, all values other than false
and null
are considered to be true
.
There has long been a bug with this function where all arguments where evaluated, no matter the result of the condition.
Work-around
Use a conditional statement (@if
/ @else
).
// Instead of:
// $value: if(length($list) > 2, nth($list, 3), nth($list, 1));
$value: nth($list, 1);
@if length($list) > 2 {
$value: nth($list, 3);
}
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
spec/libsass-closed-issues/issue_338 | ||||||
Support |
inspect
function
Description
The inspect
function returns a string containing the value as its Sass representation.
It is especially useful when printing lists and maps as CSS values.
Work-around
There is no known polyfill or work-around for this.
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
spec/libsass-closed-issues/issue_701 | ||||||
Support |
list-separator
function
Description
The list-separator
function returns the separator of a list.
If the list doesn’t have a separator due to having fewer than two elements, returns space
.
Work-around
@function _list-separator($list) {
@if function-exists("list-separator") == true {
@return list-separator($list);
}
$test-list: ();
@each $item in $list {
$test-list: append($test-list, $item, space);
}
@return if($test-list == $list, space, comma);
}
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
spec/libsass-closed-issues/issue_506 | ||||||
Support |
Map API
§Description
The Map API includes the map
Sass data type and functions map-get
, map-merge
, map-remove
, map-keys
, map-values
, map-has-key
and keywords
.
Work-around
Maps can be faked with bi-dimensional lists such as:
$map: (
a 1,
b 2,
c 3
);
Then, Sass List-Maps from Lu Nelson can be used to polyfill the whole Map API.
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
spec/maps/map-get | ||||||
spec/maps/map-has-key | ||||||
spec/maps/map-keys | ||||||
spec/maps/map-merge | ||||||
spec/maps/map-remove | ||||||
spec/maps/map-values | ||||||
Support |
Media queries merge
§Description
While nested media queries are valid CSS, they are quite uncommon. Also, some browsers (Internet Explorer and Opera) do not support nested media queries. Because of this, Sass is supposed to merge compatible nested media queries into a single one.
Work-around
Don’t nest media queries and merge them manually.
// Instead of:
// @media (min-width: 600px) {
// @media (max-width: 800px) { .. }
// }
@media (min-width: 600px) and (max-width: 800px) { .. }
Tests and support
Multi assignment @each
Description
It is possible to assign several variables at once in an @each
loop, which turns out to be especially useful when iterating over maps.
For instance, @each $key, $value in $map
. Learn more about multi-assignment.
Work-around
Use a regular loop.
@each $item in $map {
$key: nth($item, 1);
$value: nth($item, 2);
// Do something
}
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
spec/libsass-closed-issues/issue_492 | ||||||
Support |
Multi keys map-remove
Description
Some engines cannot remove multiple keys of a map at once with the map-remove
function.
Work-around
@function map-multi-remove($map, $keys...) {
@each $key in $keys {
$map: map-remove($map, $key);
}
@return $map;
}
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
spec/libsass-closed-issues/issue_510 | ||||||
Support |
Negative indexes
§Description
All list functions support negative indexes in order to start from the last item in the list rather than the first.
For instance, nth($list, -1)
returns the last item from $list
.
Work-around
Substract indexes to the result of length
function.
// Instead of:
// $value: nth($list, -3);
$value: nth($list, length($list) - 2);
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
spec/libsass-closed-issues/issue_224 | ||||||
Support |
Nested interpolations
§Description
Interpolations (#{..}
) can be nested.
Work-around
Not only nested interpolations are quite uncommon, but it also turns out to be easy to refactor the code so it doesn’t happen.
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
spec/libsass-closed-issues/issue_615 | ||||||
Support |
random
function
Description
The random
function returns a decimal between 0 and 1, inclusive.
When given an argument, it returns a decimal between 0 and the given number.
Work-around
There is no known polyfill or work-around for this.
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
spec/libsass-closed-issues/issue_657/limit | ||||||
spec/libsass-closed-issues/issue_657/default | ||||||
Support |
rebeccapurple
color
Description
The rebeccapurple
CSS color can safely be used, yet it cannot be manipulated as a color.
Work-around
Use #663399
. You could stuff it in a variable.
$rebeccapurple: #663399;
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
spec/libsass-closed-issues/issue_699 | ||||||
Support |
Reserved function names
§Description
Sass is supposed to throw an error if one tries to create and call functions named or
, not
or and
.
Work-around
Name your functions differently.
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
tests/reserved_function_names/not | ||||||
tests/reserved_function_names/and | ||||||
tests/reserved_function_names/or | ||||||
Support |
Selector manipulation functions
§Description
Selector manipulation functions include selector-nest
, selector-append
, selector-extend
, selector-replace
, selector-unify
, is-superselector
, simple-selectors
and selector-parse
.
Work-around
There is no known polyfill or work-around for this.
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
tests/selector_manipulation_functions | ||||||
Support |
set-nth
function
Description
The set-nth
function returns a new list, based on the list provided, but with the nth element changed to the value given.
Work-around
@function update-nth($list, $n, $value) {
@if function-exists("set-nth") == true {
@return set-nth($list, $n, $value);
}
$new-list: ();
@for $i from 1 through length($list) {
$new-list: append($new-list, if($i == $n, $value, nth($list, $i)));
}
@return $new-list;
}
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
spec/libsass-closed-issues/issue_578 | ||||||
Support |
Shadow DOM styling
§Description
Shadow DOM selectors for Web Components allow a slightly different syntax than usual CSS selectors.
Work-around
There is no known polyfill or work-around for this.
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
spec/libsass-closed-issues/issue_452 | ||||||
Support |
Spaces around minus symbol
§Description
Spaces around the minus symbol should not be mandatory if the value before the -
sign is a function call.
Work-around
Wrap the minus symbol with spaces to prevent any issue and easy readibility.
.foo {
content: getter() - 1;
}
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
spec/libsass-closed-issues/issue_733 | ||||||
Support |
String manipulation functions
§Description
String manipulation functions include str-length
, str-insert
, str-index
, str-slice
, to-upper-case
and to-lower-case
.
Work-around
There is no known polyfill or work-around for this.
Tests and support
transparent
color
Description
The transparent
CSS color can safely be used, yet it cannot be manipulated as a color.
Work-around
Use rgba(0, 0, 0, 0)
. You could stuff it in a variable.
$transparent: rgba(0, 0, 0, 0);
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
spec/libsass-closed-issues/issue_700 | ||||||
Support |
unique-id
function
Description
The unique-id
function returns a unique CSS identifier.
The identifier is returned as an unquoted string.
The identifier returned is only guaranteed to be unique within the scope of a single Sass run.
Work-around
There is no known polyfill or work-around for this.
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
spec/libsass-closed-issues/issue_636 | ||||||
Support |
Variable scoping
§Description
Not all engines work with the same variable scoping mechanism.
Actually, some don’t have variable scoping at all, which means all variables live in the same global environment (and can overlap).
Some engines do have the new variable scoping system, where a variable is restricted to its scope (function, mixin…) if it’s not set with the !global
flag.
Work-around
This can be detected with:
feature-exists("global-variable-shadowing") == true
Tests and support
Test | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
spec/libsass-closed-issues/issue_613 | ||||||
Support |
Tests statistics §
Caution! Those stats are computed based on the few tests we run here on Sass-Compatibility. They do not reflect the current status of support for each engine. Please do not communicate those stats to compare different engines, it would be unfair.
Section | Ruby Sass 3.2 | Ruby Sass 3.3 | Ruby Sass 3.4 | LibSass 3.1 | LibSass 3.2 | LibSass 3.3 |
---|---|---|---|---|---|---|
Passed | 8 | 54 | 68 | 33 | 67 | 68 |
Failed | 60 | 14 | 0 | 35 | 1 | 0 |
Percentage | 11.76% | 79.41% | 100.0% | 48.53% | 98.53% | 100.0% |