diff --git a/Rakefile b/Rakefile index 6f82747e1..d4c8917f2 100644 --- a/Rakefile +++ b/Rakefile @@ -67,6 +67,28 @@ namespace :sass do end end + namespace :migrator do + # Check out the latest commit of the Sass migrator into the .sass-migrator directory. + task :checkout do + unless Dir.exists?(".sass-migrator") + sh %{git clone git://github.com/sass/migrator .sass-migrator} + end + + Dir.chdir(".sass-migrator") do + sh %{git fetch} + if ENV["SASS_MIGRATOR_REVISION"] + sh %{git checkout #{ENV["SASS_MIGRATOR_REVISION"]}} + else + sh %{git checkout origin/master} + end + end + end + + task :version => :checkout do + add_version 'migrator', Dir.chdir(".sass-migrator") {latest_stable_tag} + end + end + namespace :libsass do # Check out the latest commit of Dart Sass into the .libsass directory. task :checkout do diff --git a/config.ru b/config.ru index 282665958..7221bdae5 100644 --- a/config.ru +++ b/config.ru @@ -22,9 +22,11 @@ use Rack::Rewrite do r301 '/documentation/file.SASS_CHANGELOG.html', 'https://github.com/sass/dart-sass/blob/master/CHANGELOG.md' r301 '/documentation/file.INDENTED_SYNTAX.html', '/documentation/syntax' r301 '/documentation/file.SCSS_FOR_SASS_USERS.html', '/documentation/syntax' - r301 '/documentation/Sass/Script/Functions.html', '/documentation/functions' - r301 '/documentation/Sass/Script/Functions', '/documentation/functions' + r301 '/documentation/Sass/Script/Functions.html', '/documentation/modules' + r301 '/documentation/Sass/Script/Functions', '/documentation/modules' r301 %r{/documentation/(Sass.*)}, 'http://www.rubydoc.info/gems/sass/$1' + r301 '/documentation/functions/css', '/documentation/at-rules/function#plain-css-functions' + r301 %r{/documentation/functions(.*)}, '/documentation/modules$1' r301 %r{/(.+)/$}, '/$1' r301 %r{/(.+)/index\.html$}, '/$1' diff --git a/data/documentation.yml b/data/documentation.yml index 67013fbd2..c786ab38c 100644 --- a/data/documentation.yml +++ b/data/documentation.yml @@ -14,6 +14,8 @@ toc: - Interpolation: /documentation/interpolation - At-Rules: /documentation/at-rules :children: + - @use: /documentation/at-rules/use + - @forward: /documentation/at-rules/forward - @import: /documentation/at-rules/import - @mixin and @include: /documentation/at-rules/mixin - @function: /documentation/at-rules/function @@ -46,16 +48,15 @@ toc: - Numeric: /documentation/operators/numeric - String: /documentation/operators/string - Boolean: /documentation/operators/boolean -- Built-In Functions: /documentation/functions +- Built-In Modules: /documentation/modules :children: - - Plain CSS: /documentation/functions/css - - Numbers: /documentation/functions/math - - Strings: /documentation/functions/string - - Colors: /documentation/functions/color - - Lists: /documentation/functions/list - - Maps: /documentation/functions/map - - Selectors: /documentation/functions/selector - - Introspection: /documentation/functions/meta + - sass:color: /documentation/modules/color + - sass:list: /documentation/modules/list + - sass:map: /documentation/modules/map + - sass:math: /documentation/modules/math + - sass:meta: /documentation/modules/meta + - sass:selector: /documentation/modules/selector + - sass:string: /documentation/modules/string - Breaking Changes: /documentation/breaking-changes :children: - Extending Compound Selectors: /documentation/breaking-changes/extend-compound @@ -64,4 +65,5 @@ toc: :children: - Dart Sass: /documentation/cli/dart-sass - Ruby Sass: /documentation/cli/ruby-sass + - Migrator: /documentation/cli/migrator - JavaScript API: /documentation/js-api diff --git a/helpers/sass_helpers.rb b/helpers/sass_helpers.rb index 4317ea6b7..66ed06f99 100644 --- a/helpers/sass_helpers.rb +++ b/helpers/sass_helpers.rb @@ -322,6 +322,7 @@ def release_url(impl) repo = case impl when :dart; "dart-sass" + when :migrator; "migrator" when :libsass; "libsass" end @@ -423,7 +424,7 @@ def _impl_status_row(name, status) ] end - # Renders API docs for a Sass function. + # Renders API docs for a Sass function (or mixin). # # The function's name is parsed from the signature. The API description is # passed as a Markdown block. If `returns` is passed, it's included as the @@ -434,7 +435,8 @@ def _impl_status_row(name, status) def function(*signatures, returns: nil) names = Set.new highlighted_signatures = signatures.map do |signature| - name = signature.split("(").first + name, rest = signature.split("(", 2) + name_without_namespace = name.split(".").last html = Nokogiri::HTML(_render_markdown(<null', '/documentation/values/null' when 'function'; link_to type, '/documentation/values/functions' - when 'selector'; link_to type, '/documentation/functions/selector#selector-values' + when 'selector'; link_to type, '/documentation/modules/selector#selector-values' else raise "Unknown type #{type}" end end.join(" | ") diff --git a/source/assets/js/components/redirect.js b/source/assets/js/components/redirect.js index d6d91fb9f..994f359a5 100644 --- a/source/assets/js/components/redirect.js +++ b/source/assets/js/components/redirect.js @@ -34,9 +34,9 @@ if (window.location.hash) { "#color_operations": "/documentation/operators/color", "#string_operations": "/documentation/operators/string", "#boolean_operations": "/documentation/operators/boolean", - "#list_operations": "/documentation/functions/list", + "#list_operations": "/documentation/modules/list", "#parentheses": "/documentation/operators#parentheses", - "#functions": "/documentation/functions", + "#functions": "/documentation/modules", "#keyword_arguments": "/documentation/at-rules/function#keyword-arguments", "#interpolation_": "/documentation/interpolation", "#parent-script": "/documentation/style-rules/parent-selector#in-sassscript", @@ -97,93 +97,110 @@ if (window.location.hash) { } if (redirect) window.location.href = redirect; - } else if (window.location.pathname == "/documentation/functions") { + } else if (window.location.pathname == "/documentation/modules") { var redirects = { "#declare-class_method": "/ruby-sass", "#random_number_generator-class_method": "/ruby-sass", "#random_seed=-class_method": "/ruby-sass", "#signature-class_method": "/ruby-sass", - "#abs-instance_method": "/documentation/functions/math#abs", - "#adjust_color-instance_method": "/documentation/functions/color#adjust-color", - "#adjust_hue-instance_method": "/documentation/functions/color#adjust-hue", - "#alpha-instance_method": "/documentation/functions/color#alpha", - "#append-instance_method": "/documentation/functions/list#append", - "#blue-instance_method": "/documentation/functions/color#blue", - "#call-instance_method": "/documentation/functions/meta#call", - "#ceil-instance_method": "/documentation/functions/math#ceil", - "#change_color-instance_method": "/documentation/functions/color#change-color", - "#comparable-instance_method": "/documentation/functions/math#comparable", - "#complement-instance_method": "/documentation/functions/color#complement", - "#content_exists-instance_method": "/documentation/functions/meta#content-exists", - "#darken-instance_method": "/documentation/functions/color#darken", - "#desaturate-instance_method": "/documentation/functions/color#desaturate", - "#feature_exists-instance_method": "/documentation/functions/meta#feature-exists", - "#floor-instance_method": "/documentation/functions/math#floor", - "#get_function-instance_method": "/documentation/functions/meta#get-function", - "#global_variable_exists-instance_method": "/documentation/functions/meta#global-variable-exists", - "#grayscale-instance_method": "/documentation/functions/color#grayscale", - "#green-instance_method": "/documentation/functions/color#green", - "#hsl-instance_method": "/documentation/functions/color#hsl", - "#hsla-instance_method": "/documentation/functions/color#hsla", - "#hue-instance_method": "/documentation/functions/color#hue", - "#ie_hex_str-instance_method": "/documentation/functions/color#ie-hex-str", + "#abs-instance_method": "/documentation/modules/math#abs", + "#adjust_color-instance_method": "/documentation/modules/color#adjust", + "#adjust_hue-instance_method": "/documentation/modules/color#adjust-hue", + "#alpha-instance_method": "/documentation/modules/color#alpha", + "#append-instance_method": "/documentation/modules/list#append", + "#blue-instance_method": "/documentation/modules/color#blue", + "#call-instance_method": "/documentation/modules/meta#call", + "#ceil-instance_method": "/documentation/modules/math#ceil", + "#change_color-instance_method": "/documentation/modules/color#change", + "#comparable-instance_method": "/documentation/modules/math#compatible", + "#complement-instance_method": "/documentation/modules/color#complement", + "#content_exists-instance_method": "/documentation/modules/meta#content-exists", + "#darken-instance_method": "/documentation/modules/color#darken", + "#desaturate-instance_method": "/documentation/modules/color#desaturate", + "#feature_exists-instance_method": "/documentation/modules/meta#feature-exists", + "#floor-instance_method": "/documentation/modules/math#floor", + "#get_function-instance_method": "/documentation/modules/meta#get-function", + "#global_variable_exists-instance_method": "/documentation/modules/meta#global-variable-exists", + "#grayscale-instance_method": "/documentation/modules/color#grayscale", + "#green-instance_method": "/documentation/modules/color#green", + "#hsl-instance_method": "/documentation/modules/color#hsl", + "#hsla-instance_method": "/documentation/modules/color#hsla", + "#hue-instance_method": "/documentation/modules/color#hue", + "#ie_hex_str-instance_method": "/documentation/modules/color#ie-hex-str", "#if-instance_method": "/documentation/#if", - "#index-instance_method": "/documentation/functions/list#index", - "#inspect-instance_method": "/documentation/functions/meta#inspect", - "#invert-instance_method": "/documentation/functions/color#invert", - "#is_bracketed-instance_method": "/documentation/functions/list#is-bracketed", - "#is_superselector-instance_method": "/documentation/functions/selector#is-superselector", - "#join-instance_method": "/documentation/functions/list#join", - "#keywords-instance_method": "/documentation/functions/meta#keywords", - "#length-instance_method": "/documentation/functions/list#length", - "#lighten-instance_method": "/documentation/functions/color#lighten", - "#lightness-instance_method": "/documentation/functions/color#lightness", - "#list_separator-instance_method": "/documentation/functions/list#list-separator", - "#map_get-instance_method": "/documentation/functions/map#map-get", - "#map_has_key-instance_method": "/documentation/functions/map#map-has-key", - "#map_keys-instance_method": "/documentation/functions/map#map-keys", - "#map_merge-instance_method": "/documentation/functions/map#map-merge", - "#map_remove-instance_method": "/documentation/functions/map#map-remove", - "#map_values-instance_method": "/documentation/functions/map#map-values", - "#max-instance_method": "/documentation/functions/math#max", - "#min-instance_method": "/documentation/functions/math#min", - "#mix-instance_method": "/documentation/functions/color#mix", - "#mixin_exists-instance_method": "/documentation/functions/meta#mixin-exists", - "#nth-instance_method": "/documentation/functions/list#nth", - "#opacify-instance_method": "/documentation/functions/color#opacify", - "#opacity-instance_method": "/documentation/functions/color#opacity", - "#percentage-instance_method": "/documentation/functions/math#percentage", - "#quote-instance_method": "/documentation/functions/string#quote", - "#random-instance_method": "/documentation/functions/math#random", - "#red-instance_method": "/documentation/functions/color#red", - "#rgb-instance_method": "/documentation/functions/color#rgb", - "#rgba-instance_method": "/documentation/functions/color#rgba", - "#round-instance_method": "/documentation/functions/math#round", - "#saturate-instance_method": "/documentation/functions/color#saturate", - "#saturation-instance_method": "/documentation/functions/color#saturation", - "#scale_color-instance_method": "/documentation/functions/color#scale-color", - "#selector_append-instance_method": "/documentation/functions/selector#selector-append", - "#selector_extend-instance_method": "/documentation/functions/selector#selector-extend", - "#selector_nest-instance_method": "/documentation/functions/selector#selector-nest", - "#selector_parse-instance_method": "/documentation/functions/selector#selector-parse", - "#selector_replace-instance_method": "/documentation/functions/selector#selector-replace", - "#selector_unify-instance_method": "/documentation/functions/selector#selector-unify", - "#set-instance_method": "/documentation/functions/list#set", - "#simple_selectors-instance_method": "/documentation/functions/selector#simple-selectors", - "#str_index-instance_method": "/documentation/functions/string#str-index", - "#str_insert-instance_method": "/documentation/functions/string#str-insert", - "#str_length-instance_method": "/documentation/functions/string#str-length", - "#str_slice-instance_method": "/documentation/functions/string#str-slice", - "#to_lower_case-instance_method": "/documentation/functions/string#to-lower-case", - "#to_upper_case-instance_method": "/documentation/functions/string#to-upper-case", - "#transparentize-instance_method": "/documentation/functions/color#transparentize", - "#type_of-instance_method": "/documentation/functions/meta#type-of", - "#unique_id-instance_method": "/documentation/functions/string#unique-id", - "#unit-instance_method": "/documentation/functions/math#unit", - "#unitless-instance_method": "/documentation/functions/math#unitless", - "#unquote-instance_method": "/documentation/functions/string#unquote", - "#variable_exists-instance_method": "/documentation/functions/meta#variable-exists", - "#zip-instance_method": "/documentation/functions/list#zip" + "#index-instance_method": "/documentation/modules/list#index", + "#inspect-instance_method": "/documentation/modules/meta#inspect", + "#invert-instance_method": "/documentation/modules/color#invert", + "#is_bracketed-instance_method": "/documentation/modules/list#is-bracketed", + "#is_superselector-instance_method": "/documentation/modules/selector#is-superselector", + "#join-instance_method": "/documentation/modules/list#join", + "#keywords-instance_method": "/documentation/modules/meta#keywords", + "#length-instance_method": "/documentation/modules/list#length", + "#lighten-instance_method": "/documentation/modules/color#lighten", + "#lightness-instance_method": "/documentation/modules/color#lightness", + "#list_separator-instance_method": "/documentation/modules/list#separator", + "#map_get-instance_method": "/documentation/modules/map#get", + "#map_has_key-instance_method": "/documentation/modules/map#has-key", + "#map_keys-instance_method": "/documentation/modules/map#keys", + "#map_merge-instance_method": "/documentation/modules/map#merge", + "#map_remove-instance_method": "/documentation/modules/map#remove", + "#map_values-instance_method": "/documentation/modules/map#values", + "#max-instance_method": "/documentation/modules/math#max", + "#min-instance_method": "/documentation/modules/math#min", + "#mix-instance_method": "/documentation/modules/color#mix", + "#mixin_exists-instance_method": "/documentation/modules/meta#mixin-exists", + "#nth-instance_method": "/documentation/modules/list#nth", + "#opacify-instance_method": "/documentation/modules/color#opacify", + "#opacity-instance_method": "/documentation/modules/color#opacity", + "#percentage-instance_method": "/documentation/modules/math#percentage", + "#quote-instance_method": "/documentation/modules/string#quote", + "#random-instance_method": "/documentation/modules/math#random", + "#red-instance_method": "/documentation/modules/color#red", + "#rgb-instance_method": "/documentation/modules/color#rgb", + "#rgba-instance_method": "/documentation/modules/color#rgba", + "#round-instance_method": "/documentation/modules/math#round", + "#saturate-instance_method": "/documentation/modules/color#saturate", + "#saturation-instance_method": "/documentation/modules/color#saturation", + "#scale_color-instance_method": "/documentation/modules/color#scale", + "#selector_append-instance_method": "/documentation/modules/selector#append", + "#selector_extend-instance_method": "/documentation/modules/selector#extend", + "#selector_nest-instance_method": "/documentation/modules/selector#nest", + "#selector_parse-instance_method": "/documentation/modules/selector#parse", + "#selector_replace-instance_method": "/documentation/modules/selector#replace", + "#selector_unify-instance_method": "/documentation/modules/selector#unify", + "#set-instance_method": "/documentation/modules/list#set", + "#simple_selectors-instance_method": "/documentation/modules/selector#simple-selectors", + "#str_index-instance_method": "/documentation/modules/string#index", + "#str_insert-instance_method": "/documentation/modules/string#insert", + "#str_length-instance_method": "/documentation/modules/string#length", + "#str_slice-instance_method": "/documentation/modules/string#slice", + "#to_lower_case-instance_method": "/documentation/modules/string#to-lower-case", + "#to_upper_case-instance_method": "/documentation/modules/string#to-upper-case", + "#transparentize-instance_method": "/documentation/modules/color#transparentize", + "#type_of-instance_method": "/documentation/modules/meta#type-of", + "#unique_id-instance_method": "/documentation/modules/string#unique-id", + "#unit-instance_method": "/documentation/modules/math#unit", + "#unitless-instance_method": "/documentation/modules/math#is-unitless", + "#unquote-instance_method": "/documentation/modules/string#unquote", + "#variable_exists-instance_method": "/documentation/modules/meta#variable-exists", + "#zip-instance_method": "/documentation/modules/list#zip" + }; + + var redirect = redirects[window.location.hash]; + if (redirect) window.location.href = redirect; + } else if (window.location.pathname == "/documentation/modules/color") { + var redirects = { + "#rgb": "/documentation/modules#rgb", + "#rgba": "/documentation/modules#rgba", + "#hsl": "/documentation/modules#hsl", + "#hsla": "/documentation/modules#hsla" + }; + + var redirect = redirects[window.location.hash]; + if (redirect) window.location.href = redirect; + } else if (window.location.pathname == "/documentation/modules/map") { + var redirects = { + "#keywords": "/documentation/modules/meta#keywords" }; var redirect = redirects[window.location.hash]; diff --git a/source/code-snippets/_example-advanced-nesting.html.md.erb b/source/code-snippets/_example-advanced-nesting.html.md.erb index 0b483fa37..1b952348d 100644 --- a/source/code-snippets/_example-advanced-nesting.html.md.erb +++ b/source/code-snippets/_example-advanced-nesting.html.md.erb @@ -1,12 +1,14 @@ For example, suppose you want to write a selector that matches the outer selector *and* an element selector. You could write a mixin like this one that -uses the [`selector-unify()` function][] to combine `&` with a user's selector. +uses the [`selector.unify()` function][] to combine `&` with a user's selector. -[`selector-unify()` function]: ../functions/selector#selector-unify +[`selector.unify()` function]: ../modules/selector#unify <% example do %> + @use "sass:selector"; + @mixin unify-parent($child) { - @at-root #{selector-unify(&, $child)} { + @at-root #{selector.unify(&, $child)} { @content; } } @@ -20,8 +22,10 @@ uses the [`selector-unify()` function][] to combine `&` with a user's selector. } } === + @use "sass:selector"; + @mixin unify-parent($child) - @at-root #{selector-unify(&, $child)} + @at-root #{selector.unify(&, $child)} @content @@ -32,4 +36,12 @@ uses the [`selector-unify()` function][] to combine `&` with a user's selector. @include unify-parent("select") /* ... + === + .wrapper input.field { + /* ... */ + } + + .wrapper select.field { + /* ... */ + } <% end %> diff --git a/source/code-snippets/_example-first-class-function.html.erb b/source/code-snippets/_example-first-class-function.html.erb index ebcefe309..1b0a4490e 100644 --- a/source/code-snippets/_example-first-class-function.html.erb +++ b/source/code-snippets/_example-first-class-function.html.erb @@ -1,14 +1,18 @@ <%# TODO(nweiz): auto-generate this CSS once we're compiling with Dart Sass %> <% example do %> + @use "sass:list"; + @use "sass:meta"; + @use "sass:string"; + /// Return a copy of $list with all elements for which $condition returns `true` /// removed. @function remove-where($list, $condition) { $new-list: (); - $separator: list-separator($list); + $separator: list.separator($list); @each $element in $list { - @if not call($condition, $element) { - $new-list: append($new-list, $element, $separator: $separator); + @if not meta.call($condition, $element) { + $new-list: list.append($new-list, $element, $separator: $separator); } } @return $new-list; @@ -18,19 +22,23 @@ content { @function contains-helvetica($string) { - @return str-index($string, "Helvetica"); + @return string.index($string, "Helvetica"); } - font-family: remove-where($fonts, get-function("contains-helvetica")); + font-family: remove-where($fonts, meta.get-function("contains-helvetica")); } === + @use "sass:list" + @use "sass:meta" + @use "sass:string" + /// Return a copy of $list with all elements for which $condition returns `true` /// removed. @function remove-where($list, $condition) $new-list: () - $separator: list-separator($list) + $separator: list.separator($list) @each $element in $list - @if not call($condition, $element) - $new-list: append($new-list, $element, $separator: $separator) + @if not meta.call($condition, $element) + $new-list: list.append($new-list, $element, $separator: $separator) @return $new-list @@ -40,9 +48,9 @@ content @function contains-helvetica($string) - @return str-index($string, "Helvetica") + @return string.index($string, "Helvetica") - font-family: remove-where($fonts, get-function("contains-helvetica")) + font-family: remove-where($fonts, meta.get-function("contains-helvetica")) === content { font-family: Tahoma, Geneva, Arial, sans-serif; diff --git a/source/code-snippets/_example-list-index.html.erb b/source/code-snippets/_example-list-index.html.erb index 9b1eba809..99d511536 100644 --- a/source/code-snippets/_example-list-index.html.erb +++ b/source/code-snippets/_example-list-index.html.erb @@ -1,9 +1,9 @@ <% example(autogen_css: false) do %> - @debug index(1px solid red, 1px); // 1 - @debug index(1px solid red, solid); // 2 - @debug index(1px solid red, dashed); // null + @debug list.index(1px solid red, 1px); // 1 + @debug list.index(1px solid red, solid); // 2 + @debug list.index(1px solid red, dashed); // null === - @debug index(1px solid red, 1px) // 1 - @debug index(1px solid red, solid) // 2 - @debug index(1px solid red, dashed) // null + @debug list.index(1px solid red, 1px) // 1 + @debug list.index(1px solid red, solid) // 2 + @debug list.index(1px solid red, dashed) // null <% end %> diff --git a/source/code-snippets/_example-list-nth.html.erb b/source/code-snippets/_example-list-nth.html.erb index 2b8ce0bbc..535a7f5c0 100644 --- a/source/code-snippets/_example-list-nth.html.erb +++ b/source/code-snippets/_example-list-nth.html.erb @@ -1,7 +1,7 @@ <% example(autogen_css: false) do %> - @debug nth(10px 12px 16px, 2); // 12px - @debug nth([line1, line2, line3], -1); // line3 + @debug list.nth(10px 12px 16px, 2); // 12px + @debug list.nth([line1, line2, line3], -1); // line3 === - @debug nth(10px 12px 16px, 2) // 12px - @debug nth([line1, line2, line3], -1) // line3 + @debug list.nth(10px 12px 16px, 2) // 12px + @debug list.nth([line1, line2, line3], -1) // line3 <% end %> diff --git a/source/code-snippets/_example-map-get.html.erb b/source/code-snippets/_example-map-get.html.erb index 062d80380..58d887818 100644 --- a/source/code-snippets/_example-map-get.html.erb +++ b/source/code-snippets/_example-map-get.html.erb @@ -1,11 +1,11 @@ <% example(autogen_css: false) do %> $font-weights: ("regular": 400, "medium": 500, "bold": 700); - @debug map-get($font-weights, "medium"); // 500 - @debug map-get($font-weights, "extra-bold"); // null + @debug map.get($font-weights, "medium"); // 500 + @debug map.get($font-weights, "extra-bold"); // null === $font-weights: ("regular": 400, "medium": 500, "bold": 700) - @debug map-get($font-weights, "medium") // 500 - @debug map-get($font-weights, "extra-bold") // null + @debug map.get($font-weights, "medium") // 500 + @debug map.get($font-weights, "extra-bold") // null <% end %> diff --git a/source/code-snippets/_example-mixin-arbitrary-keyword-arguments.html.erb b/source/code-snippets/_example-mixin-arbitrary-keyword-arguments.html.erb index d5bce7938..d81303c83 100644 --- a/source/code-snippets/_example-mixin-arbitrary-keyword-arguments.html.erb +++ b/source/code-snippets/_example-mixin-arbitrary-keyword-arguments.html.erb @@ -1,8 +1,11 @@ <% example do %> + @use "sass:meta"; + @mixin syntax-colors($args...) { - @debug keywords($args); // (string: #080, comment: #800, $variable: $60b) + @debug meta.keywords($args); + // (string: #080, comment: #800, $variable: $60b) - @each $name, $color in keywords($args) { + @each $name, $color in meta.keywords($args) { pre span.stx-#{$name} { color: $color; } @@ -15,17 +18,20 @@ $variable: #60b, ) === + @use "sass:meta" + @mixin syntax-colors($args...) - @debug keywords($args) // (string: #080, comment: #800, $variable: $60b) + @debug meta.keywords($args) + // (string: #080, comment: #800, $variable: $60b) - @each $name, $color in keywords($args) + @each $name, $color in meta.keywords($args) pre span.stx-#{$name} color: $color - @include syntax-colors($string: #080, $comment: #800, $variable: #60b); + @include syntax-colors($string: #080, $comment: #800, $variable: #60b) === pre span.stx-string { color: #080; diff --git a/source/code-snippets/_example-module-migrator.html.md.erb b/source/code-snippets/_example-module-migrator.html.md.erb new file mode 100644 index 000000000..02b7a5f84 --- /dev/null +++ b/source/code-snippets/_example-module-migrator.html.md.erb @@ -0,0 +1,25 @@ +```shellsession +$ cat style.scss +$body-bg: #000; +$body-color: #111; + +@import "bootstrap"; + +@include media-breakpoint-up(sm) { + .navbar { + display: block; + } +} +$ sass-migrator --migrate-deps module style.scss +$ cat style.scss +@use "bootstrap" with ( + $body-bg: #000, + $body-color: #111 +); + +@include bootstrap.media-breakpoint-up(sm) { + .navbar { + display: block; + } +} +``` diff --git a/source/code-snippets/_example-use-with.html.erb b/source/code-snippets/_example-use-with.html.erb new file mode 100644 index 000000000..20cac3d3d --- /dev/null +++ b/source/code-snippets/_example-use-with.html.erb @@ -0,0 +1,34 @@ +<% example do %> + // _library.scss + $black: #000 !default; + $border-radius: 0.25rem !default; + $box-shadow: 0 0.5rem 1rem rgba($black, 0.15) !default; + + code { + border-radius: $border-radius; + box-shadow: $box-shadow; + } + --- + // style.scss + @use 'library' with ( + $black: #222, + $border-radius: 0.1rem + ); + === + // _library.sass + $black: #000 !default + $border-radius: 0.25rem !default + $box-shadow: 0 0.5rem 1rem rgba($black, 0.15) !default + + code + border-radius: $border-radius + box-shadow: $box-shadow + --- + // style.sass + @use 'library' with ($black: #222, $border-radius: 0.1rem) + === + code { + border-radius: 0.1rem; + box-shadow: 0 0.5rem 1rem rgba(#222, 0.15); + } +<% end %> diff --git a/source/documentation/at-rules/at-root.html.md.erb b/source/documentation/at-rules/at-root.html.md.erb index a9df05b1c..c1b1f16c9 100644 --- a/source/documentation/at-rules/at-root.html.md.erb +++ b/source/documentation/at-rules/at-root.html.md.erb @@ -6,7 +6,7 @@ introduction: > of using the normal nesting. It's most often used when doing [advanced nesting](../style-rules/parent-selector#advanced-nesting) with the [SassScript parent selector](../style-rules/parent-selector#in-sassscript) and [selector - functions](../functions/selector). + functions](../modules/selector). --- <%= partial 'code-snippets/example-advanced-nesting' %> diff --git a/source/documentation/at-rules/debug.html.md.erb b/source/documentation/at-rules/debug.html.md.erb index 9f1072205..acc4abc43 100644 --- a/source/documentation/at-rules/debug.html.md.erb +++ b/source/documentation/at-rules/debug.html.md.erb @@ -34,7 +34,7 @@ test.scss:3 Debug: divider offset: 132px <% fun_fact do %> You can pass any value to `@debug`, not just a string! It prints the same - representation of that value as the [`inspect()` function][]. + representation of that value as the [`meta.inspect()` function][]. - [`inspect()` function]: ../functions/meta#inspect + [`meta.inspect()` function]: ../modules/meta#inspect <% end %> diff --git a/source/documentation/at-rules/extend.html.md.erb b/source/documentation/at-rules/extend.html.md.erb index c15cc4338..6f457f324 100644 --- a/source/documentation/at-rules/extend.html.md.erb +++ b/source/documentation/at-rules/extend.html.md.erb @@ -168,13 +168,13 @@ unification*: <% fun_fact do %> You can directly access Sass's intelligent unification using [selector - functions][]! The [`selector-unify()` function][] returns a selector that - matches the intersection of two selectors, while the [`selector-extend()` + functions][]! The [`selector.unify()` function][] returns a selector that + matches the intersection of two selectors, while the [`selector.extend()` function][] works just like `@extend`, but on a single selector. - [selector functions]: ../functions/selector - [`selector-unify()` function]: ../functions/selector#selector-unify - [`selector-extend()` function]: ../functions/selector#selector-extend + [selector functions]: ../modules/selector + [`selector.unify()` function]: ../modules/selector#unify + [`selector.extend()` function]: ../modules/selector#extend <% end %> <% heads_up do %> @@ -199,6 +199,36 @@ are. <%= partial "code-snippets/example-placeholder" %> +### Private Placeholders + +Like [module members][], a placeholder selector can be marked private by +starting its name with either `-` or `_`. A private placeholder selector can +only be extended within the stylesheet that defines it. To any other +stylesheets, it will look as though that selector doesn't exist. + +[module members]: use#private-members + +## Extension Scope + +When one stylesheet extends a selector, that extension will only affect style +rules written in *upstream* modules—that is, modules that are loaded by that +stylesheet using the [`@use` rule][] or the [`@forward` rule][], modules loaded +by *those* modules, and so on. This helps make your `@extend` rules more +predictable, ensuring that they affect only the styles you were aware of when +you wrote them. + +[`@use` rule]: use +[`@forward` rule]: forward + +<% heads_up do %> + Extensions aren't scoped at all if you're using the [`@import` rule][]. Not + only will they affect every stylesheet you import, they'll affect every + stylesheet that imports your stylesheet, everything else those stylesheets + import, and so on. Without `@use`, extensions are *global*. + + [`@import` rule]: import +<% end %> + ## Mandatory and Optional Extends Normally, if an `@extend` doesn't match any selectors in the stylesheet, Sass diff --git a/source/documentation/at-rules/forward.html.md.erb b/source/documentation/at-rules/forward.html.md.erb new file mode 100644 index 000000000..c0804c4e6 --- /dev/null +++ b/source/documentation/at-rules/forward.html.md.erb @@ -0,0 +1,181 @@ +--- +title: "@forward" +introduction: > + The `@forward` rule loads a Sass stylesheet and makes its [mixins](mixin), + [functions](function), and [variables](../variables) available when your + stylesheet is loaded with the [`@use` rule](use). It makes it possible to + organize Sass libraries across many files, while allowing their users to load + a single entrypoint file. +--- + +The rule is written `@forward ""`. It loads the module at the given URL +just like `@use`, but it makes the [public][] members of the loaded module +available to users of your module as though they were defined directly in your +module. Those members aren't available in your module, though—if you want that, +you'll need to write a `@use` rule as well. Don't worry, it'll only load the +module once! + +[public]: use#private-members + +<% fun_fact do %> + The `@forward` rule acts just like `@use` when it comes to a module's CSS. + Styles from a forwarded module will be included in the compiled CSS output, + and the module with the `@forward` can [extend][] it, even if it isn't also + `@use`d. + + [extend]: extend +<% end %> + +<% example do %> + // src/_list.scss + @mixin list-reset { + margin: 0; + padding: 0; + list-style: none; + } + --- + // bootstrap.scss + @forward "src/list"; + --- + // styles.scss + @use "bootstrap"; + + li { + @include bootstrap.list-reset; + } + === + // src/_list.sass + @mixin list-reset + margin: 0 + padding: 0 + list-style: none + --- + // bootstrap.sass + @forward "src/list" + --- + // styles.sass + @use "bootstrap" + + li + @include bootstrap.list-reset + === + li { + margin: 0; + padding: 0; + list-style: none; + } +<% end %> + +## Adding a Prefix + +Because module members are usually used with [a namespace][], short and simple +names are usually the most readable option. But those names might not make sense +outside the module they're defined in, so `@forward` has the option of adding an +extra prefix to all the members it forwards. + +This is written `@forward "" as -*`, and it adds the given prefix +to the beginning of every mixin, function, and variable name forwarded by the +module. For example, if the module defines a member named `reset` and it's +forwarded `as list-*`, downstream stylesheets will refer to it as `list-reset`. + +[a namespace]: use#loading-members + +<% example do %> + // src/_list.scss + @mixin reset { + margin: 0; + padding: 0; + list-style: none; + } + --- + // bootstrap.scss + @forward "src/list" as list-*; + --- + // styles.scss + @use "bootstrap"; + + li { + @include bootstrap.list-reset; + } + === + // src/_list.sass + @mixin reset + margin: 0 + padding: 0 + list-style: none + --- + // bootstrap.sass + @forward "src/list" as list-* + --- + // styles.sass + @use "bootstrap" + + li + @include bootstrap.list-reset + === + li { + margin: 0; + padding: 0; + list-style: none; + } +<% end %> + +## Controlling Visibility + +Sometimes, you don't want to forward *every* member from a module. You may want +to keep some members private so that only your package can use them, or you may +want to require your users to load some members a different way. You can control +exactly which members get forwarded by writing `@forward "" hide +` or `@forward "" show `. + +The `hide` form means that the listed members shouldn't be forwarded, but +everything else should. The `show` form means that *only* the named members +should be forwarded. In both forms, you list the names of mixins, functions, or +variables (including the `$`). + +<% example(autogen_css: false) do %> + // src/_list.scss + $horizontal-list-gap: 2em; + + @mixin list-reset { + margin: 0; + padding: 0; + list-style: none; + } + + @mixin list-horizontal { + @include reset; + + li { + display: inline-block; + margin: { + left: -2px; + right: $horizontal-list-gap; + } + } + } + --- + // bootstrap.scss + @forward "src/list" hide list-reset, $horizontal-list-gap; + === + // src/_list.sass + $horizontal-list-gap: 2em + + @mixin list-reset + margin: 0 + padding: 0 + list-style: none + + + @mixin list-horizontal + @include reset + + li + display: inline-block + margin: + left: -2px + right: $horizontal-list-gap + --- + // bootstrap.sass + @forward "src/list" hide list-reset, $horizontal-list-gap +<% end %> diff --git a/source/documentation/at-rules/function.html.md.erb b/source/documentation/at-rules/function.html.md.erb index 33b5da620..d8b5de665 100644 --- a/source/documentation/at-rules/function.html.md.erb +++ b/source/documentation/at-rules/function.html.md.erb @@ -190,20 +190,20 @@ argument is known as an [argument list][]. #### Taking Arbitrary Keyword Arguments Argument lists can also be used to take arbitrary keyword arguments. The -[`keywords()` function][] takes an argument list and returns any extra keywords -that were passed to the function as a [map][] from argument names (not including -`$`) to those arguments' values. +[`meta.keywords()` function][] takes an argument list and returns any extra +keywords that were passed to the function as a [map][] from argument names (not +including `$`) to those arguments' values. -[`keywords()` function]: ../functions/map#keywords +[`meta.keywords()` function]: ../modules/meta#keywords [map]: ../values/maps <% fun_fact do %> - If you don't ever pass an argument list to the [`keywords()` function][], that - argument list won't allow extra keyword arguments. This helps callers of your - function make sure they haven't accidentally written any typos in their - argument names. + If you don't ever pass an argument list to the [`meta.keywords()` function][], + that argument list won't allow extra keyword arguments. This helps callers of + your function make sure they haven't accidentally misspelled any argument + names. - [`keywords()` function]: ../functions/map#keywords + [`meta.keywords()` function]: ../modules/meta#keywords <% end %> #### Passing Arbitrary Arguments @@ -258,26 +258,30 @@ an [`@else` block][]. [`@else` block]: control/if#else -<% example do %> +<% example(autogen_css: false) do %> + @use "sass:string"; + @function str-insert($string, $insert, $index) { // Avoid making new strings if we don't need to. - @if str-length($string) == 0 { + @if string.length($string) == 0 { @return $insert; } - $before: str-slice($string, 0, $index); - $after: str-slice($string, $index); + $before: string.slice($string, 0, $index); + $after: string.slice($string, $index); @return $before + $insert + $after; } === + @use "sass:string" + @function str-insert($string, $insert, $index) // Avoid making new strings if we don't need to. - @if str-length($string) == 0 + @if string.length($string) == 0 @return $insert - $before: str-slice($string, 0, $index) - $after: str-slice($string, $index) + $before: string.slice($string, 0, $index) + $after: string.slice($string, $index) @return $before + $insert + $after <% end %> @@ -289,7 +293,45 @@ implementations also make it possible to define [custom functions][] in the host language. And of course, you can always call [plain CSS functions][] (even ones with [weird syntax][]). -[core library]: ../functions +[core library]: ../modules [custom functions]: ../js-api#functions -[plain CSS functions]: ../functions/css +[plain CSS functions]: #plain-css-functions [weird syntax]: ../syntax/special-functions + +### Plain CSS Functions + +Any function call that's not either a user-defined or [built-in](../modules) +function is compiled to a plain CSS function (unless it uses [Sass argument +syntax](../at-rules/function#arguments)). The arguments will be compiled to CSS +and included as-is in the function call. This ensures that Sass supports all CSS +functions without needing to release new versions every time a new one is added. + +<% example(autogen_css: false) do %> + @debug var(--main-bg-color); // var(--main-bg-color) + + $primary: #f2ece4; + $accent: #e1d7d2; + @debug radial-gradient($primary, $accent); // radial-gradient(#f2ece4, #e1d7d2) + === + @debug var(--main-bg-color) // var(--main-bg-color) + + $primary: #f2ece4 + $accent: #e1d7d2 + @debug radial-gradient($primary, $accent) // radial-gradient(#f2ece4, #e1d7d2) +<% end %> + +<% heads_up do %> + Because any unknown function will be compiled to CSS, it's easy to miss when + you typo a function name. Consider running a [CSS linter][] on your + stylesheet's output to be notified when this happens! + + [CSS linter]: https://stylelint.io/ +<% end %> + +<% fun_fact do %> + Some CSS functions, like `calc()` and `element()` have unusual syntax. Sass + [parses these functions specially][] as [unquoted strings][]. + + [parses these functions specially]: ../syntax/special-functions + [unquoted strings]: ../values/strings#unquoted +<% end %> diff --git a/source/documentation/at-rules/import.html.md.erb b/source/documentation/at-rules/import.html.md.erb index 542addc1c..0b02f75ab 100644 --- a/source/documentation/at-rules/import.html.md.erb +++ b/source/documentation/at-rules/import.html.md.erb @@ -18,6 +18,48 @@ required to have quotes. [indented syntax]: ../syntax#the-indented-syntax +<% heads_up do %> + The Sass team discourages the continued use of the `@import` rule. Sass will + [gradually phase it out][] over the next few years, and eventually remove it + from the language entirely. Prefer the [`@use` rule][] instead. + + [gradually phase it out]: https://github.com/sass/sass/blob/master/accepted/module-system.md#timeline + [`@use` rule]: use + + #### What's Wrong With `@import`? + + The `@import` rule has a number of serious issues: + + * `@import` makes all variables, mixins, and functions globally accessible. + This makes it very difficult for people (or tools) to tell where anything is + defined. + + * Because everything's global, libraries must prefix to all their members to + avoid naming collisions. + + * [`@extend` rules][] are also global, which makes it difficult to predict + which style rules will be extended. + + [`@extend` rules]: extend + + * Each stylesheet is executed and its CSS emitted *every time* it's + `@import`ed, which increases compilation time and produces bloated output. + + * There was no way to define private members or placeholder selectors that + were inaccessible to downstream stylesheets. + + The new module system and the `@use` rule address all these problems. + + #### How Do I Migrate? + + We've written a [migration tool][] that automatically converts most + `@import`-based code to `@use`-based code in a flash. Just point it at your + entrypoints and let it run! + + [migration tool]: /documentation/cli/migrator + +<% end %> + <% example do %> // foundation/_code.scss code { @@ -414,3 +456,89 @@ for example based on mixin parameters. @include google-font("Droid Sans") <% end %> + +## Import and Modules + +<%= partial '../snippets/module-system-status' %> + +Sass's [module system][] integrates seamlessly with `@import`, whether you're +importing a file that contains `@use` rules or loading a file that contains +imports as a module. We want to make the transition from `@import` to `@use` as +smooth as possible. + +[module system]: use + +### Importing a Module-System File + +When you import a file that contains `@use` rules, the importing file has access +to all members (even private members) defined directly in that file, but *not* +any members from modules that file has loaded. However, if that file contains +[`@forward` rules][], the importing file will have access to forwarded members. +This means that you can import a library that was written to be used with the +module system. + +[`@forward` rules]: forward + +<% heads_up do %> + When a file with `@use` rules is imported, all the CSS transitively loaded by + those is included in the resulting stylesheet, even if it's already been + included by another import. If you're not careful, this can result in bloated + CSS output! +<% end %> + +#### Import-Only Files + +An API that makes sense for `@use` might not make sense for `@import`. For +example, `@use` adds a namespace to all members by default so you can safely use +short names, but `@import` doesn't so you might need something longer. If you're +a library author, you may be concerned that if you update your library to use +the new module system, your existing `@import`-based users will break. + +To make this easier, Sass also supports *import-only files*. If you name a file +`.import.scss`, it will only be loaded for imports, not for `@use`s. This +way, you can retain compatibility for `@import` users while still providing a +nice API for users of the new module system. + +<% example(autogen_css: false) do %> + // _reset.scss + + // Module system users write `@include reset.list()`. + @mixin list() { + ul { + margin: 0; + padding: 0; + list-style: none; + } + } + --- + // _reset.import.scss + + // Legacy import users can keep writing `@include reset-list()`. + @forward "reset" as reset-*; + === + // _reset.sass + + // Module system users write `@include reset.list()`. + @mixin list() + ul + margin: 0 + padding: 0 + list-style: none + --- + // _reset.import.sass + + // Legacy import users can keep writing `@include reset-list()`. + @forward "reset" as reset-* +<% end %> + +### Loading a Module That Contains Imports + +When you use `@use` (or `@forward`) load a module that uses `@import`, that +module will contain all the public members defined by the stylesheet you load +*and* everything that stylesheet transitively imports. In other words, +everything that's imported is treated as though it were written in one big +stylesheet. + +This makes it easy to convert start using `@use` in a stylesheet even before all +the libraries you depend on have converted to the new module system. Be aware, +though, that if they do convert their APIs may well change! diff --git a/source/documentation/at-rules/mixin.html.md.erb b/source/documentation/at-rules/mixin.html.md.erb index 40f35438a..42cb1d6a5 100644 --- a/source/documentation/at-rules/mixin.html.md.erb +++ b/source/documentation/at-rules/mixin.html.md.erb @@ -256,11 +256,11 @@ is known as an [argument list][]. #### Taking Arbitrary Keyword Arguments Argument lists can also be used to take arbitrary keyword arguments. The -[`keywords()` function][] takes an argument list and returns any extra keywords -that were passed to the mixin as a [map][] from argument names (not including -`$`) to those arguments' values. +[`meta.keywords()` function][] takes an argument list and returns any extra +keywords that were passed to the mixin as a [map][] from argument names (not +including `$`) to those arguments' values. -[`keywords()` function]: ../functions/map#keywords +[`meta.keywords()` function]: ../modules/meta#keywords [map]: ../values/maps <%# TODO(nweiz): auto-generate this CSS once we're compiling with Dart Sass %> @@ -268,12 +268,12 @@ that were passed to the mixin as a [map][] from argument names (not including <%= partial 'code-snippets/example-mixin-arbitrary-keyword-arguments' %> <% fun_fact do %> - If you don't ever pass an argument list to the [`keywords()` function][], that - argument list won't allow extra keyword arguments. This helps callers of your - mixin make sure they haven't accidentally written any typos in their argument + If you don't ever pass an argument list to the [`meta.keywords()` function][], + that argument list won't allow extra keyword arguments. This helps callers of + your mixin make sure they haven't accidentally misspelled any argument names. - [`keywords()` function]: ../functions/map#keywords + [`meta.keywords()` function]: ../modules/meta#keywords <% end %> #### Passing Arbitrary Arguments diff --git a/source/documentation/at-rules/use.html.md.erb b/source/documentation/at-rules/use.html.md.erb new file mode 100644 index 000000000..d9d703143 --- /dev/null +++ b/source/documentation/at-rules/use.html.md.erb @@ -0,0 +1,431 @@ +--- +title: "@use" +table_of_contents: true +introduction: > + The `@use` rule loads [mixins](mixin), [functions](function), and + [variables](../variables) from other Sass stylesheets, and combines CSS from + multiple stylesheets together. Stylesheets loaded by `@use` are called + "modules". Sass also provides [built-in modules](../modules) full of useful + functions. +--- + +<% content_for :before_introduction do %> + <%= partial '../snippets/module-system-status' %> +<% end %> + +The simplest `@use` rule is written `@use ""`, which loads the module at +the given URL. Any styles loaded this way will be included exactly once in the +compiled CSS output, no matter how many times those styles are loaded. + +<% heads_up do %> + A stylesheet's `@use` rules must come before any rules other than `@forward`, + including [style rules][]. However, you can declare variables before `@use` + rules to use when [configuring modules][]. + + [style rules]: ../style-rules + [configuring modules]: #configuring-modules +<% end %> + +<% example do %> + // foundation/_code.scss + code { + padding: .25em; + line-height: 0; + } + --- + // foundation/_lists.scss + ul, ol { + text-align: left; + + & & { + padding: { + bottom: 0; + left: 0; + } + } + } + --- + // style.scss + @use 'foundation/code'; + @use 'foundation/lists'; + === + // foundation/_code.sass + code + padding: .25em + line-height: 0 + --- + // foundation/_lists.sass + ul, ol + text-align: left + + & & + padding: + bottom: 0 + left: 0 + --- + // style.sass + @use 'foundation/code' + @use 'foundation/lists' + === + code { + padding: .25em; + line-height: 0; + } + + ul, ol { + text-align: left; + } + ul ul, ol ol { + padding-bottom: 0; + padding-left: 0; + } +<% end %> + +## Loading Members + +You can access variables, functions, and mixins from another module by writing +`.`, `.()`, or `@include +.()`. By default, the namespace is just the last component of +the module's URL. + +Members (variables, functions, and mixins) loaded with `@use` are only visible +in the stylesheet that loads them. Other stylesheets will need to write their +own `@use` rules if they also want to access them. This helps make it easy to +figure out exactly where each member is coming from. If you want to load members +from many files at once, you can use the [`@forward` rule][] to forward them all +from one shared file. + +[`@forward` rule]: forward + +<% fun_fact do %> + Because `@use` adds namespaces to member names, it's safe to choose very + simple names like `$radius` or `$width` when writing a stylesheet. This is + different from the old [`@import` rule][], which encouraged that users write + long names like `$mat-corner-radius` to avoid conflicts with other + libraries, and it helps keep your stylesheets clear and easy to read! + + [`@import` rule]: import +<% end %> + +<% example do %> + // src/_corners.scss + $radius: 3px; + + @mixin rounded { + border-radius: $radius; + } + --- + // style.scss + @use "src/corners"; + + .button { + @include corners.rounded; + padding: 5px + corners.$radius; + } + === + // src/_corners.sass + $radius: 5px + + @mixin rounded + border-radius: $radius + --- + // style.sass + @use "src/corners" + + .button + @include corners.rounded + padding: 5px + corners.$radius + === + .button { + border-radius: 3px; + padding: 8px; + } +<% end %> + +### Choosing a Namespace + +By default, a module's namespace is just the last component of its URL without a +file extension. However, sometimes you might want to choose a different +namespace—you might want to use a shorter name for a module you refer to a lot, +or you might be loading multiple modules with the same filename. You can do this +by writine `@use "" as `. + +<% example do %> + // src/_corners.scss + $radius: 3px; + + @mixin rounded { + border-radius: $radius; + } + --- + // style.scss + @use "src/corners" as c; + + .button { + @include c.rounded; + padding: 5px + c.$radius; + } + === + // src/_corners.sass + $radius: 5px + + @mixin rounded + border-radius: $radius + --- + // style.sass + @use "src/corners" as c + + .button + @include c.rounded + padding: 5px + c.$radius + === + .button { + border-radius: 3px; + padding: 8px; + } +<% end %> + +You can even load a module *without* a namespace by writing `@use "" as *`. +We recommend you only do this for stylesheets written by you, though; otherwise, +they may introduce new members that cause name conflicts! + +<% example do %> + // src/_corners.scss + $radius: 3px; + + @mixin rounded { + border-radius: $radius; + } + --- + // style.scss + @use "src/corners" as *; + + .button { + @include rounded; + padding: 5px + $radius; + } + === + // src/_corners.sass + $radius: 5px + + @mixin rounded + border-radius: $radius + --- + // style.sass + @use "src/corners" as * + + .button + @include rounded + padding: 5px + $radius + === + .button { + border-radius: 3px; + padding: 8px; + } +<% end %> + +### Private Members + +As a stylesheet author, you may not want all the members you define to be +available outside your stylesheet. Sass makes it easy to define a private member +by starting its name with either `-` or `_`. These members will work just like +normal within the stylesheet that defines them, but they won't be part of a +module's public API. That means stylesheets that load your module can't see +them! + +<% fun_fact do %> + If you want to make a member private to an entire *package* rather than just a + single module, just don't [forward its module][] from any of your package's + entrypoints (the stylesheets you tell your users to load to use your package). + You can even [hide that member][] while forwarding the rest of its module! + + [forward its module]: forward + [hide that member]: forward#controlling-visibility +<% end %> + +<% example(autogen_css: false) do %> + // src/_corners.scss + $-radius: 3px; + + @mixin rounded { + border-radius: $-radius; + } + --- + // style.scss + @use "src/corners"; + + .button { + @include corners.rounded; + + // This is an error! $-radius isn't visible outside of `_corners.scss`. + padding: 5px + corners.$-radius; + } + === + // src/_corners.sass + $-radius: 5px + + @mixin rounded + border-radius: $radius + --- + // style.sass + @use "src/corners" + + .button + @include corners.rounded + + // This is an error! $-radius isn't visible outside of `_corners.scss`. + padding: 5px + corners.$-radius +<% end %> + +## Configuring Modules + +A stylesheet can define variables with the [`!default` flag][] to make them +configurable. To load a module with configuration, write `@use with +(: , : )`. The configured values will override +the variables' default values. + +[`!default` flag]: ../variables#default-values + +<%= partial '../../code-snippets/example-use-with' %> + +## Finding the Module + +It wouldn't be any fun to write out absolute URLs for every stylesheet you load, +so Sass's algorithm for finding a module makes it a little easier. For starters, +you don't have to explicitly write out the extension of the file you want to +load; `@use "variables"` will automatically load `variables.scss`, +`variables.sass`, or `variables.css`. + +<% heads_up do %> + To ensure that stylesheets work on every operating system, Sass loads files by + *URL*, not by *file path*. This means you need to use forward slashes, not + backslashes, even on Windows. +<% end %> + +### Load Paths + +All Sass implementations allow users to provide *load paths*: paths on the +filesystem that Sass will look in when locating modules. For example, if you +pass `node_modules/susy/sass` as a load path, you can use `@use "susy"` to load +`node_modules/susy/sass/susy.scss`. + +Modules will always be loaded relative to the current file first, though. Load +paths will only be used if no relative file exists that matches the module's +URL. This ensures that you can't accidentally mess up your relative imports when +you add a new library. + +<% fun_fact do %> + Unlike some other languages, Sass doesn't require that you use `./` for + relative imports. Relative imports are always available. +<% end %> + +### Partials + +As a convention, Sass files that are only meant to be loaded as modules, not +compiled on their own, begin with `_` (as in `_code.scss`). These are called +*partials*, and they tell Sass tools not to try to compile those files on their +own. You can leave off the `_` when importing a partial. + +### Index Files + +If you write an `_index.scss` or `_index.sass` in a folder, the index file will +be loaded automatically. when you load the URL for the folder itself. + +<% example do %> + // foundation/_code.scss + code { + padding: .25em; + line-height: 0; + } + --- + // foundation/_lists.scss + ul, ol { + text-align: left; + + & & { + padding: { + bottom: 0; + left: 0; + } + } + } + --- + // foundation/_index.scss + @use 'code'; + @use 'lists'; + --- + // style.scss + @use 'foundation'; + === + // foundation/_code.sass + code + padding: .25em + line-height: 0 + --- + // foundation/_lists.sass + ul, ol + text-align: left + + & & + padding: + bottom: 0 + left: 0 + --- + // foundation/_index.sass + @use 'code' + @use 'lists' + --- + // style.sass + @use 'foundation' + === + code { + padding: .25em; + line-height: 0; + } + + ul, ol { + text-align: left; + } + ul ul, ol ol { + padding-bottom: 0; + padding-left: 0; + } +<% end %> + +## Loading CSS + +In addition to loading `.sass` and `.scss` files, Sass can load plain old `.css` +files. + +<% example do %> + // code.css + code { + padding: .25em; + line-height: 0; + } + --- + // style.scss + @use 'code'; + === + // code.css + code { + padding: .25em; + line-height: 0; + } + --- + // style.sass + @use 'code' + === + code { + padding: .25em; + line-height: 0; + } +<% end %> + +CSS files loaded as modules don't allow any special Sass features and so can't +expose any Sass variables, functions, or mixins. In order to make sure authors +don't accidentally write Sass in their CSS, all Sass features that aren't also +valid CSS will produce errors. Otherwise, the CSS will be rendered as-is. It can +even be [extended][]! + +[extended]: extend diff --git a/source/documentation/breaking-changes/css-vars.html.md.erb b/source/documentation/breaking-changes/css-vars.html.md.erb index f88a8a353..0b119402d 100644 --- a/source/documentation/breaking-changes/css-vars.html.md.erb +++ b/source/documentation/breaking-changes/css-vars.html.md.erb @@ -70,21 +70,29 @@ versions, and so is recommended for all stylesheets. <% heads_up do %> Because interpolation removes quotation marks from quoted strings, it may be - necessary to wrap them in the [`inspect()` function][] to preserve their + necessary to wrap them in the [`meta.inspect()` function][] to preserve their quotes. - [`inspect()` function]: ../functions/meta#inspect + [`meta.inspect()` function]: ../modules/meta#inspect <% example do %> + @use "sass:meta"; + $font-family-monospace: Menlo, Consolas, "Courier New", monospace; :root { - --font-family-monospace: #{inspect($font-family-monospace)}; + --font-family-monospace: #{meta.inspect($font-family-monospace)}; } === + @use "sass:meta" + $font-family-monospace: Menlo, Consolas, "Courier New", monospace :root - --font-family-monospace: #{inspect($font-family-monospace)} + --font-family-monospace: #{meta.inspect($font-family-monospace)} + === + :root { + --font-family-monospace: Menlo, Consolas, "Courier New", monospace; + } <% end %> <% end %> diff --git a/source/documentation/breaking-changes/slash-div.html.md.erb b/source/documentation/breaking-changes/slash-div.html.md.erb index fabeba304..149e95959 100644 --- a/source/documentation/breaking-changes/slash-div.html.md.erb +++ b/source/documentation/breaking-changes/slash-div.html.md.erb @@ -19,21 +19,25 @@ use `/` as a separator, this is becoming more and more painful to Sass users. [CSS Grid]: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-row [new `rgb()` and `hsl()` syntax]: https://drafts.csswg.org/css-color/#rgb-functions -Because Sass is a CSS superset, it's redefining `/` to be *only* a separator. `/` -will be treated as a new type of list separator, similar to how `,` works today. -Division will instead be written using the new `divide()` function. This -function will behave exactly the same as `/` does today. +Because Sass is a CSS superset, it's redefining `/` to be *only* a separator. +`/` will be treated as a new type of list separator, similar to how `,` works +today. Division will instead be written using the new `math.div()` function. +This function will behave exactly the same as `/` does today. <% example do %> + @use "sass:math"; + // Future Sass, doesn't work yet! .item3 { - $row: span divide(6, 2) / 7; // A two-element slash-separated list. + $row: span math.div(6, 2) / 7; // A two-element slash-separated list. grid-row: $row; } === + @use "sass:math" + // Future Sass, doesn't work yet! .item3 - $row: span divide(6, 2) / 7 // A two-element slash-separated list. + $row: span math.div(6, 2) / 7 // A two-element slash-separated list. grid-row: $row === .item3 { @@ -43,34 +47,39 @@ function will behave exactly the same as `/` does today. ## Transition Period -<% impl_status dart: false, libsass: false, ruby: false, feature: "divide() and slash-list()" %> +<% impl_status dart: false, libsass: false, ruby: false, + feature: "math.div() and list.slash()" %> -To ease the transition, implementations will begin by adding the `divide()` +To ease the transition, implementations will begin by adding the `math.div()` function. The `/` operator will continue to do division, but it also prints a deprecation warning when it does so. Users should switch all division to use -`divide()` instead. +`math.div()` instead. <% example(autogen_css: false) do %> + @use "sass:math"; + // WRONG, will not work in future Sass versions. @debug (12px/4px); // 3 // RIGHT, will work in future Sass versions. - @debug divide(12px, 4px); // 3 + @debug math.div(12px, 4px); // 3 === + @use "sass:math" + // WRONG, will not work in future Sass versions. @debug (12px/4px) // 3 // RIGHT, will work in future Sass versions. - @debug divide(12px, 4px) // 3 + @debug math.div(12px, 4px) // 3 <% end %> Slash-separated lists will also be available in the transition period. Because -they can't be created with `/` yet, the `slash-list()` function will be added to +they can't be created with `/` yet, the `list.slash()` function will be added to create them. You will also be able to pass `"slash"` as the `$separator` to the -[`join()` function][] and the [`append()` function][]. +[`list.join()` function][] and the [`list.append()` function][]. -[`join()` function]: ../functions/list#join -[`append()` function]: ../functions/list#append +[`list.join()` function]: ../modules/list#join +[`list.append()` function]: ../modules/list#append <% example do %> .item3 { @@ -90,7 +99,7 @@ create them. You will also be able to pass `"slash"` as the `$separator` to the ## Automatic Migration You can use [the Sass migrator][] to automatically update your stylesheets to -use `divide()` and `slash-list()`. +use `math.div()` and `list.slash()`. [the Sass migrator]: https://github.com/sass/migrator#readme diff --git a/source/documentation/cli/dart-sass.html.md.erb b/source/documentation/cli/dart-sass.html.md.erb index 820916126..3d7820ce5 100644 --- a/source/documentation/cli/dart-sass.html.md.erb +++ b/source/documentation/cli/dart-sass.html.md.erb @@ -91,11 +91,11 @@ The `--stdin` flag may not be used with [many-to-many mode][]. This flag tells Sass to parse the input file as the [indented syntax][]. If it's used in [many-to-many mode][], all input files are parsed as the indented -syntax, although files they [import][] will have their syntax determined as -usual. The inverse, `--no-indented`, can be used to force all input files to be -parsed as [SCSS][] instead. +syntax, although files they [use][] will have their syntax determined as usual. +The inverse, `--no-indented`, can be used to force all input files to be parsed +as [SCSS][] instead. -[import]: ../at-rules/import +[use]: ../at-rules/use The `--indented` flag is mostly useful when the input file is coming from [standard input][], so its syntax can't be automatically determined. @@ -110,10 +110,10 @@ h1 { #### `--load-path` This option (abbreviated `-I`) adds an additional [load path][] for Sass to look -for imports. It can be passed multiple times to provide multiple load paths. +for stylesheets. It can be passed multiple times to provide multiple load paths. Earlier load paths will take precedence over later ones. -[load path]: ../at-rules/import#load-paths +[load path]: ../at-rules/use#load-paths ```shellsession $ sass --load-path=node_modules/bootstrap/dist/css style.scss style.css @@ -341,18 +341,20 @@ Error: Expected expression. This flag (abbreviated `-i`) tells Sass to run in interactive mode, where you can write [SassScript expressions][] and see their results. Interactive mode -also supports [variables][]. +also supports [variables][] and [`@use` rules][]. [SassScript expressions]: ../syntax/structure#expressions [variables]: ../variables +[`@use` rules]: ../at-rules/use ```shellsession $ sass --interactive >> 1px + 1in 97px +>> @use "sass:map" >> $map: ("width": 100px, "height": 70px) ("width": 100px, "height": 70px) ->> map-get($map, "width") +>> map.get($map, "width") 100px ``` diff --git a/source/documentation/cli/migrator.html.md.erb b/source/documentation/cli/migrator.html.md.erb new file mode 100644 index 000000000..ddcc8b025 --- /dev/null +++ b/source/documentation/cli/migrator.html.md.erb @@ -0,0 +1,345 @@ +--- +title: "Migrator" +table_of_contents: true +introduction: > + The Sass migrator automatically updates your Sass files to help you move on to + the latest and greatest version of the language. Each of its commands migrates + a single feature, to give you as much control as possible over what you update + and when. +--- + +## Usage + +To use the Sass migrator, tell it [which migration][] you want to run and what +Sass files you want to migrate: + +[which migration]: #migrations + +``` +sass-migrator +``` + +By default, the migrator will only change files that you explicitly pass on the +command line. Passing the [`--migrate-deps` option][] tells the migrator to also +change all the stylesheets that are loaded using the [`@use` rule][], +[`@forward` rule][], or [`@import` rule][]. And if you want to do a test run to +see what changes will be made without actually saving them, you can pass +[--dry-run][] [--verbose][] (or `-nv` for short). + +[`--migrate-deps` option]: #migrate-deps +[`@use` rule]: ../at-rules/use +[`@forward` rule]: ../at-rules/forward +[`@import` rule]: ../at-rules/import +[--dry-run]: #dry-run +[--verbose]: #verbose + +<%= partial 'code-snippets/example-module-migrator' %> + +## Installation + +You can install the Sass migrator from most of the same places that you can +install [Dart Sass](/dart-sass): + +### Standalone + +You can install the Sass migrator on Windows, Mac, or Linux by downloading the +package for your operating system [from GitHub][] and [adding it to your +`PATH`][]. + +[from GitHub]: <%= release_url(:migrator) %> +[adding it to your `PATH`]: https://katiek2.github.io/path-doc/ + +### npm + +If you use Node.js, you can also install the Sass migrator using [npm][] by +running + +[npm]: https://www.npmjs.com + +``` +npm install -g sass-migrator +``` + +### Chocolatey + +If you use [the Chocolatey package manager][] for Windows, you can install the +Sass migrator by running + +[the Chocolatey package manager]: https://chocolatey.org + +``` +choco install sass-migrator +``` + +### Homebrew + +If you use [the Homebrew package manager][] for Mac OS X, you can install Dart +Sass by running + +[the Homebrew package manager]: https://brew.sh + +``` +brew install sass/sass/migrator +``` + +## Global Options + +These options are available for all migrators. + +### `--migrate-deps` + +This option (abbreviated `-d`) tells the migrator to change not just the +stylesheets that are explicitly passed on the command line, but also any +stylesheets that they depend on using the [`@use` rule][], [`@forward` rule][], +or [`@import` rule][]. + +```shellsession +$ sass-migrator module --verbose style.scss +Migrating style.scss +$ sass-migrator module --verbose --migrate-deps style.scss +Migrating style.scss +Migrating _theme.scss +Migrating _fonts.scss +Migrating _grid.scss +``` + +<% heads_up do %> + The [module migrator][] assumes that any stylesheet that is depended on using + a [`@use` rule][] or a [`@forward` rule][] has already been migrated to the + module system, so it won't attempt to migrate them, even when the + `--migrate-deps` option is passed. + + [module migrator]: #module +<% end %> + +### `--load-path` + +This option (abbreviated `-I`) tells the migrator a [load path][] where it +should look for stylesheets. It can be passed multiple times to provide multiple +load paths. Earlier load paths will take precedence over later ones. + +Dependencies loaded from load paths are assumed to be third-party libraries, so +the migrator will not migrate them even when the [`--migrate-deps` option][] is +passed. + +[load path]: ../at-rules/use#load-paths + +### `--dry-run` + +This flag (abbreviated `-n`) tells the migrator not to save any changes to +disk. It instead prints the list of files that it would have changed. This is +commonly paired with the [`--verbose` option][] to print the contents of the +changes that would have been made as well. + +[`--verbose` option]: #verbose + +```shellsession +$ sass-migrator module --dry-run --migrate-deps style.scss +Dry run. Logging migrated files instead of overwriting... + +style.scss +_theme.scss +_fonts.scss +_grid.scss +``` + +#### `--no-unicode` + +This flag tells the Sass migrator only to emit ASCII characters to the terminal +as part of error messages. By default, or if `--unicode` is passed, the migrator +will emit non-ASCII characters for these messages. This flag does not affect the +CSS output. + +```shellsession +$ sass-migrator --no-unicode module style.scss +line 1, column 9 of style.scss: Error: Could not find Sass file at 'typography'. + , +1 | @import "typography"; + | ^^^^^^^^^^^^ + ' +Migration failed! +$ sass-migrator --unicode module style.scss +line 1, column 9 of style.scss: Error: Could not find Sass file at 'typography'. + ╷ +1 │ @import "typography"; + │ ^^^^^^^^^^^^ + ╵ +Migration failed! +``` + +### `--verbose` + +This flag (abbreviated `-v`) tells the migrator to print extra information to +the console. By default, it just prints the name of files that are changed, but +when combined with the [`--dry-run` option][] it also prints those files' new +contents. + +[`--dry-run` option]: #dry-run + +<%# Indent this because otherwise the table-of-contents generator interprets +the `===` as a heading. %> + + $ sass-migrator module --verbose --dry-run style.scss + Dry run. Logging migrated files instead of overwriting... + <==> style.scss + @use "bootstrap" with ( + $body-bg: #000, + $body-color: #111 + ); + + @include bootstrap.media-breakpoint-up(sm) { + .navbar { + display: block; + } + } + $ sass-migrator module --verbose style.scss + Migrating style.scss + +## Migrations + +The migrator currently supports only one migration, but expect more to come as +the Sass language continues to evolve! + +### Module + +This migration converts stylesheets that use the old [`@import` rule][] to load +dependencies so that they use the Sass module system via the [`@use` rule][] +instead. It doesn't just naïvely change `@import`s to `@use`s—it updates +stylesheets intelligently so that they keep working the same way they did +before, including: + +* Adding namespaces to uses of members (variables, mixins, and functions) from + other modules. + +* Adding new `@use` rules to stylesheets that were using members without + importing them. + +* Converting overridden default variables to [`with` clauses][]. + + [`with` clauses]: ../at-rules/use#configuring-modules + +* Automatically removing `-` and `_` prefixes from members that are used from + other files (because otherwise they'd be considered [private][] and could only + be used in the module they're declared). + + [private]: ../at-rules/use#private-members + +* Converting [nested imports][] to use the [`meta.load-css()` mixin][] instead. + + [nested imports]: ../at-rules/import#nesting + [`meta.load-css()` mixin]: ../modules/meta#load-css + +<% heads_up do %> + Because the module migrator may need to modify both member definitions *and* + member names, it's important to either run it with the [`--migrate-deps` + option][] or ensure that you pass it all the stylesheets in your package or + application. + + [`--migrate-deps` option]: #migrate-deps +<% end %> + +<%= partial 'code-snippets/example-module-migrator' %> + +#### Loading Dependencies + +The module migrator needs to be able to read all of the stylesheets depended on +by the ones it's migrating, even if the [`--migrate-deps` option][] is not +passed. If the migrator fails to find a dependency, you'll get an error. + +```shellsession +$ ls . +style.scss node_modules +$ sass-migrator module style.scss +Error: Could not find Sass file at 'dependency'. + , +1 | @import "dependency"; + | ^^^^^^^^^^^^ + ' + style.scss 1:9 root stylesheet +Migration failed! +$ sass-migrator --load-path node_modules module style.scss +``` + +If you use a [load path][] when compiling your stylesheets, make sure to pass +that to the migrator using the [`--load-path` option][]. + +Unfortunately, the migrator does not support custom importers, but it does have +built-in support for resolving URLs starting with `~` by searching in +`node_modules`, similar to [what Webpack supports][]. + +[load path]: ../at-rules/use#load-paths +[`--load-path` option]: #load-path +[what Webpack supports]: https://github.com/webpack-contrib/sass-loader#resolving-import-at-rules + +#### `--remove-prefix` + +This option (abbreviated `-p`) takes an identifier prefix to remove from the +beginning of all variable, mixin, and function names when they're migrated. +Members that don't start with this prefix will remain unchanged. + +The [`@import` rule][] put all top-level members in one global scope, so when it +was the standard way of loading stylesheets, everyone was incentivized to add +prefixes to all their member names to avoid accidentally redefining some other +stylesheet's. The module system solves this problem, so it's useful to +automatically strip those old prefixes now that they're unnecessary. + +```shellsession +$ cat style.scss +@import "theme"; + +@mixin app-inverted { + color: $app-bg-color; + background-color: $app-color; +} +$ sass-migrator --migrate-deps module --remove-prefix=app- style.scss +$ cat style.scss +@import "theme"; + +@mixin inverted { + color: theme.$bg-color; + background-color: theme.$color; +} +``` + +When you pass this option, the migrator will also generate an [import-only +stylesheet][] that [forwards][] all the members with the prefix added back, to +preserve backwards-compatibility for users who were importing the library. + +[import-only stylesheet]: ../at-rules/import#import-only-files +[forwards]: ../at-rules/forward + +#### `--forward` + +This option tells the migrator which members to forward using the [`@forward` +rule][]. It supports the following settings: + +* `none` (the default) doesn't forward any members. + +* `all` forwards all members except those that started with `-` or `_` in the + original stylesheet, since that was commonly used to mark a package-private + member before the module system was introduced. + +* `prefixed` forwards only members that begin with the prefix passed to the + [`--remove-prefix` option][]. This option may only be used in conjunction with + the `--remove-prefix` option. + + [`--remove-prefix` option]: #remove-prefix + +All files that are passed explicitly on the command line will forward members +that are transitively loaded by those files using the `@import` rule. Files +loaded using the [`--migrate-deps` option][] will not forward any new members. +This option is particularly useful when migrating a Sass library, because it +ensures that users of that library will still be able to access all the members +it defines. + +```shellsession +$ cat _index.scss +@import "theme"; +@import "typography"; +@import "components"; +$ sass-migrator --migrate-deps module --forward=all style.scss +$ cat _index.scss +@forward "theme"; +@forward "typography"; +@forward "components"; +``` diff --git a/source/documentation/cli/ruby-sass.html.md.erb b/source/documentation/cli/ruby-sass.html.md.erb index ce27d0c30..0de20b3f2 100644 --- a/source/documentation/cli/ruby-sass.html.md.erb +++ b/source/documentation/cli/ruby-sass.html.md.erb @@ -80,7 +80,7 @@ When compiling whole directories, Sass will ignore [partial files][] whose names begin with `_`. You can use partials to separate out your stylesheets without creating a bunch of unnecessary output files. -[partial files]: ../at-rules/import#partials +[partial files]: ../at-rules/use#partials Many-to-many mode will only compile stylesheets whose dependencies have been modified more recently than the corresponding CSS file was generated. It will @@ -93,10 +93,10 @@ also print status messages when updating stylesheets. #### `--load-path` This option (abbreviated `-I`) adds an additional [load path][] for Sass to look -for imports. It can be passed multiple times to provide multiple load paths. +for stylesheets. It can be passed multiple times to provide multiple load paths. Earlier load paths will take precedence over later ones. -[load path]: ../at-rules/import#load-paths +[load path]: ../at-rules/use#load-paths ```shellsession $ sass --load-path=node_modules/bootstrap/dist/css style.scss style.css diff --git a/source/documentation/functions.html.md.erb b/source/documentation/functions.html.md.erb deleted file mode 100644 index 830c5b9b6..000000000 --- a/source/documentation/functions.html.md.erb +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: Built-In Functions -introduction: > - In addition to allowing users to [define their own - functions](at-rules/function), there are many useful functions built right - into Sass. These functions are called using the normal CSS function syntax, - with the addition of [special Sass argument - syntax](at-rules/function#arguments). -overview: true ---- - -Sass's built-in functions are divided into a few categories: - -* Any function that Sass doesn't recognize as built-in or user-defined is - treated as a [plain CSS function][]. - -* [Number functions][] operate on [numbers][], usually to perform some sort of - math. - -* [String functions][] make it easy to combine, search, or split apart - [strings][]. - -* [Color functions][] generate new [colors][] based on existing ones, making it - easy to build color themes. - -* [List functions][] access and modify values in [lists][]. - -* [Map functions][] make it possible to look up the value associated with a key - in a [map][], and much more. - -* [Selector functions][] provide access to Sass's powerful selector engine. - -* [Introspection functions][] expose the details of Sass's inner workings. - -[plain CSS function]: functions/css -[Number functions]: functions/math -[numbers]: values/numbers -[String functions]: functions/string -[strings]: values/strings -[Color functions]: functions/color -[colors]: values/colors -[List functions]: functions/list -[lists]: values/lists -[Map functions]: functions/map -[map]: values/maps -[Selector functions]: functions/selector -[Introspection functions]: functions/meta - - -<% function "if($condition, $if-true, $if-false)" do %> - Returns `$if-true` if `$condition` is [truthy][], and `$if-false` otherwise. - - This function is special in that it doesn't even evaluate the argument that - isn't returned, so it's safe to call even if the unused argument would throw an - error. - - [truthy]: at-rules/control/if#truthiness-and-falsiness - - <% example(autogen_css: false) do %> - @debug if(true, 10px, 15px); // 10px - @debug if(false, 10px, 15px); // 15px - @debug if(variable-defined($var), $var, null); // null - === - @debug if(true, 10px, 15px) // 10px - @debug if(false, 10px, 15px) // 15px - @debug if(variable-defined($var), $var, null) // null - <% end %> -<% end %> diff --git a/source/documentation/functions/color.html.md.erb b/source/documentation/functions/color.html.md.erb deleted file mode 100644 index 39de59929..000000000 --- a/source/documentation/functions/color.html.md.erb +++ /dev/null @@ -1,876 +0,0 @@ ---- -title: Color Functions ---- - -<% function < - Increases or decreases one or more properties of `$color` by fixed amounts. - - Adds the value passed for each keyword argument to the corresponding property - of the color, and returns the adjusted color. It's an error to specify an RGB - property (`$red`, `$green`, and/or `$blue`) at the same time as an HSL - property (`$hue`, `$saturation`, and/or `$lightness`). - - All optional arguments must be numbers. The `$red`, `$green`, and `$blue` - arguments must be [unitless][] and between -255 and 255 (inclusive). The - `$hue` argument must have either the unit `deg` or no unit. The `$saturation` - and `$lightness` arguments must be between `-100%` and `100%` (inclusive), and - may be unitless. The `$alpha` argument must be unitless and between -1 and 1 - (inclusive). - - [unitless]: ../values/numbers#units - - See also: - - * [`scale-color()`](#scale-color) for fluidly scaling a color's properties. - * [`change-color()`](#change-color) for setting a color's properties. - - <% example(autogen_css: false) do %> - @debug adjust-color(#6b717f, $red: 15); // #7a717f - @debug adjust-color(#d2e1dd, $red: -10, $blue: 10); // #c8e1e7 - @debug adjust-color(#998099, $lightness: -30%, $alpha: -0.4); // rgba(71, 57, 71, 0.6) - === - @debug adjust-color(#6b717f, $red: 15) // #7a717f - @debug adjust-color(#d2e1dd, $red: -10, $blue: 10) // #c8e1e7 - @debug adjust-color(#998099, $lightness: -30%, $alpha: -0.4) // rgba(71, 57, 71, 0.6) - <% end %> -<% end %> - - -<% function 'adjust-hue($color, $degrees)', returns: 'color' do %> - Increases or decreases `$color`'s hue. - - The `$hue` must be a number between `-360deg` and `360deg` (inclusive) to add - to `$color`'s hue. It may be [unitless][]. - - [unitless]: ../values/numbers#units - - See also [`adjust-color()`](#adjust-color), which can adjust any property of a - color. - - <% example(autogen_css: false) do %> - // Hue 222deg becomes 282deg. - @debug adjust-hue(#6b717f, 60deg); // #796b7f - - // Hue 164deg becomes 104deg. - @debug adjust-hue(#d2e1dd, -60deg); // #d6e1d2 - - // Hue 210deg becomes 255deg. - @debug adjust-hue(#036, 45); // #1a0066 - === - // Hue 222deg becomes 282deg. - @debug adjust-hue(#6b717f, 60deg) // #796b7f - - // Hue 164deg becomes 104deg. - @debug adjust-hue(#d2e1dd, -60deg) // #d6e1d2 - - // Hue 210deg becomes 255deg. - @debug adjust-hue(#036, 45) // #1a0066 - <% end %> -<% end %> - - -<% function 'alpha($color)', 'opacity($color)', returns: 'number' do %> - Returns the alpha channel of `$color` as a number between 0 and 1. - - As a special case, this supports the Internet Explorer syntax - `alpha(opacity=20)`, for which it returns an [unquoted string][]. - - [unquoted string]: ../values/strings#unquoted - - See also: - - * [`red()`](#red) for getting a color's red channel. - * [`green()`](#green) for getting a color's green channel. - * [`blue()`](#blue) for getting a color's blue channel. - * [`hue()`](#hue) for getting a color's hue. - * [`saturation()`](#saturation) for getting a color's saturation. - * [`lightness()`](#lightness) for getting a color's lightness. - - <% example(autogen_css: false) do %> - @debug alpha(#e1d7d2); // 1 - @debug opacity(rgb(210, 225, 221, 0.4)); // 0.4 - @debug alpha(opacity=20); // alpha(opacity=20) - === - @debug alpha(#e1d7d2) // 1 - @debug opacity(rgb(210, 225, 221, 0.4)) // 0.4 - @debug alpha(opacity=20) // alpha(opacity=20) - <% end %> -<% end %> - - -<% function 'blue($color)', returns: 'number' do %> - Returns the blue channel of `$color` as a number between 0 and 255. - - See also: - - * [`red()`](#red) for getting a color's red channel. - * [`green()`](#green) for getting a color's green channel. - * [`hue()`](#hue) for getting a color's hue. - * [`saturation()`](#saturation) for getting a color's saturation. - * [`lightness()`](#lightness) for getting a color's lightness. - * [`alpha()`](#alpha) for getting a color's alpha channel. - - <% example(autogen_css: false) do %> - @debug blue(#e1d7d2); // 210 - @debug blue(white); // 255 - @debug blue(black); // 0 - === - @debug blue(#e1d7d2) // 210 - @debug blue(white) // 255 - @debug blue(black) // 0 - <% end %> -<% end %> - - -<% function < - Sets one or more properties of a color to new values. - - Uses the value passed for each keyword argument in place of the corresponding - property of the color, and returns the changed color. It's an error to specify - an RGB property (`$red`, `$green`, and/or `$blue`) at the same time as an HSL - property (`$hue`, `$saturation`, and/or `$lightness`). - - All optional arguments must be numbers. The `$red`, `$green`, and `$blue` - arguments must be [unitless][] and between 0 and 255 (inclusive). The `$hue` - argument must have either the unit `deg` or no unit. The `$saturation` and - `$lightness` arguments must be between `0%` and `100%` (inclusive), and may be - unitless. The `$alpha` argument must be unitless and between -1 and 1 - (inclusive). - - [unitless]: ../values/numbers#units - - See also: - - * [`scale-color()`](#scale-color) for fluidly scaling a color's properties. - * [`adjust-color()`](#adjust-color) for adjusting a color's properties by fixed - amounts. - - <% example(autogen_css: false) do %> - @debug change-color(#6b717f, $red: 100); // #64717f - @debug change-color(#d2e1dd, $red: 100, $blue: 50); // #64e132 - @debug change-color(#998099, $lightness: 30%, $alpha: 0.5); // rgba(85, 68, 85, 0.5) - === - @debug change-color(#6b717f, $red: 100) // #64717f - @debug change-color(#d2e1dd, $red: 100, $blue: 50) // #64e132 - @debug change-color(#998099, $lightness: 30%, $alpha: 0.5) // rgba(85, 68, 85, 0.5) - <% end %> -<% end %> - - -<% function 'complement($color)', returns: 'color' do %> - Returns the RGB [complement][] of `$color`. - - This is identical to [`adjust-hue($color, 180deg)`](#adjust-hue). - - [complement]: https://en.wikipedia.org/wiki/Complementary_colors - - <% example(autogen_css: false) do %> - // Hue 222deg becomes 42deg. - @debug complement(#6b717f); // #7f796b - - // Hue 164deg becomes 344deg. - @debug complement(#d2e1dd); // #e1d2d6 - - // Hue 210deg becomes 30deg. - @debug complement(#036); // #663300 - === - // Hue 222deg becomes 42deg. - @debug complement(#6b717f) // #7f796b - - // Hue 164deg becomes 344deg. - @debug complement(#d2e1dd) // #e1d2d6 - - // Hue 210deg becomes 30deg. - @debug complement(#036) // #663300 - <% end %> -<% end %> - - -<% function 'darken($color, $amount)', returns: 'color' do %> - Makes `$color` darker. - - The `$amount` must be a number between `0%` and `100%` (inclusive). Decreases - the HSL lightness of `$color` by that amount. - - <% heads_up do %> - The `darken()` function decreases lightness by a fixed amount, which is often - not the desired effect. To make a color a certain percentage darker than it was - before, use [`scale-color()`](#scale-color) instead. - - <% example(autogen_css: false) do %> - // #036 has lightness 20%, so when darken() subtracts 30% it just returns black. - @debug darken(#036, 30%); // black - - // scale-color() instead makes it 30% darker than it was originally. - @debug scale-color(#036, $lightness: -30%); // #002447 - === - // #036 has lightness 20%, so when darken() subtracts 30% it just returns black. - @debug darken(#036, 30%) // black - - // scale-color() instead makes it 30% darker than it was originally. - @debug scale-color(#036, $lightness: -30%) // #002447 - <% end %> - <% end %> - - <% example(autogen_css: false) do %> - // Lightness 92% becomes 72%. - @debug darken(#b37399, 20%); // #7c4465 - - // Lightness 85% becomes 45%. - @debug darken(#f2ece4, 40%); // #b08b5a - - // Lightness 20% becomes 0%. - @debug darken(#036, 30%); // black - === - // Lightness 92% becomes 72%. - @debug darken(#b37399, 20%) // #7c4465 - - // Lightness 85% becomes 45%. - @debug darken(#f2ece4, 40%) // #b08b5a - - // Lightness 20% becomes 0%. - @debug darken(#036, 30%) // black - <% end %> -<% end %> - - -<% function 'desaturate($color, $amount)', returns: 'color' do %> - Makes `$color` less saturated. - - The `$amount` must be a number between `0%` and `100%` (inclusive). Decreases - the HSL saturation of `$color` by that amount. - - <% heads_up do %> - The `desaturate()` function decreases saturation by a fixed amount, which is - often not the desired effect. To make a color a certain percentage less - saturated than it was before, use [`scale-color()`](#scale-color) instead. - - <% example(autogen_css: false) do %> - // #d2e1dd has saturation 20%, so when desaturate() subtracts 30% it just - // returns gray. - @debug desaturate(#d2e1dd, 30%); // #dadada - - // scale-color() instead makes it 30% less saturated than it was originally. - @debug scale-color(#6b717f, $saturation: -30%); // #6e727c - === - // #6b717f has saturation 20%, so when desaturate() subtracts 30% it just - // returns gray. - @debug desaturate(#d2e1dd, 30%) // #dadada - - // scale-color() instead makes it 30% less saturated than it was originally. - @debug scale-color(#6b717f, $saturation: -30%) // #6e727c - <% end %> - <% end %> - - <% example(autogen_css: false) do %> - // Saturation 100% becomes 80%. - @debug desaturate(#036, 20%); // #0a335c - - // Saturation 35% becomes 15%. - @debug desaturate(#f2ece4, 20%); // #eeebe8 - - // Saturation 20% becomes 0%. - @debug desaturate(#d2e1dd, 30%); // #dadada - === - // Saturation 100% becomes 80%. - @debug desaturate(#036, 20%) // #0a335c - - // Saturation 35% becomes 15%. - @debug desaturate(#f2ece4, 20%) // #eeebe8 - - // Saturation 20% becomes 0%. - @debug desaturate(#d2e1dd, 30%) // #dadada - <% end %> -<% end %> - - -<% function 'grayscale($color)', returns: 'color' do %> - Returns a gray color with the same lightness as `$color`. - - This is identical to [`change-color($color, $saturation: 0%)`](#change-color). - - <% example(autogen_css: false) do %> - @debug grayscale(#6b717f); // #757575 - @debug grayscale(#d2e1dd); // #dadada - @debug grayscale(#036); // #333333 - === - @debug grayscale(#6b717f) // #757575 - @debug grayscale(#d2e1dd) // #dadada - @debug grayscale(#036) // #333333 - <% end %> -<% end %> - - -<% function 'green($color)', returns: 'number' do %> - Returns the green channel of `$color` as a number between 0 and 255. - - See also: - - * [`red()`](#red) for getting a color's red channel. - * [`blue()`](#blue) for getting a color's blue channel. - * [`hue()`](#hue) for getting a color's hue. - * [`saturation()`](#saturation) for getting a color's saturation. - * [`lightness()`](#lightness) for getting a color's lightness. - * [`alpha()`](#alpha) for getting a color's alpha channel. - - <% example(autogen_css: false) do %> - @debug green(#e1d7d2); // 215 - @debug green(white); // 255 - @debug green(black); // 0 - === - @debug green(#e1d7d2) // 215 - @debug green(white) // 255 - @debug green(black) // 0 - <% end %> -<% end %> - - -<% function 'hsl($hue $saturation $lightness)', - 'hsl($hue $saturation $lightness / $alpha)', - 'hsl($hue, $saturation, $lightness, $alpha: 1)', - 'hsla($hue $saturation $lightness)', - 'hsla($hue $saturation $lightness / $alpha)', - 'hsla($hue, $saturation, $lightness, $alpha: 1)', - returns: 'color' do %> - <% impl_status dart: '1.15.0', libsass: false, ruby: false, feature: "Level 4 Syntax" do %> - LibSass and Ruby Sass only support the following signatures: - - * `hsl($hue, $saturation, $lightness)` - * `hsla($hue, $saturation, $lightness, $alpha)` - - Note that for these implementations, the `$alpha` argument is *required* if - the function name `hsla()` is used, and *forbidden* if the function name - `hsl()` is used. - <% end %> - - <% impl_status dart: true, libsass: false, ruby: '3.7.0', feature: "Percent Alpha" do %> - LibSass and older versions of Ruby Sass don't support alpha values specified as - percentages. - <% end %> - - Returns a color with the given [hue, saturation, and lightness][] and the given - alpha channel. - - [hue, saturation, and lightness]: https://en.wikipedia.org/wiki/HSL_and_HSV - - The hue is a number between `0deg` and `360deg` (inclusive). The saturation - and lightness are numbers between `0%` and `100%` (inclusive). All these - numbers may be [unitless][]. The alpha channel can be specified as either a - unitless number between 0 and 1 (inclusive), or a percentage between `0%` and - `100%` (inclusive). - - [unitless]: ../values/numbers#units - - <% fun_fact do %> - You can pass [special functions][] like `calc()` or `var()` in place of any - argument to `hsl()`. You can even use `var()` in place of multiple - arguments, since it might be replaced by multiple values! When a color - function is called this way, it returns an unquoted string using the same - signature it was called with. - - [special functions]: ../syntax/special-functions - - <% example(autogen_css: false) do %> - @debug hsl(210deg 100% 20% / var(--opacity)); // hsl(210deg 100% 20% / var(--opacity)) - @debug hsla(var(--peach), 20%); // hsla(var(--peach), 20%) - === - @debug hsl(210deg 100% 20% / var(--opacity)) // hsl(210deg 100% 20% / var(--opacity)) - @debug hsla(var(--peach), 20%) // hsla(var(--peach), 20%) - <% end %> - <% end %> - - <% heads_up do %> - Sass's [special parsing rules][] for slash-separated values make it - difficult to pass variables for `$lightness` or `$alpha` when using the - `hsl($hue $saturation $lightness / $alpha)` signature. Consider using - `hsl($hue, $saturation, $lightness, $alpha)` instead. - - [special parsing rules]: ../operators/numeric#slash-separated-values - <% end %> - - <% example(autogen_css: false) do %> - @debug hsl(210deg 100% 20%); // #036 - @debug hsl(34, 35%, 92%); // #f2ece4 - @debug hsl(210deg 100% 20% / 50%); // rgba(0, 51, 102, 0.5) - @debug hsla(34, 35%, 92%, 0.2); // rgba(242, 236, 228, 0.2) - === - @debug hsl(210deg 100% 20%) // #036 - @debug hsl(34, 35%, 92%) // #f2ece4 - @debug hsl(210deg 100% 20% / 50%) // rgba(0, 51, 102, 0.5) - @debug hsla(34, 35%, 92%, 0.2) // rgba(242, 236, 228, 0.2) - <% end %> -<% end %> - - -<% function 'hue($color)', returns: 'number' do %> - Returns the hue of `$color` as a number between `0deg` and `255deg`. - - See also: - - * [`red()`](#red) for getting a color's red channel. - * [`green()`](#green) for getting a color's green channel. - * [`blue()`](#blue) for getting a color's blue channel. - * [`saturation()`](#saturation) for getting a color's saturation. - * [`lightness()`](#lightness) for getting a color's lightness. - * [`alpha()`](#alpha) for getting a color's alpha channel. - - <% example(autogen_css: false) do %> - @debug hue(#e1d7d2); // 20deg - @debug hue(#f2ece4); // 34.2857142857deg - @debug hue(#dadbdf); // 228deg - === - @debug hue(#e1d7d2) // 20deg - @debug hue(#f2ece4) // 34.2857142857deg - @debug hue(#dadbdf) // 228deg - <% end %> -<% end %> - - -<% function 'ie-hex-str($color)', returns: 'unquoted string' do %> - Returns an unquoted string that represents `$color` in the `#AARRGGBB` format - expected by Internet Explorer's [`-ms-filter`][] property. - - [`-ms-filter`]: https://developer.mozilla.org/en-US/docs/Web/CSS/-ms-filter - - <% example(autogen_css: false) do %> - @debug ie-hex-str(#b37399); // #FFB37399 - @debug ie-hex-str(#808c99); // #FF808C99 - @debug ie-hex-str(rgba(242, 236, 228, 0.6)); // #99F2ECE4 - === - @debug ie-hex-str(#b37399); // #FFB37399 - @debug ie-hex-str(#808c99); // #FF808C99 - @debug ie-hex-str(rgba(242, 236, 228, 0.6)); // #99F2ECE4 - <% end %> -<% end %> - - -<% function 'invert($color, $weight: 100%)', returns: 'color' do %> - Returns the inverse or [negative][] of `$color`. - - [negative]: https://en.wikipedia.org/wiki/Negative_(photography) - - The `$weight` must be a number between `0%` and `100%` (inclusive). A higher - weight means the result will be closer to the negative, and a lower weight means - it will be closer to `$color`. Weight `50%` will always produce `#808080`. - - <% example(autogen_css: false) do %> - @debug invert(#b37399); // #4c8c66 - @debug invert(black); // white - @debug invert(#550e0c, 20%); // #663b3a - === - @debug invert(#b37399) // #4c8c66 - @debug invert(black) // white - @debug invert(#550e0c, 20%) // #663b3a - <% end %> -<% end %> - - -<% function 'lighten($color, $amount)', returns: 'color' do %> - Makes `$color` lighter. - - The `$amount` must be a number between `0%` and `100%` (inclusive). Increases - the HSL lightness of `$color` by that amount. - - <% heads_up do %> - The `lighten()` function increases lightness by a fixed amount, which is often - not the desired effect. To make a color a certain percentage lighter than it was - before, use [`scale-color()`](#scale-color) instead. - - <% example(autogen_css: false) do %> - // #e1d7d2 has lightness 85%, so when lighten() adds 30% it just returns white. - @debug lighten(#e1d7d2, 30%); // white - - // scale-color() instead makes it 30% lighter than it was originally. - @debug scale-color(#e1d7d2, $lightness: 30%); // #eae3e0 - === - // #e1d7d2 has lightness 85%, so when lighten() adds 30% it just returns white. - @debug lighten(#e1d7d2, 30%) // white - - // scale-color() instead makes it 30% lighter than it was originally. - @debug scale-color(#e1d7d2, $lightness: 30%) // #eae3e0 - <% end %> - <% end %> - - <% example(autogen_css: false) do %> - // Lightness 46% becomes 66%. - @debug lighten(#6b717f, 20%); // #a1a5af - - // Lightness 20% becomes 80%. - @debug lighten(#036, 60%); // #99ccff - - // Lightness 85% becomes 100%. - @debug lighten(#e1d7d2, 30%); // white - === - // Lightness 46% becomes 66%. - @debug lighten(#6b717f, 20%) // #a1a5af - - // Lightness 20% becomes 80%. - @debug lighten(#036, 60%) // #99ccff - - // Lightness 85% becomes 100%. - @debug lighten(#e1d7d2, 30%) // white - <% end %> -<% end %> - - -<% function 'lightness($color)', returns: 'number' do %> - Returns the HSL lightness of `$color` as a number between `0%` and `100%`. - - See also: - - * [`red()`](#red) for getting a color's red channel. - * [`green()`](#green) for getting a color's green channel. - * [`blue()`](#blue) for getting a color's blue channel. - * [`hue()`](#hue) for getting a color's hue. - * [`saturation()`](#saturation) for getting a color's saturation. - * [`alpha()`](#alpha) for getting a color's alpha channel. - - <% example(autogen_css: false) do %> - @debug lightness(#e1d7d2); // 85.2941176471% - @debug lightness(#f2ece4); // 92.1568627451% - @debug lightness(#dadbdf); // 86.4705882353% - === - @debug lightness(#e1d7d2) // 85.2941176471% - @debug lightness(#f2ece4) // 92.1568627451% - @debug lightness(#dadbdf) // 86.4705882353% - <% end %> -<% end %> - - -<% function 'mix($color1, $color2, $weight: 50%)', returns: 'color' do %> - Returns a number that's a mixture of `$color1` and `$color2`. - - Both the `$weight` and the relative opacity of each color determines how much of - each color is in the result. The `$weight` must be a number between `0%` and - `100%` (inclusive). A larger weight indicates that more of `$color1` should be - used, and a smaller weight indicates that more of `$color2` should be used. - - <% example(autogen_css: false) do %> - @debug mix(#036, #d2e1dd); // #698aa2 - @debug mix(#036, #d2e1dd, 75%); // #355f84 - @debug mix(#036, #d2e1dd, 25%); // #9eb6bf - @debug mix(rgba(242, 236, 228, 0.5), #6b717f); // rgba(141, 144, 152, 0.75) - === - @debug mix(#036, #d2e1dd) // #698aa2 - @debug mix(#036, #d2e1dd, 75%) // #355f84 - @debug mix(#036, #d2e1dd, 25%) // #9eb6bf - @debug mix(rgba(242, 236, 228, 0.5), #6b717f) // rgba(141, 144, 152, 0.75) - <% end %> -<% end %> - - -<% function 'opacify($color, $amount)', 'fade-in($color, $amount)', returns: 'color' do %> - Makes `$color` more opaque. - - The `$amount` must be a number between `0` and `1` (inclusive). Increases the - alpha channel of `$color` by that amount. - - <% heads_up do %> - The `opacify()` function increases the alpha channel by a fixed amount, which is often - not the desired effect. To make a color a certain percentage more opaque than it was - before, use [`scale-color()`](#scale-color) instead. - - <% example(autogen_css: false) do %> - // rgba(#036, 0.7) has alpha 0.7, so when opacify() adds 0.3 it returns a fully - // opaque color. - @debug opacify(rgba(#036, 0.7), 0.3); // #036 - - // scale-color() instead makes it 30% more opaque than it was originally. - @debug scale-color(rgba(#036, 0.7), $alpha: 30%); // rgba(0, 51, 102, 0.79) - === - // rgba(#036, 0.7) has alpha 0.7, so when opacify() adds 0.3 it returns a fully - // opaque color. - @debug opacify(rgba(#036, 0.7), 0.3) // #036 - - // scale-color() instead makes it 30% more opaque than it was originally. - @debug scale-color(rgba(#036, 0.7), $alpha: 30%) // rgba(0, 51, 102, 0.79) - <% end %> - <% end %> - - <% example(autogen_css: false) do %> - @debug opacify(rgba(#6b717f, 0.5), 0.2); // rgba(107, 113, 127, 0.7) - @debug fade-in(rgba(#e1d7d2, 0.5), 0.4); // rgba(225, 215, 210, 0.9) - @debug opacify(rgba(#036, 0.7), 0.3); // #036 - === - @debug opacify(rgba(#6b717f, 0.5), 0.2) // rgba(107, 113, 127, 0.7) - @debug fade-in(rgba(#e1d7d2, 0.5), 0.4) // rgba(225, 215, 210, 0.9) - @debug opacify(rgba(#036, 0.7), 0.3) // #036 - <% end %> -<% end %> - - -<% function 'red($color)', returns: 'number' do %> - Returns the red channel of `$color` as a number between 0 and 255. - - See also: - - * [`green()`](#green) for getting a color's green channel. - * [`blue()`](#blue) for getting a color's blue channel. - * [`hue()`](#hue) for getting a color's hue. - * [`saturation()`](#saturation) for getting a color's saturation. - * [`lightness()`](#lightness) for getting a color's lightness. - * [`alpha()`](#alpha) for getting a color's alpha channel. - - <% example(autogen_css: false) do %> - @debug red(#e1d7d2); // 225 - @debug red(white); // 255 - @debug red(black); // 0 - === - @debug red(#e1d7d2) // 225 - @debug red(white) // 255 - @debug red(black) // 0 - <% end %> -<% end %> - - -<% function 'rgb($red $green $blue)', - 'rgb($red $green $blue / $alpha)', - 'rgb($red, $green, $blue, $alpha: 1)', - 'rgb($color, $alpha)', - 'rgba($red $green $blue)', - 'rgba($red $green $blue / $alpha)', - 'rgba($red, $green, $blue, $alpha: 1)', - 'rgba($color, $alpha)', - returns: 'color' do %> - <% impl_status dart: '1.15.0', libsass: false, ruby: false, feature: "Level 4 Syntax" do %> - LibSass and Ruby Sass only support the following signatures: - - * `rgb($red, $green, $blue)` - * `rgba($red, $green, $blue, $alpha)` - * `rgba($color, $alpha)` - - Note that for these implementations, the `$alpha` argument is *required* if - the function name `rgba()` is used, and *forbidden* if the function name - `rgb()` is used. - <% end %> - - <% impl_status dart: true, libsass: false, ruby: '3.7.0', feature: "Percent Alpha" do %> - LibSass and older versions of Ruby Sass don't support alpha values specified - as percentages. - <% end %> - - If `$red`, `$green`, `$blue`, and optionally `$alpha` are passed, returns a - color with the given red, green, blue, and alpha channels. - - Each channel can be specified as either a [unitless][] number between 0 and - 255 (inclusive), or a percentage between `0%` and `100%` (inclusive). The - alpha channel can be specified as either a unitless number between 0 and 1 - (inclusive), or a percentage between `0%` and `100%` (inclusive). - - [unitless]: ../values/numbers#units - - <% fun_fact do %> - You can pass [special functions][] like `calc()` or `var()` in place of any - argument to `rgb()`. You can even use `var()` in place of multiple - arguments, since it might be replaced by multiple values! When a color - function is called this way, it returns an unquoted string using the same - signature it was called with. - - [special functions]: ../syntax/special-functions - - <% example(autogen_css: false) do %> - @debug rgb(0 51 102 / var(--opacity)); // rgb(0 51 102 / var(--opacity)) - @debug rgba(var(--peach), 0.2); // rgba(var(--peach), 0.2) - === - @debug rgb(0 51 102 / var(--opacity)) // rgb(0 51 102 / var(--opacity)) - @debug rgba(var(--peach), 0.2) // rgba(var(--peach), 0.2) - <% end %> - <% end %> - - <% heads_up do %> - Sass's [special parsing rules][] for slash-separated values make it - difficult to pass variables for `$blue` or `$alpha` when using the - `rgb($red $green $blue / $alpha)` signature. Consider using - `hsl($red, $green, $blue, $alpha)` instead. - - [special parsing rules]: ../operators/numeric#slash-separated-values - <% end %> - - <% example(autogen_css: false) do %> - @debug rgb(0 51 102); // #036 - @debug rgb(95%, 92.5%, 89.5%); // #f2ece4 - @debug rgb(0 51 102 / 50%); // rgba(0, 51, 102, 0.5) - @debug rgba(95%, 92.5%, 89.5%, 0.2); // rgba(242, 236, 228, 0.2) - === - @debug rgb(0 51 102) // #036 - @debug rgb(95%, 92.5%, 89.5%) // #f2ece4 - @debug rgb(0 51 102 / 50%) // rgba(0, 51, 102, 0.5) - @debug rgba(95%, 92.5%, 89.5%, 0.2) // rgba(242, 236, 228, 0.2) - <% end %> - - --- - - If `$color` and `$alpha` are passed, this returns `$color` with the given - `$alpha` channel instead of its original alpha channel. - - <% example(autogen_css: false) do %> - @debug rgb(#f2ece4, 50%); // rgba(242, 236, 228, 0.5); - @debug rgba(rgba(0, 51, 102, 0.5), 1); // #003366 - === - @debug rgb(#f2ece4, 50%) // rgba(242, 236, 228, 0.5) - @debug rgba(rgba(0, 51, 102, 0.5), 1) // #003366 - <% end %> -<% end %> - - -<% function 'saturate($color, $amount)', returns: 'color' do %> - Makes `$color` more saturated. - - The `$amount` must be a number between `0%` and `100%` (inclusive). Increases - the HSL saturation of `$color` by that amount. - - <% heads_up do %> - The `saturate()` function increases saturation by a fixed amount, which is often - not the desired effect. To make a color a certain percentage more saturated than - it was before, use [`scale-color()`](#scale-color) instead. - - <% example(autogen_css: false) do %> - // #0e4982 has saturation 80%, so when saturate() adds 30% it just becomes - // fully saturated. - @debug saturate(#0e4982, 30%); // #004990 - - // scale-color() instead makes it 30% more saturated than it was originally. - @debug scale-color(#0e4982, $saturation: 30%); // #0a4986 - === - // #0e4982 has saturation 80%, so when saturate() adds 30% it just becomes - // fully saturated. - @debug saturate(#0e4982, 30%) // #004990 - - // scale-color() instead makes it 30% more saturated than it was originally. - @debug scale-color(#0e4982, $saturation: 30%) // #0a4986 - <% end %> - <% end %> - - <% example(autogen_css: false) do %> - // Saturation 50% becomes 70%. - @debug saturate(#c69, 20%); // #e05299 - - // Saturation 35% becomes 85%. - @debug desaturate(#f2ece4, 50%); // #ebebeb - - // Saturation 80% becomes 100%. - @debug saturate(#0e4982, 30%) // #004990 - === - // Saturation 50% becomes 70%. - @debug saturate(#c69, 20%); // #e05299 - - // Saturation 35% becomes 85%. - @debug desaturate(#f2ece4, 50%); // #ebebeb - - // Saturation 80% becomes 100%. - @debug saturate(#0e4982, 30%) // #004990 - <% end %> -<% end %> - - -<% function 'saturation($color)', returns: 'number' do %> - Returns the HSL saturation of `$color` as a number between `0%` and `100%`. - - See also: - - * [`red()`](#red) for getting a color's red channel. - * [`green()`](#green) for getting a color's green channel. - * [`blue()`](#blue) for getting a color's blue channel. - * [`hue()`](#hue) for getting a color's hue. - * [`lightness()`](#lightness) for getting a color's lightness. - * [`alpha()`](#alpha) for getting a color's alpha channel. - - <% example(autogen_css: false) do %> - @debug saturation(#e1d7d2); // 20% - @debug saturation(#f2ece4); // 30% - @debug saturation(#dadbdf); // 7.2463768116% - === - @debug saturation(#e1d7d2) // 20% - @debug saturation(#f2ece4) // 30% - @debug saturation(#dadbdf) // 7.2463768116% - <% end %> -<% end %> - - -<% function < - Fluidly scales one or more properties of `$color`. - - Each keyword argument must be a number between `-100%` and `100%` (inclusive). - This indicates how far the corresponding property should be moved from its - original position towards the maximum (if the argument is positive) or the - minimum (if the argument is negative). This means that, for example, - `$lightness: 50%` will make all colors `50%` closer to maximum lightness - without making them fully white. - - It's an error to specify an RGB property (`$red`, `$green`, and/or `$blue`) at - the same time as an HSL property (`$saturation`, and/or `$lightness`). - - See also: - - * [`adjust-color()`](#adjust-color) for changing a color's properties by fixed - amounts. - * [`change-color()`](#change-color) for setting a color's properties. - - <% example(autogen_css: false) do %> - @debug scale-color(#6b717f, $red: 15%); // #81717f - @debug scale-color(#d2e1dd, $lightness: -10%, $saturation: 10%); // #b3d4cb - @debug scale-color(#998099, $alpha: -40%); // rgba(153, 128, 153, 0.6) - === - @debug scale-color(#6b717f, $red: 15%) // #81717f - @debug scale-color(#d2e1dd, $lightness: -10%, $saturation: 10%) // #b3d4cb - @debug scale-color(#998099, $alpha: -40%) // rgba(153, 128, 153, 0.6) - <% end %> -<% end %> - - -<% function 'transparentize($color, $amount)', 'fade-out($color, $amount)', returns: 'color' do %> - Makes `$color` more transparent. - - The `$amount` must be a number between `0` and `1` (inclusive). Decreases the - alpha channel of `$color` by that amount. - - <% heads_up do %> - The `transparentize()` function decreases the alpha channel by a fixed amount, - which is often not the desired effect. To make a color a certain percentage more - transparent than it was before, use [`scale-color()`](#scale-color) instead. - - <% example(autogen_css: false) do %> - // rgba(#036, 0.3) has alpha 0.3, so when transparentize() subtracts 0.3 it - // returns a fully transparent color. - @debug transparentize(rgba(#036, 0.3), 0.3); // rgba(0, 51, 102, 0) - - // scale-color() instead makes it 30% more transparent than it was originally. - @debug scale-color(rgba(#036, 0.3), $alpha: -30%); // rgba(0, 51, 102, 0.21) - === - // rgba(#036, 0.3) has alpha 0.3, so when transparentize() subtracts 0.3 it - // returns a fully transparent color. - @debug transparentize(rgba(#036, 0.3), 0.3) // rgba(0, 51, 102, 0) - - // scale-color() instead makes it 30% more transparent than it was originally. - @debug scale-color(rgba(#036, 0.3), $alpha: -30%) // rgba(0, 51, 102, 0.21) - <% end %> - <% end %> - - <% example(autogen_css: false) do %> - @debug transparentize(rgba(#6b717f, 0.5), 0.2) // rgba(107, 113, 127, 0.3) - @debug fade-out(rgba(#e1d7d2, 0.5), 0.4) // rgba(225, 215, 210, 0.1) - @debug transparentize(rgba(#036, 0.3), 0.3) // rgba(0, 51, 102, 0) - === - @debug transparentize(rgba(#6b717f, 0.5), 0.2) // rgba(107, 113, 127, 0.3) - @debug fade-out(rgba(#e1d7d2, 0.5), 0.4) // rgba(225, 215, 210, 0.1) - @debug transparentize(rgba(#036, 0.3), 0.3) // rgba(0, 51, 102, 0) - <% end %> -<% end %> diff --git a/source/documentation/functions/css.html.md.erb b/source/documentation/functions/css.html.md.erb deleted file mode 100644 index 1fe5b811d..000000000 --- a/source/documentation/functions/css.html.md.erb +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: Plain CSS Functions -introduction: > - Any function call that's not either a [built-in](../functions) or - [user-defined](../at-rules/function) function is compiled to a plain CSS - function (unless it uses [Sass argument - syntax](../at-rules/function#arguments)). The arguments will be compiled to - CSS and included as-is in the function call. This ensures that Sass supports - all CSS functions without needing to release new versions every time a new one - is added. ---- - -<% example(autogen_css: false) do %> - @debug var(--main-bg-color); // var(--main-bg-color) - - $primary: #f2ece4; - $accent: #e1d7d2; - @debug radial-gradient($primary, $accent); // radial-gradient(#f2ece4, #e1d7d2) - === - @debug var(--main-bg-color) // var(--main-bg-color) - - $primary: #f2ece4 - $accent: #e1d7d2 - @debug radial-gradient($primary, $accent) // radial-gradient(#f2ece4, #e1d7d2) -<% end %> - -<% heads_up do %> - Because any unknown function will be compiled to CSS, it's easy to miss when - you typo a function name. Consider running a [CSS linter][] on your - stylesheet's output to be notified when this happens! - - [CSS linter]: https://stylelint.io/ -<% end %> - -<% fun_fact do %> - Some CSS functions, like `calc()` and `element()` have unusual syntax. Sass - [parses these functions specially][] as [unquoted strings][]. - - [parses these functions specially]: ../syntax/special-functions - [unquoted strings]: ../values/strings#unquoted -<% end %> diff --git a/source/documentation/functions/list.html.md.erb b/source/documentation/functions/list.html.md.erb deleted file mode 100644 index cb1013e59..000000000 --- a/source/documentation/functions/list.html.md.erb +++ /dev/null @@ -1,203 +0,0 @@ ---- -title: List Functions ---- - -<% fun_fact do %> - In Sass, every [map][] counts as a list that contains a two-element list for - each key/value pair. For example, `(1: 2, 3: 4)` counts as `(1 2, 3 4)`. So - all these functions work for maps as well! - - [map]: ../values/maps - - Individual values also count as lists. All these functions treat `1px` as a - list that contains the value `1px`. -<% end %> - - -<% function 'append($list, $val, $separator: auto)', returns: 'list' do %> - Returns a copy of `$list` with `$val` added to the end. - - If `$separator` is `comma`, the returned list is comma-separted. If it's - `space`, the returned list is space-separated. If it's `auto` (the default), the - returned list will use the same separator as `$list` (or `space` if `$list` - doesn't have a separator). Other values aren't allowed. - - [separator]: ../values/lists - - Note that unlike [`join()`](#join), if `$val` is a list it's nested within the - returned list rather than having all its elements added to the returned list. - - <% example(autogen_css: false) do %> - @debug append(10px 20px, 30px); // 10px 20px 30px - @debug append((blue, red), green); // blue, red, green - @debug append(10px 20px, 30px 40px); // 10px 20px (30px 40px) - @debug append(10px, 20px, $separator: comma); // 10px, 20px - @debug append((blue, red), green, $separator: space); // blue red green - === - @debug append(10px 20px, 30px) // 10px 20px 30px - @debug append((blue, red), green) // blue, red, green - @debug append(10px 20px, 30px 40px) // 10px 20px (30px 40px) - @debug append(10px, 20px, $separator: comma) // 10px, 20px - @debug append((blue, red), green, $separator: space) // blue red green - <% end %> -<% end %> - - -<% function 'index($list, $value)', returns: 'number | null' do %> - Returns the [index][] of `$value` in `$list`. - - [index]: ../values/lists#indexes - - If `$value` doesn't appear in `$list`, this returns [`null`][]. If `$value` - appears multiple times in `$list`, this returns the index of its first - appearance. - - [`null`]: ../values/null - - <%= partial 'code-snippets/example-list-index' %> -<% end %> - - -<% function 'is-bracketed($list)', returns: 'boolean' do %> - Returns whether `$list` has square brackets. - - <% example(autogen_css: false) do %> - @debug is-bracketed(1px 2px 3px); // false - @debug is-bracketed([1px, 2px, 3px]); // true - === - @debug is-bracketed(1px 2px 3px) // false - @debug is-bracketed([1px, 2px, 3px]) // true - <% end %> -<% end %> - - -<% function 'join($list1, $list2, $separator: auto, $bracketed: auto)', returns: 'list' do %> - Returns a new list containing the elements of `$list1` followed by the elements - of `$list2`. - - <% heads_up do %> - Because individual values count as single-element lists, it's possible to - use `join()` to add a value to the end of a list. However, *this is not - recommended*, since if that value is a list it will be concatenated, which - is probably not what you're expecting. - - Use [`append()`](#append) instead to add a single value to a list. Only use - `join()` to combine two lists together into one. - <% end %> - - If `$separator` is `comma`, the returned list is comma-separted. If it's - `space`, the returned list is space-separated. If it's `auto` (the default), - the returned list will use the same separator as `$list1` if it has a - separator, or else `$list2` if it has a separator, or else `space`. Other - values aren't allowed. - - If `$bracketed` is `true`, the returned list has square brackets. If it's - `false`, the returned list has no brackets. If it's `auto` (the default), the - returned list will be bracketed if `$list1` is. Other values aren't allowed. - - <% example(autogen_css: false) do %> - @debug join(10px 20px, 30px 40px); // 10px 20px 30px 40px - @debug join((blue, red), (#abc, #def)); // blue, red, #abc, #def - @debug join(10px, 20px); // 10px 20px - @debug join(10px, 20px, $separator: comma); // 10px, 20px - @debug join((blue, red), (#abc, #def), $separator: space); // blue red #abc #def - @debug join([10px], 20px); // [10px 20px] - @debug join(10px, 20px, $bracketed: true); // [10px 20px] - === - @debug join(10px 20px, 30px 40px) // 10px 20px 30px 40px - @debug join((blue, red), (#abc, #def)) // blue, red, #abc, #def - @debug join(10px, 20px) // 10px 20px - @debug join(10px, 20px, comma) // 10px, 20px - @debug join((blue, red), (#abc, #def), space) // blue red #abc #def - @debug join([10px], 20px) // [10px 20px] - @debug join(10px, 20px, $bracketed: true) // [10px 20px] - <% end %> -<% end %> - - -<% function 'length($list)', returns: 'number' do %> - Returns the length of `$list`. - - This can also return the number of pairs in a map. - - <% example(autogen_css: false) do %> - @debug length(10px); // 1 - @debug length(10px 20px 30px); // 3 - @debug length((width: 10px, height: 20px)); // 2 - === - @debug length(10px) // 1 - @debug length(10px 20px 30px) // 3 - @debug length((width: 10px, height: 20px)) // 2 - <% end %> -<% end %> - - -<% function 'list-separator($list)', returns: 'unquoted string' do %> - Returns the name of the separator used by `$list`, either `space` or `comma`. - - If `$list` doesn't have a separator, returns `space`. - - <% example(autogen_css: false) do %> - @debug list-separator(1px 2px 3px); // space - @debug list-separator(1px, 2px, 3px); // comma - @debug list-separator('Helvetica'); // space - @debug list-separator(()); // space - === - @debug list-separator(1px 2px 3px) // space - @debug list-separator(1px, 2px, 3px) // comma - @debug list-separator('Helvetica') // space - @debug list-separator(()) // space - <% end %> -<% end %> - - -<% function 'nth($list, $n)' do %> - Returns the element of `$list` at [index][] `$n`. - - [index]: ../values/lists#indexes - - If `$n` is negative, it counts from the end of `$list`. Throws an error if - there is no element at index `$n`. - - <%= partial 'code-snippets/example-list-nth' %> -<% end %> - - -<% function 'set-nth($list, $n, $value)', returns: 'list' do %> - Returns a copy of `$list` with the element at [index][] `$n` replaced with - `$value`. - - [index]: ../values/lists#indexes - - If `$n` is negative, it counts from the end of `$list`. Throws an error if - there is no existing element at index `$n`. - - <% example(autogen_css: false) do %> - @debug set-nth(10px 20px 30px, 1, 2em); // 2em 20px 30px - @debug set-nth(10px 20px 30px, -1, 8em); // 10px, 20px, 8em - @debug set-nth((Helvetica, Arial, sans-serif), 3, Roboto); // Helvetica, Arial, Roboto - === - @debug set-nth(10px 20px 30px, 1, 2em); // 2em 20px 30px - @debug set-nth(10px 20px 30px, -1, 8em); // 10px, 20px, 8em - @debug set-nth((Helvetica, Arial, sans-serif), 3, Roboto); // Helvetica, Arial, Roboto - <% end %> -<% end %> - - -<% function 'zip($lists...)', returns: 'list' do %> - Combines every list in `$lists` into a single list of sub-lists. - - Each element in the returned list contains all the elements at that position - in `$lists`. The returned list is as long as the shortest list in `$lists`. - - The returned list is always comma-separated and the sub-lists are always - space-separated. - - <% example(autogen_css: false) do %> - @debug zip(10px 50px 100px, short mid long); // 10px short, 50px mid, 100px long - @debug zip(10px 50px 100px, short mid); // 10px short, 50px mid - === - @debug zip(10px 50px 100px, short mid long) // 10px short, 50px mid, 100px long - @debug zip(10px 50px 100px, short mid) // 10px short, 50px mid - <% end %> -<% end %> diff --git a/source/documentation/functions/math.html.erb b/source/documentation/functions/math.html.erb deleted file mode 100644 index 0761ba741..000000000 --- a/source/documentation/functions/math.html.erb +++ /dev/null @@ -1,205 +0,0 @@ ---- -title: Number Functions ---- - -<% function 'abs($number)', returns: 'number' do %> - Returns the [absolute value][] of `$number`. If `$number` is negative, this - returns `-$number`, and if `$number` is positive, it returns `$number` as-is. - - [absolute value]: https://en.wikipedia.org/wiki/Absolute_value - - <% example(autogen_css: false) do %> - @debug abs(10px); // 10px - @debug abs(-10px); // 10px - === - @debug abs(10px) // 10px - @debug abs(-10px) // 10px - <% end %> -<% end %> - - -<% function 'ceil($number)', returns: 'number' do %> - Rounds `$number` up to the next highest whole number. - - <% example(autogen_css: false) do %> - @debug ceil(4); // 4 - @debug ceil(4.2); // 5 - @debug ceil(4.9); // 5 - === - @debug ceil(4) // 4 - @debug ceil(4.2) // 5 - @debug ceil(4.9) // 5 - <% end %> -<% end %> - - -<% function 'comparable($number1, $number2)', returns: 'boolean' do %> - Returns whether `$number1` and `$number2` have compatible units. - - If this returns `true`, `$number1` and `$number2` can safely be [added][], - [subtracted][], and [compared][]. Otherwise, doing so will produce errors. - - [added]: ../operators/numeric - [subtracted]: ../operators/numeric - [compared]: ../operators/relational - - <% example(autogen_css: false) do %> - @debug comparable(2px, 1px); // true - @debug comparable(100px, 3em); // false - @debug comparable(10cm, 3mm); // true - === - @debug comparable(2px, 1px) // true - @debug comparable(100px, 3em) // false - @debug comparable(10cm, 3mm) // true - <% end %> -<% end %> - - -<% function 'floor($number)', returns: 'number' do %> - Rounds `$number` down to the next lowest whole number. - - <% example(autogen_css: false) do %> - @debug floor(4); // 4 - @debug floor(4.2); // 4 - @debug floor(4.9); // 4 - === - @debug floor(4) // 4 - @debug floor(4.2) // 4 - @debug floor(4.9) // 4 - <% end %> -<% end %> - - -<% function 'max($number...)', returns: 'number' do %> - Returns the highest of one or more numbers. A list of numbers can be passed - [using `...`][]. - - [using `...`]: ../at-rules/function#passing-arbitrary-arguments - - <% example(autogen_css: false) do %> - @debug max(1px, 4px); // 4px - - $widths: 50px, 30px, 100px; - @debug max($widths...); // 100px - === - @debug max(1px, 4px) // 4px - - $widths: 50px, 30px, 100px - @debug max($widths...) // 100px - <% end %> -<% end %> - - -<% function 'min($number...)', returns: 'number' do %> - Returns the lowest of one or more numbers. A list of numbers can be passed - [using `...`][]. - - [using `...`]: ../at-rules/function#passing-arbitrary-arguments - - <% example(autogen_css: false) do %> - @debug min(1px, 4px); // 1px - - $widths: 50px, 30px, 100px; - @debug min($widths...); // 30px - === - @debug min(1px, 4px) // 1px - - $widths: 50px, 30px, 100px - @debug min($widths...) // 30px - <% end %> -<% end %> - - -<% function 'percentage($number)', returns: 'number' do %> - Converts a unitless `$number` (usually a decimal between 0 and 1) to a - percentage. - - <% fun_fact do %> - This function is identical to `$number * 100%`. - <% end %> - - <% example(autogen_css: false) do %> - @debug percentage(0.2); // 20% - @debug percentage(100px / 50px); // 200% - === - @debug percentage(0.2) // 20% - @debug percentage(100px / 50px) // 200% - <% end %> -<% end %> - - -<% function 'random($limit: null)', returns: 'number' do %> - If `$limit` is [`null`][], returns a random decimal number between 0 and 1. - - [`null`]: ../values/null - - <% example(autogen_css: false) do %> - @debug random(); // 0.2821251858 - @debug random(); // 0.6221325814 - === - @debug random() // 0.2821251858 - @debug random() // 0.6221325814 - <% end %> - - * * * - - If `$limit` is a number greater than or equal to 1, returns a random whole - number between 1 and `$limit`. - - <% example(autogen_css: false) do %> - @debug random(10); // 4 - @debug random(10000); // 5373 - === - @debug random(10) // 4 - @debug random(10000) // 5373 - <% end %> -<% end %> - - -<% function 'round($number)', returns: 'number' do %> - Rounds `$number` to the nearest whole number. - - <% example(autogen_css: false) do %> - @debug round(4); // 4 - @debug round(4.2); // 4 - @debug round(4.9); // 5 - === - @debug round(4) // 4 - @debug round(4.2) // 4 - @debug round(4.9) // 5 - <% end %> -<% end %> - - -<% function 'unit($number)', returns: 'quoted string' do %> - Returns a string representation of `$number`'s units. - - <% heads_up do %> - This function is intended for debugging; its output format is not guaranteed - to be consistent across Sass versions or implementations. - <% end %> - - <% example(autogen_css: false) do %> - @debug unit(100); // "" - @debug unit(100px); // "px" - @debug unit(5px * 10px); // "px*px" - @debug unit(5px / 1s); // "px/s" - === - @debug unit(100) // "" - @debug unit(100px) // "px" - @debug unit(5px * 10px) // "px*px" - @debug unit(5px / 1s) // "px/s" - <% end %> -<% end %> - -<% function 'unitless($number)', returns: 'boolean' do %> - Returns whether `$number` has no units. - - <% example(autogen_css: false) do %> - @debug unitless(100); // true - @debug unitless(100px); // false - === - @debug unitless(100) // true - @debug unitless(100px) // false - <% end %> -<% end %> diff --git a/source/documentation/functions/meta.html.md.erb b/source/documentation/functions/meta.html.md.erb deleted file mode 100644 index 93c89913a..000000000 --- a/source/documentation/functions/meta.html.md.erb +++ /dev/null @@ -1,275 +0,0 @@ ---- -title: Introspection Functions ---- - -<% function 'call($function, $args...)' do %> - <%= partial 'documentation/snippets/call-impl-status' %> - - Invokes `$function` with `$args` and returns the result. - - The `$function` should be a [function][] returned by [`get-function()`][]. - - [function]: ../values/functions - [`get-function()`]: #get-function - - <%= partial 'code-snippets/example-first-class-function' %> -<% end %> - - -<% function 'content-exists()', returns: 'boolean' do %> - Returns whether the current mixin was passed a [`@content` block][]. - - [`@content` block]: ../at-rules/mixin#content-blocks - - Throws an error if called outside of a mixin. - - <% example(autogen_css: false) do %> - @mixin debug-content-exists { - @debug content-exists(); - @content; - } - - @include debug-content-exists; // false - @include debug-content-exists { // true - // Content! - } - === - @mixin debug-content-exists - @debug content-exists() - @content - - - @include debug-content-exists // false - @include debug-content-exists // true - // Content! - <% end %> -<% end %> - - -<% function 'feature-exists($feature)', returns: 'boolean' do %> - Returns whether the current Sass implementation supports `$feature`. - - The `$feature` must be a string. The currently recognized features are: - - * `global-variable-shadowing`, which means that a local variable will - [shadow][] a global variable unless it has the `!global` flag. - * `extend-selector-pseudoclass`, which means that the [`@extend` rule][] will - affect selectors nested in pseudo-classes like `:not()`. - * `units-level3`, which means that [unit arithmetic][] supports units defined - in [CSS Values and Units Level 3][]. - * `at-error`, which means that the [`@error` rule][] is supported. - * `custom-property`, which means that [custom property declaration][] values - don't support any [expressions][] other than [interpolation][]. - - [shadow]: ../variables#shadowing - [`@extend` rule]: ../at-rules/extend - [unit arithmetic]: ../values/numbers#units - [CSS Values and Units Level 3]: http://www.w3.org/TR/css3-values - [`@error` rule]: ../at-rules/error - [custom property declaration]: ../style-rules/declarations#custom-properties - [expressions]: ../syntax/structure#expressions - [interpolation]: ../interpolation - - Returns `false` for any unrecognized `$feature`. - - <% example(autogen_css: false) do %> - @debug feature-exists("at-error"); // true - @debug feature-exists("unrecognized"); // false - === - @debug feature-exists("at-error") // true - @debug feature-exists("unrecognized") // false - <% end %> -<% end %> - - -<% function 'function-exists($name)', returns: 'boolean' do %> - Returns whether a function named `$name` is defined, either as a built-in - function or a user-defined function. - - <% example(autogen_css: false) do %> - @debug function-exists("scale-color"); // true - @debug function-exists("add"); // false - - @function add($num1, $num2) { - @return $num1 + $num2; - } - @debug function-exists("add"); // true - === - @debug function-exists("scale-color") // true - @debug function-exists("add") // false - - @function add($num1, $num2) - @return $num1 + $num2 - - @debug function-exists("add") // true - <% end %> -<% end %> - - -<% function 'get-function($name, $css: false)', returns: 'function' do %> - Returns the [function][] named `$name`. - - [function]: ../values/functions - - This can access both built-in and [user-defined][] functions. By default, it - throws an error if `$name` doesn't refer to either a built-in or user-defined - function. However, if `$css` is `true`, it instead returns a - [plain CSS function][]. - - [user-defined]: ../at-rules/function - [plain CSS function]: css - - The returned function can be called using [`call()`](#call). - - <%= partial 'code-snippets/example-first-class-function' %> -<% end %> - - -<% function 'global-variable-exists($name)', returns: 'boolean' do %> - Returns whether a [global variable][] named `$name` (without the `$`) exists. - - [global variable]: ../variables#scope - - See also [`variable-exists()`](#variable-exists). - - <% example(autogen_css: false) do %> - @debug global-variable-exists("var1"); // false - - $var1: value; - @debug global-variable-exists("var1"); // true - - h1 { - // $var2 is local. - $var2: value; - @debug global-variable-exists("var2"); // false - } - === - @debug global-variable-exists("var1") // false - - $var1: value - @debug global-variable-exists("var1") // true - - h1 - // $var2 is local. - $var2: value - @debug global-variable-exists("var2") // false - <% end %> -<% end %> - - -<% function 'inspect($value)', returns: 'unquoted string' do %> - - Returns a string representation of `$value`. - - Returns a representation of *any* Sass value, not just those that can be - represented in CSS. As such, its return value is not guaranteed to be valid - CSS. - - <% heads_up do %> - This function is intended for debugging; its output format is not guaranteed - to be consistent across Sass versions or implementations. - <% end %> - - <% example(autogen_css: false) do %> - @debug inspect(10px 20px 30px); // unquote("10px 20px 30px") - @debug inspect(("width": 200px)); // unquote('("width": 200px)') - @debug inspect(null); // unquote("null") - @debug inspect("Helvetica"); // unquote('"Helvetica"') - === - @debug inspect(10px 20px 30px) // unquote("10px 20px 30px") - @debug inspect(("width": 200px)) // unquote('("width": 200px)') - @debug inspect(null) // unquote("null") - @debug inspect("Helvetica") // unquote('"Helvetica"') - <% end %> -<% end %> - - -<% function 'mixin-exists($name)', returns: 'boolean' do %> - Returns whether a [mixin][] named `$name` exists. - - [mixin]: ../at-rules/mixin - - <% example(autogen_css: false) do %> - @debug mixin-exists("shadow-none"); // false - - @mixin shadow-none { - box-shadow: none; - } - - @debug mixin-exists("shadow-none"); // true - === - @debug mixin-exists("shadow-none") // false - - @mixin shadow-none - box-shadow: none - - - @debug mixin-exists("shadow-none") // true - <% end %> -<% end %> - - -<% function 'type-of($value)', returns: 'unquoted string' do %> - Returns the type of `$value`. - - This can return the following values: - - * [`number`](../values/numbers) - * [`string`](../values/strings) - * [`color`](../values/colors) - * [`list`](../values/lists) - * [`map`](../values/maps) - * [`bool`](../values/booleans) - * [`null`](../values/null) - * [`function`](../values/functions) - * [`arglist`](../values/lists#argument-lists) - - New possible values may be added in the future. It may return either `list` or - `map` for `()`, depending on whether or not it was returned by a - [map function][]. - - [map function]: map - - <% example(autogen_css: false) do %> - @debug type-of(10px); // number - @debug type-of(10px 20px 30px); // list - @debug type-of(()); // list - === - @debug type-of(10px) // number - @debug type-of(10px 20px 30px) // list - @debug type-of(()) // list - <% end %> -<% end %> - - -<% function 'variable-exists($name)', returns: 'boolean' do %> - Returns whether a variable named `$name` (without the `$`) exists in the - current [scope][]. - - [scope]: ../variables#scope - - See also [`global-variable-exists()`](#global-variable-exists). - - <% example(autogen_css: false) do %> - @debug variable-exists("var1"); // false - - $var1: value; - @debug variable-exists("var1"); // true - - h1 { - // $var2 is local. - $var2: value; - @debug variable-exists("var2"); // true - } - === - @debug variable-exists("var1") // false - - $var1: value - @debug variable-exists("var1") // true - - h1 - // $var2 is local. - $var2: value - @debug variable-exists("var2") // true - <% end %> -<% end %> diff --git a/source/documentation/functions/string.html.md.erb b/source/documentation/functions/string.html.md.erb deleted file mode 100644 index 7bcea53b8..000000000 --- a/source/documentation/functions/string.html.md.erb +++ /dev/null @@ -1,149 +0,0 @@ ---- -title: String Functions ---- - -<% function 'quote($string)', returns: 'string' do %> - Returns `$string` as a quoted string. - - <% example(autogen_css: false) do %> - @debug quote(Helvetica); // "Helvetica" - @debug quote("Helvetica"); // "Helvetica" - === - @debug quote(Helvetica) // "Helvetica" - @debug quote("Helvetica") // "Helvetica" - <% end %> -<% end %> - - -<% function 'str-index($string, $substring)', returns: 'number' do %> - Returns the first [index][] of `$substring` in `$string`, or `null` if - `$string` doesn't contain `$substring`. - - [index]: ../values/strings#string-indexes - - <% example(autogen_css: false) do %> - @debug str-index("Helvetica Neue", "Helvetica"); // 1 - @debug str-index("Helvetica Neue", "Neue"); // 11 - === - @debug str-index("Helvetica Neue", "Helvetica") // 1 - @debug str-index("Helvetica Neue", "Neue") // 11 - <% end %> -<% end %> - - -<% function 'str-insert($string, $insert, $index)', returns: 'string' do %> - Returns a copy of `$string` with `$insert` inserted at [`$index`][]. - - [`$index`]: ../values/strings#string-indexes - - <% example(autogen_css: false) do %> - @debug str-insert("Roboto Bold", " Mono", 7); // "Roboto Mono Bold" - @debug str-insert("Roboto Bold", " Mono", -6); // "Roboto Mono Bold" - === - @debug str-insert("Roboto Bold", " Mono", 7) // "Roboto Mono Bold" - @debug str-insert("Roboto Bold", " Mono", -6) // "Roboto Mono Bold" - <% end %> - - If of `$index` is higher than the length of `$string`, `$insert` is added to - the end. If `$index` is smaller than the negative length of the string, - `$insert` is added to the beginning. - - <% example(autogen_css: false) do %> - @debug str-insert("Roboto", " Bold", 100); // "Roboto Bold" - @debug str-insert("Bold", "Roboto ", -100); // "Roboto Bold" - === - @debug str-insert("Roboto", " Bold", 100) // "Roboto Bold" - @debug str-insert("Bold", "Roboto ", -100) // "Roboto Bold" - <% end %> -<% end %> - - -<% function 'str-length($string)', returns: 'number' do %> - Returns the number of characters in `$string`. - - <% example(autogen_css: false) do %> - @debug str-length("Helvetica Neue"); // 14 - @debug str-length(bold); // 4 - @debug str-index(""); // 0 - === - @debug str-length("Helvetica Neue") // 14 - @debug str-length(bold) // 4 - @debug str-index("") // 0 - <% end %> -<% end %> - - -<% function 'str-slice($string, $start-at, $end-at: -1)', returns: 'string' do %> - Returns the slice of `$string` starting at [index][] `$start-at` and ending at - index `$end-at` (both inclusive). - - [index]: ../values/strings#string-indexes - - <% example(autogen_css: false) do %> - @debug str-slice("Helvetica Neue", 11); // "Neue" - @debug str-slice("Helvetica Neue", 1, 3); // "Hel" - @debug str-slice("Helvetica Neue", 1, -6); // "Helvetica" - === - @debug str-slice("Helvetica Neue", 11) // "Neue" - @debug str-slice("Helvetica Neue", 1, 3) // "Hel" - @debug str-slice("Helvetica Neue", 1, -6) // "Helvetica" - <% end %> -<% end %> - - -<% function 'to-upper-case($string)', returns: 'string' do %> - Returns a copy of `$string` with the [ASCII][] letters converted to upper case. - - [ASCII]: https://en.wikipedia.org/wiki/ASCII - - <% example(autogen_css: false) do %> - @debug to-upper-case("Bold"); // "BOLD" - @debug to-upper-case(sans-serif); // SANS-SERIF - === - @debug to-upper-case("Bold") // "BOLD" - @debug to-upper-case(sans-serif) // SANS-SERIF - <% end %> -<% end %> - - -<% function 'to-lower-case($string)', returns: 'string' do %> - Returns a copy of `$string` with the [ASCII][] letters converted to lower case. - - [ASCII]: https://en.wikipedia.org/wiki/ASCII - - <% example(autogen_css: false) do %> - @debug to-lower-case("Bold"); // "bold" - @debug to-lower-case(SANS-SERIF); // sans-serif - === - @debug to-lower-case("Bold") // "bold" - @debug to-lower-case(SANS-SERIF) // sans-serif - <% end %> -<% end %> - - -<% function 'unique-id()', returns: 'string' do %> - Returns a randomly-generated unquoted string that's guaranteed to be a valid - CSS identifier and to be unique within the current Sass compilation. - - <% example(autogen_css: false) do %> - @debug unique-id(); // uabtrnzug - @debug unique-id(); // u6w1b1def - === - @debug unique-id(); // uabtrnzug - @debug unique-id(); // u6w1b1def - <% end %> -<% end %> - - -<% function 'unquote()', returns: 'string' do %> - Returns `$string` as an unquoted string. This can produce strings that aren't - valid CSS, so use with caution. - - <% example(autogen_css: false) do %> - @debug unquote("Helvetica"); // Helvetica - @debug unquote(".widget:hover"); // .widget:hover - === - @debug unquote("Helvetica") // Helvetica - @debug unquote(".widget:hover") // .widget:hover - <% end %> -<% end %> diff --git a/source/documentation/index.html.md b/source/documentation/index.html.md index e4420300b..8214f7ecb 100644 --- a/source/documentation/index.html.md +++ b/source/documentation/index.html.md @@ -5,7 +5,7 @@ introduction: > [variables](/documentation/variables), [nested rules](/documentation/style-rules#nesting), [mixins](/documentation/at-rules/mixin), - [functions](/documentation/functions), and more, all with a fully + [functions](/documentation/modules), and more, all with a fully CSS-compatible syntax. Sass helps keep large stylesheets well-organized and makes it easy to share design within and across projects. overview: true @@ -15,7 +15,7 @@ overview: true tutorial](/guide). * If you want to look up a built-in Sass function, look no further than [the - function reference](/documentation/functions). + built-in module reference](/documentation/modules). * If you're calling Sass from JavaScript, you may want the [JS API documentation][js]. diff --git a/source/documentation/interpolation.html.md.erb b/source/documentation/interpolation.html.md.erb index 0c45a0668..1706e7838 100644 --- a/source/documentation/interpolation.html.md.erb +++ b/source/documentation/interpolation.html.md.erb @@ -15,7 +15,7 @@ introduction: > * [Plain CSS `@import`s](at-rules/import#plain-css-imports) * [Quoted or unquoted strings](values/strings) * [Special functions](syntax/special-functions) -* [Plain CSS function names](functions/css) +* [Plain CSS function names](at-rules/function#plain-css-functions) * [Loud comments](syntax/comments) <% example do %> @@ -144,8 +144,8 @@ them into style rules. <% heads_up do %> While it's tempting to use this feature to convert quoted strings to unquoted - strings, it's a lot clearer to use the [`unquote()` function][]. Instead of - `#{$string}`, write `unquote($string)`! + strings, it's a lot clearer to use the [`string.unquote()` function][]. + Instead of `#{$string}`, write `string.unquote($string)`! - [`unquote()` function]: functions/string#unquote + [`string.unquote()` function]: modules/string#unquote <% end %> diff --git a/source/documentation/js-api.html.md.erb b/source/documentation/js-api.html.md.erb index 9441eb4f2..fd7944629 100644 --- a/source/documentation/js-api.html.md.erb +++ b/source/documentation/js-api.html.md.erb @@ -137,8 +137,8 @@ console.log(result.map.toString()); An array of the absolute paths of all Sass files loaded during compilation. If a stylesheet was loaded from an [importer][] that returned the stylesheet's -contents, the raw strings of that stylesheet's `@import` is included in this -array. +contents, the raw string of the `@use` or `@import` that loaded that stylesheet +is included in this array. [importer]: #importer @@ -188,9 +188,9 @@ provides the same information. The stylesheet where the error occurred. If the error occurred in a stylesheet loaded from disk, this is the absolute path of that stylesheet. If the error occurred in a stylesheet that was loaded from an [importer][] which returned the -stylesheet's contents, this is the raw string of that stylesheet's `@import`. If -it occurred in the contents of the [`data` option][], this is the string -`"stdin"`. +stylesheet's contents, this is the raw string of the `@use` or `@import` that +loaded that stylesheet. If it occurred in the contents of the [`data` option][], +this is the string `"stdin"`. #### `error.line` @@ -741,21 +741,23 @@ h1 { somewhere else to break it. <% end %> -This option defines one or more additional handlers for loading files when an -[`@import` rule][] is encountered. It can either be a single JavaScript -function, or an array of functions. These functions are always passed two -arguments: +This option defines one or more additional handlers for loading files when a +[`@use` rule] or an [`@import` rule][] is encountered. It can either be a single +JavaScript function, or an array of functions. These functions are always passed +two arguments: +[`@use` rule]: at-rules/use [`@import` rule]: at-rules/import -1. The `@import` rule's URL as a string, exactly as it appears in the +1. The `@use` or `@import` rule's URL as a string, exactly as it appears in the stylesheet. -2. A string identifying for the stylesheet that contained the `@import`. This - identifier's format depends on how that stylesheet was loaded: +2. A string identifying for the stylesheet that contained the `@use` or + `@import`. This identifier's format depends on how that stylesheet was + loaded: * If the stylesheet was loaded from the filesystem, it's the absolute path of its file. * If the stylesheet was loaded from an importer that returned its contents, - it's the URL of the `@import` rule that loaded it. + it's the URL of the `@use` or `@import` rule that loaded it. * If the stylesheet came from the [`data` option][], it's the string `"stdin"`. @@ -775,7 +777,7 @@ asynchronously pass the result of the import once it's complete. Imports are resolved by trying, in order: -* Loading a file relative to the file in which the `@import` appeared. +* Loading a file relative to the file in which the `@use` or `@import` appeared. * Each custom importer. @@ -793,7 +795,7 @@ sass.render({ // This importer uses the synchronous API, and can be passed to either // renderSync() or render(). function(url, prev) { - // This generates a stylesheet from scratch for `@import "big-headers"`. + // This generates a stylesheet from scratch for `@use "big-headers"`. if (url != "big-headers") return null; return { @@ -807,7 +809,7 @@ h1 { // This importer uses the asynchronous API, and can only be passed to // render(). function(url, prev, done) { - // Convert `@import "foo/bar"` to "node_modules/foo/sass/bar". + // Convert `@use "foo/bar"` to "node_modules/foo/sass/bar". var components = url.split('/'); var innerPath = components.slice(1).join('/'); done({ diff --git a/source/documentation/modules.html.md.erb b/source/documentation/modules.html.md.erb new file mode 100644 index 000000000..94ce09ee7 --- /dev/null +++ b/source/documentation/modules.html.md.erb @@ -0,0 +1,278 @@ +--- +title: Built-In Modules +introduction: > + Sass provides many built-in modules which contain useful functions (and the + occasional mixin). These modules can be loaded with the + [`@use` rule](at-rules/use) like any user-defined stylesheet, and their + functions can be called [like any other module + member](at-rules/use#loading-members). All built-in module URLs begin with + `sass:` to indicate that they're part of Sass itself. +overview: true +--- + +<% content_for :before_introduction do %> + <%= partial 'snippets/built-in-module-status' %> +<% end %> + +<% heads_up do %> + Before the Sass module system was introduced, all Sass functions were globally + available at all times. Many functions still have global aliases (these are + listed in their documentation). The Sass team discourages their use and will + eventually deprecate them, but for now they remain available for compatibility + with older Sass versions and with LibSass (which doesn't support the module + system yet). + + [A few functions][] are *only* available globally even in the new module + system, either because they have special evaluation behavior ([`if()`][]) or + because they add extra behavior on top of built-in CSS functions ([`rgb()`][] + and [`hsl()`][]). These will not be deprecated and can be used freely. + + [a few functions]: #global-functions + [`if()`]: #if + [`rgb()`]: #rgb + [`hsl()`]: #hsl +<% end %> + +<% example do %> + @use "sass:color"; + + .button { + $primary-color: #6b717f; + color: $primary-color; + border: 1px solid color.scale($primary-color, $lightness: 20%); + } + === + @use "sass:color" + + .button + $primary-color: #6b717f + color: $primary-color + border: 1px solid color.scale($primary-color, $lightness: 20%) + === + .button { + color: #6b717f; + border: 1px solid #878d9a; + } +<% end %> + +Sass provides the following built-in modules: + +* The [`sass:math` module][] provides functions that operate on [numbers][]. + +* The [`sass:string` module][] makes it easy to combine, search, or split apart + [strings][]. + +* The [`sass:color` module][] generates new [colors][] based on existing ones, + making it easy to build color themes. + +* The [`sass:list` module][] lets you access and modify values in [lists][]. + +* The [`sass:map` module][] makes it possible to look up the value associated + with a key in a [map][], and much more. + +* The [`sass:selector` module][] provides access to Sass's powerful selector + engine. + +* The [`sass:meta` module][] exposes the details of Sass's inner workings. + +[`sass:math` module]: modules/math +[numbers]: values/numbers +[`sass:string` module]: modules/string +[strings]: values/strings +[`sass:color` module]: modules/color +[colors]: values/colors +[`sass:list` module]: modules/list +[lists]: values/lists +[`sass:map` module]: modules/map +[map]: values/maps +[`sass:selector` module]: modules/selector +[`sass:meta` module]: modules/meta + +## Global Functions + +<% function 'hsl($hue $saturation $lightness)', + 'hsl($hue $saturation $lightness / $alpha)', + 'hsl($hue, $saturation, $lightness, $alpha: 1)', + 'hsla($hue $saturation $lightness)', + 'hsla($hue $saturation $lightness / $alpha)', + 'hsla($hue, $saturation, $lightness, $alpha: 1)', + returns: 'color' do %> + <% impl_status dart: '1.15.0', libsass: false, ruby: false, feature: "Level 4 Syntax" do %> + LibSass and Ruby Sass only support the following signatures: + + * `hsl($hue, $saturation, $lightness)` + * `hsla($hue, $saturation, $lightness, $alpha)` + + Note that for these implementations, the `$alpha` argument is *required* if + the function name `hsla()` is used, and *forbidden* if the function name + `hsl()` is used. + <% end %> + + <% impl_status dart: true, libsass: false, ruby: '3.7.0', feature: "Percent Alpha" do %> + LibSass and older versions of Ruby Sass don't support alpha values specified as + percentages. + <% end %> + + Returns a color with the given [hue, saturation, and lightness][] and the given + alpha channel. + + [hue, saturation, and lightness]: https://en.wikipedia.org/wiki/HSL_and_HSV + + The hue is a number between `0deg` and `360deg` (inclusive). The saturation + and lightness are numbers between `0%` and `100%` (inclusive). All these + numbers may be [unitless][]. The alpha channel can be specified as either a + unitless number between 0 and 1 (inclusive), or a percentage between `0%` and + `100%` (inclusive). + + [unitless]: values/numbers#units + + <% fun_fact do %> + You can pass [special functions][] like `calc()` or `var()` in place of any + argument to `hsl()`. You can even use `var()` in place of multiple + arguments, since it might be replaced by multiple values! When a color + function is called this way, it returns an unquoted string using the same + signature it was called with. + + [special functions]: syntax/special-functions + + <% example(autogen_css: false) do %> + @debug hsl(210deg 100% 20% / var(--opacity)); // hsl(210deg 100% 20% / var(--opacity)) + @debug hsla(var(--peach), 20%); // hsla(var(--peach), 20%) + === + @debug hsl(210deg 100% 20% / var(--opacity)) // hsl(210deg 100% 20% / var(--opacity)) + @debug hsla(var(--peach), 20%) // hsla(var(--peach), 20%) + <% end %> + <% end %> + + <% heads_up do %> + Sass's [special parsing rules][] for slash-separated values make it + difficult to pass variables for `$lightness` or `$alpha` when using the + `hsl($hue $saturation $lightness / $alpha)` signature. Consider using + `hsl($hue, $saturation, $lightness, $alpha)` instead. + + [special parsing rules]: operators/numeric#slash-separated-values + <% end %> + + <% example(autogen_css: false) do %> + @debug hsl(210deg 100% 20%); // #036 + @debug hsl(34, 35%, 92%); // #f2ece4 + @debug hsl(210deg 100% 20% / 50%); // rgba(0, 51, 102, 0.5) + @debug hsla(34, 35%, 92%, 0.2); // rgba(242, 236, 228, 0.2) + === + @debug hsl(210deg 100% 20%) // #036 + @debug hsl(34, 35%, 92%) // #f2ece4 + @debug hsl(210deg 100% 20% / 50%) // rgba(0, 51, 102, 0.5) + @debug hsla(34, 35%, 92%, 0.2) // rgba(242, 236, 228, 0.2) + <% end %> +<% end %> + + +<% function "if($condition, $if-true, $if-false)" do %> + Returns `$if-true` if `$condition` is [truthy][], and `$if-false` otherwise. + + This function is special in that it doesn't even evaluate the argument that + isn't returned, so it's safe to call even if the unused argument would throw an + error. + + [truthy]: at-rules/control/if#truthiness-and-falsiness + + <% example(autogen_css: false) do %> + @debug if(true, 10px, 15px); // 10px + @debug if(false, 10px, 15px); // 15px + @debug if(variable-defined($var), $var, null); // null + === + @debug if(true, 10px, 15px) // 10px + @debug if(false, 10px, 15px) // 15px + @debug if(variable-defined($var), $var, null) // null + <% end %> +<% end %> + + +<% function 'rgb($red $green $blue)', + 'rgb($red $green $blue / $alpha)', + 'rgb($red, $green, $blue, $alpha: 1)', + 'rgb($color, $alpha)', + 'rgba($red $green $blue)', + 'rgba($red $green $blue / $alpha)', + 'rgba($red, $green, $blue, $alpha: 1)', + 'rgba($color, $alpha)', + returns: 'color' do %> + <% impl_status dart: '1.15.0', libsass: false, ruby: false, feature: "Level 4 Syntax" do %> + LibSass and Ruby Sass only support the following signatures: + + * `rgb($red, $green, $blue)` + * `rgba($red, $green, $blue, $alpha)` + * `rgba($color, $alpha)` + + Note that for these implementations, the `$alpha` argument is *required* if + the function name `rgba()` is used, and *forbidden* if the function name + `rgb()` is used. + <% end %> + + <% impl_status dart: true, libsass: false, ruby: '3.7.0', feature: "Percent Alpha" do %> + LibSass and older versions of Ruby Sass don't support alpha values specified + as percentages. + <% end %> + + If `$red`, `$green`, `$blue`, and optionally `$alpha` are passed, returns a + color with the given red, green, blue, and alpha channels. + + Each channel can be specified as either a [unitless][] number between 0 and + 255 (inclusive), or a percentage between `0%` and `100%` (inclusive). The + alpha channel can be specified as either a unitless number between 0 and 1 + (inclusive), or a percentage between `0%` and `100%` (inclusive). + + [unitless]: values/numbers#units + + <% fun_fact do %> + You can pass [special functions][] like `calc()` or `var()` in place of any + argument to `rgb()`. You can even use `var()` in place of multiple + arguments, since it might be replaced by multiple values! When a color + function is called this way, it returns an unquoted string using the same + signature it was called with. + + [special functions]: syntax/special-functions + + <% example(autogen_css: false) do %> + @debug rgb(0 51 102 / var(--opacity)); // rgb(0 51 102 / var(--opacity)) + @debug rgba(var(--peach), 0.2); // rgba(var(--peach), 0.2) + === + @debug rgb(0 51 102 / var(--opacity)) // rgb(0 51 102 / var(--opacity)) + @debug rgba(var(--peach), 0.2) // rgba(var(--peach), 0.2) + <% end %> + <% end %> + + <% heads_up do %> + Sass's [special parsing rules][] for slash-separated values make it + difficult to pass variables for `$blue` or `$alpha` when using the + `rgb($red $green $blue / $alpha)` signature. Consider using + `hsl($red, $green, $blue, $alpha)` instead. + + [special parsing rules]: operators/numeric#slash-separated-values + <% end %> + + <% example(autogen_css: false) do %> + @debug rgb(0 51 102); // #036 + @debug rgb(95%, 92.5%, 89.5%); // #f2ece4 + @debug rgb(0 51 102 / 50%); // rgba(0, 51, 102, 0.5) + @debug rgba(95%, 92.5%, 89.5%, 0.2); // rgba(242, 236, 228, 0.2) + === + @debug rgb(0 51 102) // #036 + @debug rgb(95%, 92.5%, 89.5%) // #f2ece4 + @debug rgb(0 51 102 / 50%) // rgba(0, 51, 102, 0.5) + @debug rgba(95%, 92.5%, 89.5%, 0.2) // rgba(242, 236, 228, 0.2) + <% end %> + + --- + + If `$color` and `$alpha` are passed, this returns `$color` with the given + `$alpha` channel instead of its original alpha channel. + + <% example(autogen_css: false) do %> + @debug rgb(#f2ece4, 50%); // rgba(242, 236, 228, 0.5); + @debug rgba(rgba(0, 51, 102, 0.5), 1); // #003366 + === + @debug rgb(#f2ece4, 50%) // rgba(242, 236, 228, 0.5) + @debug rgba(rgba(0, 51, 102, 0.5), 1) // #003366 + <% end %> +<% end %> diff --git a/source/documentation/modules/color.html.md.erb b/source/documentation/modules/color.html.md.erb new file mode 100644 index 000000000..75dddaf5d --- /dev/null +++ b/source/documentation/modules/color.html.md.erb @@ -0,0 +1,766 @@ +--- +title: sass:color +--- + +<%= partial '../snippets/built-in-module-status' %> + +<% function < + Increases or decreases one or more properties of `$color` by fixed amounts. + + Adds the value passed for each keyword argument to the corresponding property + of the color, and returns the adjusted color. It's an error to specify an RGB + property (`$red`, `$green`, and/or `$blue`) at the same time as an HSL + property (`$hue`, `$saturation`, and/or `$lightness`). + + All optional arguments must be numbers. The `$red`, `$green`, and `$blue` + arguments must be [unitless][] and between -255 and 255 (inclusive). The + `$hue` argument must have either the unit `deg` or no unit. The `$saturation` + and `$lightness` arguments must be between `-100%` and `100%` (inclusive), and + may be unitless. The `$alpha` argument must be unitless and between -1 and 1 + (inclusive). + + [unitless]: ../values/numbers#units + + See also: + + * [`color.scale()`](#scale) for fluidly scaling a color's properties. + * [`color.change()`](#change) for setting a color's properties. + + <% example(autogen_css: false) do %> + @debug color.adjust(#6b717f, $red: 15); // #7a717f + @debug color.adjust(#d2e1dd, $red: -10, $blue: 10); // #c8e1e7 + @debug color.adjust(#998099, $lightness: -30%, $alpha: -0.4); // rgba(71, 57, 71, 0.6) + === + @debug color.adjust(#6b717f, $red: 15) // #7a717f + @debug color.adjust(#d2e1dd, $red: -10, $blue: 10) // #c8e1e7 + @debug color.adjust(#998099, $lightness: -30%, $alpha: -0.4) // rgba(71, 57, 71, 0.6) + <% end %> +<% end %> + + +<% function 'adjust-hue($color, $degrees)', returns: 'color' do %> + Increases or decreases `$color`'s hue. + + The `$hue` must be a number between `-360deg` and `360deg` (inclusive) to add + to `$color`'s hue. It may be [unitless][]. + + [unitless]: ../values/numbers#units + + See also [`color.adjust()`](#adjust), which can adjust any property of a + color. + + <% heads_up do %> + Because `adjust-hue()` is redundant with [`adjust()`](#adjust), it's not + included directly in the new module system. Instead of + `adjust-hue($color, $amount)`, you can write + [`color.adjust($color, $hue: $amount)`](#adjust). + <% end %> + + <% example(autogen_css: false) do %> + // Hue 222deg becomes 282deg. + @debug adjust-hue(#6b717f, 60deg); // #796b7f + + // Hue 164deg becomes 104deg. + @debug adjust-hue(#d2e1dd, -60deg); // #d6e1d2 + + // Hue 210deg becomes 255deg. + @debug adjust-hue(#036, 45); // #1a0066 + === + // Hue 222deg becomes 282deg. + @debug adjust-hue(#6b717f, 60deg) // #796b7f + + // Hue 164deg becomes 104deg. + @debug adjust-hue(#d2e1dd, -60deg) // #d6e1d2 + + // Hue 210deg becomes 255deg. + @debug adjust-hue(#036, 45) // #1a0066 + <% end %> +<% end %> + + +<% function 'color.alpha($color)', + 'alpha($color)', + 'opacity($color)', + returns: 'number' do %> + Returns the alpha channel of `$color` as a number between 0 and 1. + + As a special case, this supports the Internet Explorer syntax + `alpha(opacity=20)`, for which it returns an [unquoted string][]. + + [unquoted string]: ../values/strings#unquoted + + See also: + + * [`color.red()`](#red) for getting a color's red channel. + * [`color.green()`](#green) for getting a color's green channel. + * [`color.blue()`](#blue) for getting a color's blue channel. + * [`color.hue()`](#hue) for getting a color's hue. + * [`color.saturation()`](#saturation) for getting a color's saturation. + * [`color.lightness()`](#lightness) for getting a color's lightness. + + <% example(autogen_css: false) do %> + @debug color.alpha(#e1d7d2); // 1 + @debug color.opacity(rgb(210, 225, 221, 0.4)); // 0.4 + @debug alpha(opacity=20); // alpha(opacity=20) + === + @debug color.alpha(#e1d7d2) // 1 + @debug color.opacity(rgb(210, 225, 221, 0.4)) // 0.4 + @debug alpha(opacity=20) // alpha(opacity=20) + <% end %> +<% end %> + + +<% function 'color.blue($color)', 'blue($color)', returns: 'number' do %> + Returns the blue channel of `$color` as a number between 0 and 255. + + See also: + + * [`color.red()`](#red) for getting a color's red channel. + * [`color.green()`](#green) for getting a color's green channel. + * [`color.hue()`](#hue) for getting a color's hue. + * [`color.saturation()`](#saturation) for getting a color's saturation. + * [`color.lightness()`](#lightness) for getting a color's lightness. + * [`color.alpha()`](#alpha) for getting a color's alpha channel. + + <% example(autogen_css: false) do %> + @debug color.blue(#e1d7d2); // 210 + @debug color.blue(white); // 255 + @debug color.blue(black); // 0 + === + @debug color.blue(#e1d7d2) // 210 + @debug color.blue(white) // 255 + @debug color.blue(black) // 0 + <% end %> +<% end %> + + +<% function < + Sets one or more properties of a color to new values. + + Uses the value passed for each keyword argument in place of the corresponding + property of the color, and returns the changed color. It's an error to specify + an RGB property (`$red`, `$green`, and/or `$blue`) at the same time as an HSL + property (`$hue`, `$saturation`, and/or `$lightness`). + + All optional arguments must be numbers. The `$red`, `$green`, and `$blue` + arguments must be [unitless][] and between 0 and 255 (inclusive). The `$hue` + argument must have either the unit `deg` or no unit. The `$saturation` and + `$lightness` arguments must be between `0%` and `100%` (inclusive), and may be + unitless. The `$alpha` argument must be unitless and between -1 and 1 + (inclusive). + + [unitless]: ../values/numbers#units + + See also: + + * [`color.scale()`](#scale) for fluidly scaling a color's properties. + * [`color.adjust()`](#adjust) for adjusting a color's properties by fixed + amounts. + + <% example(autogen_css: false) do %> + @debug color.change(#6b717f, $red: 100); // #64717f + @debug color.change(#d2e1dd, $red: 100, $blue: 50); // #64e132 + @debug color.change(#998099, $lightness: 30%, $alpha: 0.5); // rgba(85, 68, 85, 0.5) + === + @debug color.change(#6b717f, $red: 100) // #64717f + @debug color.change(#d2e1dd, $red: 100, $blue: 50) // #64e132 + @debug color.change(#998099, $lightness: 30%, $alpha: 0.5) // rgba(85, 68, 85, 0.5) + <% end %> +<% end %> + + +<% function 'color.complement($color)', + 'complement($color)', + returns: 'color' do %> + Returns the RGB [complement][] of `$color`. + + This is identical to [`color.adjust($color, $hue: 180deg)`](#adjust). + + [complement]: https://en.wikipedia.org/wiki/Complementary_colors + + <% example(autogen_css: false) do %> + // Hue 222deg becomes 42deg. + @debug color.complement(#6b717f); // #7f796b + + // Hue 164deg becomes 344deg. + @debug color.complement(#d2e1dd); // #e1d2d6 + + // Hue 210deg becomes 30deg. + @debug color.complement(#036); // #663300 + === + // Hue 222deg becomes 42deg. + @debug color.complement(#6b717f) // #7f796b + + // Hue 164deg becomes 344deg. + @debug color.complement(#d2e1dd) // #e1d2d6 + + // Hue 210deg becomes 30deg. + @debug color.complement(#036) // #663300 + <% end %> +<% end %> + + +<% function 'darken($color, $amount)', returns: 'color' do %> + Makes `$color` darker. + + The `$amount` must be a number between `0%` and `100%` (inclusive). Decreases + the HSL lightness of `$color` by that amount. + + <% heads_up do %> + The `darken()` function decreases lightness by a fixed amount, which is often + not the desired effect. To make a color a certain percentage darker than it was + before, use [`color.scale()`](#scale) instead. + + Because `darken()` is usually not the best way to make a color darker, it's + not included directly in the new module system. However, if you have to + preserve the existing behavior, `darken($color, $amount)` can be written + [`color.adjust($color, $lightness: -$amount)`](#adjust). + + <% example(autogen_css: false) do %> + // #036 has lightness 20%, so when darken() subtracts 30% it just returns black. + @debug darken(#036, 30%); // black + + // scale() instead makes it 30% darker than it was originally. + @debug color.scale(#036, $lightness: -30%); // #002447 + === + // #036 has lightness 20%, so when darken() subtracts 30% it just returns black. + @debug darken(#036, 30%) // black + + // scale() instead makes it 30% darker than it was originally. + @debug color.scale(#036, $lightness: -30%) // #002447 + <% end %> + <% end %> + + <% example(autogen_css: false) do %> + // Lightness 92% becomes 72%. + @debug darken(#b37399, 20%); // #7c4465 + + // Lightness 85% becomes 45%. + @debug darken(#f2ece4, 40%); // #b08b5a + + // Lightness 20% becomes 0%. + @debug darken(#036, 30%); // black + === + // Lightness 92% becomes 72%. + @debug darken(#b37399, 20%) // #7c4465 + + // Lightness 85% becomes 45%. + @debug darken(#f2ece4, 40%) // #b08b5a + + // Lightness 20% becomes 0%. + @debug darken(#036, 30%) // black + <% end %> +<% end %> + + +<% function 'desaturate($color, $amount)', returns: 'color' do %> + Makes `$color` less saturated. + + The `$amount` must be a number between `0%` and `100%` (inclusive). Decreases + the HSL saturation of `$color` by that amount. + + <% heads_up do %> + The `desaturate()` function decreases saturation by a fixed amount, which is + often not the desired effect. To make a color a certain percentage less + saturated than it was before, use [`color.scale()`](#scale) instead. + + Because `desaturate()` is usually not the best way to make a color less + saturated, it's not included directly in the new module system. However, if + you have to preserve the existing behavior, `desaturate($color, $amount)` + can be written [`color.adjust($color, $saturation: -$amount)`](#adjust). + + <% example(autogen_css: false) do %> + // #d2e1dd has saturation 20%, so when desaturate() subtracts 30% it just + // returns gray. + @debug desaturate(#d2e1dd, 30%); // #dadada + + // scale() instead makes it 30% less saturated than it was originally. + @debug color.scale(#6b717f, $saturation: -30%); // #6e727c + === + // #6b717f has saturation 20%, so when desaturate() subtracts 30% it just + // returns gray. + @debug desaturate(#d2e1dd, 30%) // #dadada + + // scale() instead makes it 30% less saturated than it was originally. + @debug color.scale(#6b717f, $saturation: -30%) // #6e727c + <% end %> + <% end %> + + <% example(autogen_css: false) do %> + // Saturation 100% becomes 80%. + @debug desaturate(#036, 20%); // #0a335c + + // Saturation 35% becomes 15%. + @debug desaturate(#f2ece4, 20%); // #eeebe8 + + // Saturation 20% becomes 0%. + @debug desaturate(#d2e1dd, 30%); // #dadada + === + // Saturation 100% becomes 80%. + @debug desaturate(#036, 20%) // #0a335c + + // Saturation 35% becomes 15%. + @debug desaturate(#f2ece4, 20%) // #eeebe8 + + // Saturation 20% becomes 0%. + @debug desaturate(#d2e1dd, 30%) // #dadada + <% end %> +<% end %> + + +<% function 'color.grayscale($color)', + 'grayscale($color)', + returns: 'color' do %> + Returns a gray color with the same lightness as `$color`. + + This is identical to [`color.change($color, $saturation: 0%)`](#change). + + <% example(autogen_css: false) do %> + @debug color.grayscale(#6b717f); // #757575 + @debug color.grayscale(#d2e1dd); // #dadada + @debug color.grayscale(#036); // #333333 + === + @debug color.grayscale(#6b717f) // #757575 + @debug color.grayscale(#d2e1dd) // #dadada + @debug color.grayscale(#036) // #333333 + <% end %> +<% end %> + + +<% function 'color.green($color)', 'green($color)', returns: 'number' do %> + Returns the green channel of `$color` as a number between 0 and 255. + + See also: + + * [`color.red()`](#red) for getting a color's red channel. + * [`color.blue()`](#blue) for getting a color's blue channel. + * [`color.hue()`](#hue) for getting a color's hue. + * [`color.saturation()`](#saturation) for getting a color's saturation. + * [`color.lightness()`](#lightness) for getting a color's lightness. + * [`color.alpha()`](#alpha) for getting a color's alpha channel. + + <% example(autogen_css: false) do %> + @debug color.green(#e1d7d2); // 215 + @debug color.green(white); // 255 + @debug color.green(black); // 0 + === + @debug color.green(#e1d7d2) // 215 + @debug color.green(white) // 255 + @debug color.green(black) // 0 + <% end %> +<% end %> + + +<% function 'color.hue($color)', 'hue($color)', returns: 'number' do %> + Returns the hue of `$color` as a number between `0deg` and `255deg`. + + See also: + + * [`color.red()`](#red) for getting a color's red channel. + * [`color.green()`](#green) for getting a color's green channel. + * [`color.blue()`](#blue) for getting a color's blue channel. + * [`color.saturation()`](#saturation) for getting a color's saturation. + * [`color.lightness()`](#lightness) for getting a color's lightness. + * [`color.alpha()`](#alpha) for getting a color's alpha channel. + + <% example(autogen_css: false) do %> + @debug color.hue(#e1d7d2); // 20deg + @debug color.hue(#f2ece4); // 34.2857142857deg + @debug color.hue(#dadbdf); // 228deg + === + @debug color.hue(#e1d7d2) // 20deg + @debug color.hue(#f2ece4) // 34.2857142857deg + @debug color.hue(#dadbdf) // 228deg + <% end %> +<% end %> + + +<% function 'color.ie-hex-str($color)', + 'ie-hex-str($color)', + returns: 'unquoted string' do %> + Returns an unquoted string that represents `$color` in the `#AARRGGBB` format + expected by Internet Explorer's [`-ms-filter`][] property. + + [`-ms-filter`]: https://developer.mozilla.org/en-US/docs/Web/CSS/-ms-filter + + <% example(autogen_css: false) do %> + @debug color.ie-hex-str(#b37399); // #FFB37399 + @debug color.ie-hex-str(#808c99); // #FF808C99 + @debug color.ie-hex-str(rgba(242, 236, 228, 0.6)); // #99F2ECE4 + === + @debug color.ie-hex-str(#b37399); // #FFB37399 + @debug color.ie-hex-str(#808c99); // #FF808C99 + @debug color.ie-hex-str(rgba(242, 236, 228, 0.6)); // #99F2ECE4 + <% end %> +<% end %> + + +<% function 'color.invert($color, $weight: 100%)', + 'invert($color, $weight: 100%)', + returns: 'color' do %> + Returns the inverse or [negative][] of `$color`. + + [negative]: https://en.wikipedia.org/wiki/Negative_(photography) + + The `$weight` must be a number between `0%` and `100%` (inclusive). A higher + weight means the result will be closer to the negative, and a lower weight means + it will be closer to `$color`. Weight `50%` will always produce `#808080`. + + <% example(autogen_css: false) do %> + @debug color.invert(#b37399); // #4c8c66 + @debug color.invert(black); // white + @debug color.invert(#550e0c, 20%); // #663b3a + === + @debug color.invert(#b37399) // #4c8c66 + @debug color.invert(black) // white + @debug color.invert(#550e0c, 20%) // #663b3a + <% end %> +<% end %> + + +<% function 'lighten($color, $amount)', returns: 'color' do %> + Makes `$color` lighter. + + The `$amount` must be a number between `0%` and `100%` (inclusive). Increases + the HSL lightness of `$color` by that amount. + + <% heads_up do %> + The `lighten()` function increases lightness by a fixed amount, which is often + not the desired effect. To make a color a certain percentage lighter than it was + before, use [`scale()`](#scale) instead. + + Because `lighten()` is usually not the best way to make a color lighter, + it's not included directly in the new module system. However, if you have to + preserve the existing behavior, `lighten($color, $amount)` can be written + [`adjust($color, $lightness: $amount)`](#adjust). + + <% example(autogen_css: false) do %> + // #e1d7d2 has lightness 85%, so when lighten() adds 30% it just returns white. + @debug lighten(#e1d7d2, 30%); // white + + // scale() instead makes it 30% lighter than it was originally. + @debug color.scale(#e1d7d2, $lightness: 30%); // #eae3e0 + === + // #e1d7d2 has lightness 85%, so when lighten() adds 30% it just returns white. + @debug lighten(#e1d7d2, 30%) // white + + // scale() instead makes it 30% lighter than it was originally. + @debug color.scale(#e1d7d2, $lightness: 30%) // #eae3e0 + <% end %> + <% end %> + + <% example(autogen_css: false) do %> + // Lightness 46% becomes 66%. + @debug lighten(#6b717f, 20%); // #a1a5af + + // Lightness 20% becomes 80%. + @debug lighten(#036, 60%); // #99ccff + + // Lightness 85% becomes 100%. + @debug lighten(#e1d7d2, 30%); // white + === + // Lightness 46% becomes 66%. + @debug lighten(#6b717f, 20%) // #a1a5af + + // Lightness 20% becomes 80%. + @debug lighten(#036, 60%) // #99ccff + + // Lightness 85% becomes 100%. + @debug lighten(#e1d7d2, 30%) // white + <% end %> +<% end %> + + +<% function 'color.lightness($color)', + 'lightness($color)', + returns: 'number' do %> + Returns the HSL lightness of `$color` as a number between `0%` and `100%`. + + See also: + + * [`color.red()`](#red) for getting a color's red channel. + * [`color.green()`](#green) for getting a color's green channel. + * [`color.blue()`](#blue) for getting a color's blue channel. + * [`color.hue()`](#hue) for getting a color's hue. + * [`color.saturation()`](#saturation) for getting a color's saturation. + * [`color.alpha()`](#alpha) for getting a color's alpha channel. + + <% example(autogen_css: false) do %> + @debug color.lightness(#e1d7d2); // 85.2941176471% + @debug color.lightness(#f2ece4); // 92.1568627451% + @debug color.lightness(#dadbdf); // 86.4705882353% + === + @debug color.lightness(#e1d7d2) // 85.2941176471% + @debug color.lightness(#f2ece4) // 92.1568627451% + @debug color.lightness(#dadbdf) // 86.4705882353% + <% end %> +<% end %> + + +<% function 'color.mix($color1, $color2, $weight: 50%)', + 'mix($color1, $color2, $weight: 50%)', + returns: 'color' do %> + Returns a number that's a mixture of `$color1` and `$color2`. + + Both the `$weight` and the relative opacity of each color determines how much of + each color is in the result. The `$weight` must be a number between `0%` and + `100%` (inclusive). A larger weight indicates that more of `$color1` should be + used, and a smaller weight indicates that more of `$color2` should be used. + + <% example(autogen_css: false) do %> + @debug color.mix(#036, #d2e1dd); // #698aa2 + @debug color.mix(#036, #d2e1dd, 75%); // #355f84 + @debug color.mix(#036, #d2e1dd, 25%); // #9eb6bf + @debug color.mix(rgba(242, 236, 228, 0.5), #6b717f); // rgba(141, 144, 152, 0.75) + === + @debug color.mix(#036, #d2e1dd) // #698aa2 + @debug color.mix(#036, #d2e1dd, 75%) // #355f84 + @debug color.mix(#036, #d2e1dd, 25%) // #9eb6bf + @debug color.mix(rgba(242, 236, 228, 0.5), #6b717f) // rgba(141, 144, 152, 0.75) + <% end %> +<% end %> + + +<% function 'opacify($color, $amount)', 'fade-in($color, $amount)', returns: 'color' do %> + Makes `$color` more opaque. + + The `$amount` must be a number between `0` and `1` (inclusive). Increases the + alpha channel of `$color` by that amount. + + <% heads_up do %> + The `opacify()` function increases the alpha channel by a fixed amount, which is often + not the desired effect. To make a color a certain percentage more opaque than it was + before, use [`scale()`](#scale) instead. + + Because `opacify()` is usually not the best way to make a color more opaque, + it's not included directly in the new module system. However, if you have to + preserve the existing behavior, `opacify($color, $amount)` can be written + [`adjust($color, $alpha: -$amount)`](#adjust). + + <% example(autogen_css: false) do %> + // rgba(#036, 0.7) has alpha 0.7, so when opacify() adds 0.3 it returns a fully + // opaque color. + @debug opacify(rgba(#036, 0.7), 0.3); // #036 + + // scale() instead makes it 30% more opaque than it was originally. + @debug color.scale(rgba(#036, 0.7), $alpha: 30%); // rgba(0, 51, 102, 0.79) + === + // rgba(#036, 0.7) has alpha 0.7, so when opacify() adds 0.3 it returns a fully + // opaque color. + @debug opacify(rgba(#036, 0.7), 0.3) // #036 + + // scale() instead makes it 30% more opaque than it was originally. + @debug color.scale(rgba(#036, 0.7), $alpha: 30%) // rgba(0, 51, 102, 0.79) + <% end %> + <% end %> + + <% example(autogen_css: false) do %> + @debug opacify(rgba(#6b717f, 0.5), 0.2); // rgba(107, 113, 127, 0.7) + @debug fade-in(rgba(#e1d7d2, 0.5), 0.4); // rgba(225, 215, 210, 0.9) + @debug opacify(rgba(#036, 0.7), 0.3); // #036 + === + @debug opacify(rgba(#6b717f, 0.5), 0.2) // rgba(107, 113, 127, 0.7) + @debug fade-in(rgba(#e1d7d2, 0.5), 0.4) // rgba(225, 215, 210, 0.9) + @debug opacify(rgba(#036, 0.7), 0.3) // #036 + <% end %> +<% end %> + + +<% function 'color.red($color)', 'red($color)', returns: 'number' do %> + Returns the red channel of `$color` as a number between 0 and 255. + + See also: + + * [`color.green()`](#green) for getting a color's green channel. + * [`color.blue()`](#blue) for getting a color's blue channel. + * [`color.hue()`](#hue) for getting a color's hue. + * [`color.saturation()`](#saturation) for getting a color's saturation. + * [`color.lightness()`](#lightness) for getting a color's lightness. + * [`color.alpha()`](#alpha) for getting a color's alpha channel. + + <% example(autogen_css: false) do %> + @debug color.red(#e1d7d2); // 225 + @debug color.red(white); // 255 + @debug color.red(black); // 0 + === + @debug color.red(#e1d7d2) // 225 + @debug color.red(white) // 255 + @debug color.red(black) // 0 + <% end %> +<% end %> + + +<% function 'saturate($color, $amount)', 'saturate($color, $amount)', returns: 'color' do %> + Makes `$color` more saturated. + + The `$amount` must be a number between `0%` and `100%` (inclusive). Increases + the HSL saturation of `$color` by that amount. + + <% heads_up do %> + The `saturate()` function increases saturation by a fixed amount, which is often + not the desired effect. To make a color a certain percentage more saturated than + it was before, use [`scale()`](#scale) instead. + + Because `saturate()` is usually not the best way to make a color more + saturated, it's not included directly in the new module system. However, if + you have to preserve the existing behavior, `saturate($color, $amount)` can + be written [`adjust($color, $saturation: $amount)`](#adjust). + + <% example(autogen_css: false) do %> + // #0e4982 has saturation 80%, so when saturate() adds 30% it just becomes + // fully saturated. + @debug saturate(#0e4982, 30%); // #004990 + + // scale() instead makes it 30% more saturated than it was originally. + @debug color.scale(#0e4982, $saturation: 30%); // #0a4986 + === + // #0e4982 has saturation 80%, so when saturate() adds 30% it just becomes + // fully saturated. + @debug saturate(#0e4982, 30%) // #004990 + + // scale() instead makes it 30% more saturated than it was originally. + @debug color.scale(#0e4982, $saturation: 30%) // #0a4986 + <% end %> + <% end %> + + <% example(autogen_css: false) do %> + // Saturation 50% becomes 70%. + @debug saturate(#c69, 20%); // #e05299 + + // Saturation 35% becomes 85%. + @debug desaturate(#f2ece4, 50%); // #ebebeb + + // Saturation 80% becomes 100%. + @debug saturate(#0e4982, 30%) // #004990 + === + // Saturation 50% becomes 70%. + @debug saturate(#c69, 20%); // #e05299 + + // Saturation 35% becomes 85%. + @debug desaturate(#f2ece4, 50%); // #ebebeb + + // Saturation 80% becomes 100%. + @debug saturate(#0e4982, 30%) // #004990 + <% end %> +<% end %> + + +<% function 'color.saturation($color)', + 'saturation($color)', + returns: 'number' do %> + Returns the HSL saturation of `$color` as a number between `0%` and `100%`. + + See also: + + * [`color.red()`](#red) for getting a color's red channel. + * [`color.green()`](#green) for getting a color's green channel. + * [`color.blue()`](#blue) for getting a color's blue channel. + * [`color.hue()`](#hue) for getting a color's hue. + * [`color.lightness()`](#lightness) for getting a color's lightness. + * [`color.alpha()`](#alpha) for getting a color's alpha channel. + + <% example(autogen_css: false) do %> + @debug color.saturation(#e1d7d2); // 20% + @debug color.saturation(#f2ece4); // 30% + @debug color.saturation(#dadbdf); // 7.2463768116% + === + @debug color.saturation(#e1d7d2) // 20% + @debug color.saturation(#f2ece4) // 30% + @debug color.saturation(#dadbdf) // 7.2463768116% + <% end %> +<% end %> + + +<% function < + Fluidly scales one or more properties of `$color`. + + Each keyword argument must be a number between `-100%` and `100%` (inclusive). + This indicates how far the corresponding property should be moved from its + original position towards the maximum (if the argument is positive) or the + minimum (if the argument is negative). This means that, for example, + `$lightness: 50%` will make all colors `50%` closer to maximum lightness + without making them fully white. + + It's an error to specify an RGB property (`$red`, `$green`, and/or `$blue`) at + the same time as an HSL property (`$saturation`, and/or `$lightness`). + + See also: + + * [`color.adjust()`](#adjust) for changing a color's properties by fixed + amounts. + * [`color.change()`](#change) for setting a color's properties. + + <% example(autogen_css: false) do %> + @debug color.scale(#6b717f, $red: 15%); // #81717f + @debug color.scale(#d2e1dd, $lightness: -10%, $saturation: 10%); // #b3d4cb + @debug color.scale(#998099, $alpha: -40%); // rgba(153, 128, 153, 0.6) + === + @debug color.scale(#6b717f, $red: 15%) // #81717f + @debug color.scale(#d2e1dd, $lightness: -10%, $saturation: 10%) // #b3d4cb + @debug color.scale(#998099, $alpha: -40%) // rgba(153, 128, 153, 0.6) + <% end %> +<% end %> + + +<% function 'transparentize($color, $amount)', 'fade-out($color, $amount)', returns: 'color' do %> + Makes `$color` more transparent. + + The `$amount` must be a number between `0` and `1` (inclusive). Decreases the + alpha channel of `$color` by that amount. + + <% heads_up do %> + The `transparentize()` function decreases the alpha channel by a fixed amount, + which is often not the desired effect. To make a color a certain percentage more + transparent than it was before, use [`color.scale()`](#scale) instead. + + Because `transparentize()` is usually not the best way to make a color more + transparent, it's not included directly in the new module system. However, + if you have to preserve the existing behavior, + `transparentize($color, $amount)` can be written + [`color.adjust($color, $alpha: -$amount)`](#adjust). + + <% example(autogen_css: false) do %> + // rgba(#036, 0.3) has alpha 0.3, so when transparentize() subtracts 0.3 it + // returns a fully transparent color. + @debug transparentize(rgba(#036, 0.3), 0.3); // rgba(0, 51, 102, 0) + + // scale() instead makes it 30% more transparent than it was originally. + @debug color.scale(rgba(#036, 0.3), $alpha: -30%); // rgba(0, 51, 102, 0.21) + === + // rgba(#036, 0.3) has alpha 0.3, so when transparentize() subtracts 0.3 it + // returns a fully transparent color. + @debug transparentize(rgba(#036, 0.3), 0.3) // rgba(0, 51, 102, 0) + + // scale() instead makes it 30% more transparent than it was originally. + @debug color.scale(rgba(#036, 0.3), $alpha: -30%) // rgba(0, 51, 102, 0.21) + <% end %> + <% end %> + + <% example(autogen_css: false) do %> + @debug transparentize(rgba(#6b717f, 0.5), 0.2) // rgba(107, 113, 127, 0.3) + @debug fade-out(rgba(#e1d7d2, 0.5), 0.4) // rgba(225, 215, 210, 0.1) + @debug transparentize(rgba(#036, 0.3), 0.3) // rgba(0, 51, 102, 0) + === + @debug transparentize(rgba(#6b717f, 0.5), 0.2) // rgba(107, 113, 127, 0.3) + @debug fade-out(rgba(#e1d7d2, 0.5), 0.4) // rgba(225, 215, 210, 0.1) + @debug transparentize(rgba(#036, 0.3), 0.3) // rgba(0, 51, 102, 0) + <% end %> +<% end %> diff --git a/source/documentation/modules/list.html.md.erb b/source/documentation/modules/list.html.md.erb new file mode 100644 index 000000000..d63cc0229 --- /dev/null +++ b/source/documentation/modules/list.html.md.erb @@ -0,0 +1,218 @@ +--- +title: sass:list +--- + +<%= partial '../snippets/built-in-module-status' %> + +<% fun_fact do %> + In Sass, every [map][] counts as a list that contains a two-element list for + each key/value pair. For example, `(1: 2, 3: 4)` counts as `(1 2, 3 4)`. So + all these functions work for maps as well! + + [map]: ../values/maps + + Individual values also count as lists. All these functions treat `1px` as a + list that contains the value `1px`. +<% end %> + + +<% function 'list.append($list, $val, $separator: auto)', + 'append($list, $val, $separator: auto)', + returns: 'list' do %> + Returns a copy of `$list` with `$val` added to the end. + + If `$separator` is `comma`, the returned list is comma-separted. If it's + `space`, the returned list is space-separated. If it's `auto` (the default), the + returned list will use the same separator as `$list` (or `space` if `$list` + doesn't have a separator). Other values aren't allowed. + + [separator]: ../values/lists + + Note that unlike [`list.join()`](#join), if `$val` is a list it's nested + within the returned list rather than having all its elements added to the + returned list. + + <% example(autogen_css: false) do %> + @debug list.append(10px 20px, 30px); // 10px 20px 30px + @debug list.append((blue, red), green); // blue, red, green + @debug list.append(10px 20px, 30px 40px); // 10px 20px (30px 40px) + @debug list.append(10px, 20px, $separator: comma); // 10px, 20px + @debug list.append((blue, red), green, $separator: space); // blue red green + === + @debug list.append(10px 20px, 30px) // 10px 20px 30px + @debug list.append((blue, red), green) // blue, red, green + @debug list.append(10px 20px, 30px 40px) // 10px 20px (30px 40px) + @debug list.append(10px, 20px, $separator: comma) // 10px, 20px + @debug list.append((blue, red), green, $separator: space) // blue red green + <% end %> +<% end %> + + +<% function 'list.index($list, $value)', + 'index($list, $value)', + returns: 'number | null' do %> + Returns the [index][] of `$value` in `$list`. + + [index]: ../values/lists#indexes + + If `$value` doesn't appear in `$list`, this returns [`null`][]. If `$value` + appears multiple times in `$list`, this returns the index of its first + appearance. + + [`null`]: ../values/null + + <%= partial 'code-snippets/example-list-index' %> +<% end %> + + +<% function 'list.is-bracketed($list)', + 'is-bracketed($list)', + returns: 'boolean' do %> + Returns whether `$list` has square brackets. + + <% example(autogen_css: false) do %> + @debug list.is-bracketed(1px 2px 3px); // false + @debug list.is-bracketed([1px, 2px, 3px]); // true + === + @debug list.is-bracketed(1px 2px 3px) // false + @debug list.is-bracketed([1px, 2px, 3px]) // true + <% end %> +<% end %> + + +<% function 'list.join($list1, $list2, $separator: auto, $bracketed: auto)', + 'join($list1, $list2, $separator: auto, $bracketed: auto)', + returns: 'list' do %> + Returns a new list containing the elements of `$list1` followed by the elements + of `$list2`. + + <% heads_up do %> + Because individual values count as single-element lists, it's possible to + use `list.join()` to add a value to the end of a list. However, *this is not + recommended*, since if that value is a list it will be concatenated, which + is probably not what you're expecting. + + Use [`list.append()`](#append) instead to add a single value to a list. Only + use `list.join()` to combine two lists together into one. + <% end %> + + If `$separator` is `comma`, the returned list is comma-separted. If it's + `space`, the returned list is space-separated. If it's `auto` (the default), + the returned list will use the same separator as `$list1` if it has a + separator, or else `$list2` if it has a separator, or else `space`. Other + values aren't allowed. + + If `$bracketed` is `true`, the returned list has square brackets. If it's + `false`, the returned list has no brackets. If it's `auto` (the default), the + returned list will be bracketed if `$list1` is. Other values aren't allowed. + + <% example(autogen_css: false) do %> + @debug list.join(10px 20px, 30px 40px); // 10px 20px 30px 40px + @debug list.join((blue, red), (#abc, #def)); // blue, red, #abc, #def + @debug list.join(10px, 20px); // 10px 20px + @debug list.join(10px, 20px, $separator: comma); // 10px, 20px + @debug list.join((blue, red), (#abc, #def), $separator: space); // blue red #abc #def + @debug list.join([10px], 20px); // [10px 20px] + @debug list.join(10px, 20px, $bracketed: true); // [10px 20px] + === + @debug list.join(10px 20px, 30px 40px) // 10px 20px 30px 40px + @debug list.join((blue, red), (#abc, #def)) // blue, red, #abc, #def + @debug list.join(10px, 20px) // 10px 20px + @debug list.join(10px, 20px, comma) // 10px, 20px + @debug list.join((blue, red), (#abc, #def), space) // blue red #abc #def + @debug list.join([10px], 20px) // [10px 20px] + @debug list.join(10px, 20px, $bracketed: true) // [10px 20px] + <% end %> +<% end %> + + +<% function 'list.length($list)', 'length($list)', returns: 'number' do %> + Returns the length of `$list`. + + This can also return the number of pairs in a map. + + <% example(autogen_css: false) do %> + @debug list.length(10px); // 1 + @debug list.length(10px 20px 30px); // 3 + @debug list.length((width: 10px, height: 20px)); // 2 + === + @debug list.length(10px) // 1 + @debug list.length(10px 20px 30px) // 3 + @debug list.length((width: 10px, height: 20px)) // 2 + <% end %> +<% end %> + + +<% function 'list.separator($list)', + 'list-separator($list)', + returns: 'unquoted string' do %> + Returns the name of the separator used by `$list`, either `space` or `comma`. + + If `$list` doesn't have a separator, returns `space`. + + <% example(autogen_css: false) do %> + @debug list.separator(1px 2px 3px); // space + @debug list.separator(1px, 2px, 3px); // comma + @debug list.separator('Helvetica'); // space + @debug list.separator(()); // space + === + @debug list.separator(1px 2px 3px) // space + @debug list.separator(1px, 2px, 3px) // comma + @debug list.separator('Helvetica') // space + @debug list.separator(()) // space + <% end %> +<% end %> + + +<% function 'list.nth($list, $n)', 'nth($list, $n)' do %> + Returns the element of `$list` at [index][] `$n`. + + [index]: ../values/lists#indexes + + If `$n` is negative, it counts from the end of `$list`. Throws an error if + there is no element at index `$n`. + + <%= partial 'code-snippets/example-list-nth' %> +<% end %> + + +<% function 'list.set-nth($list, $n, $value)', + 'set-nth($list, $n, $value)', + returns: 'list' do %> + Returns a copy of `$list` with the element at [index][] `$n` replaced with + `$value`. + + [index]: ../values/lists#indexes + + If `$n` is negative, it counts from the end of `$list`. Throws an error if + there is no existing element at index `$n`. + + <% example(autogen_css: false) do %> + @debug list.set-nth(10px 20px 30px, 1, 2em); // 2em 20px 30px + @debug list.set-nth(10px 20px 30px, -1, 8em); // 10px, 20px, 8em + @debug list.set-nth((Helvetica, Arial, sans-serif), 3, Roboto); // Helvetica, Arial, Roboto + === + @debug list.set-nth(10px 20px 30px, 1, 2em); // 2em 20px 30px + @debug list.set-nth(10px 20px 30px, -1, 8em); // 10px, 20px, 8em + @debug list.set-nth((Helvetica, Arial, sans-serif), 3, Roboto); // Helvetica, Arial, Roboto + <% end %> +<% end %> + + +<% function 'list.zip($lists...)', 'zip($lists...)', returns: 'list' do %> + Combines every list in `$lists` into a single list of sub-lists. + + Each element in the returned list contains all the elements at that position + in `$lists`. The returned list is as long as the shortest list in `$lists`. + + The returned list is always comma-separated and the sub-lists are always + space-separated. + + <% example(autogen_css: false) do %> + @debug list.zip(10px 50px 100px, short mid long); // 10px short, 50px mid, 100px long + @debug list.zip(10px 50px 100px, short mid); // 10px short, 50px mid + === + @debug list.zip(10px 50px 100px, short mid long) // 10px short, 50px mid, 100px long + @debug list.zip(10px 50px 100px, short mid) // 10px short, 50px mid + <% end %> +<% end %> diff --git a/source/documentation/functions/map.html.md.erb b/source/documentation/modules/map.html.md.erb similarity index 56% rename from source/documentation/functions/map.html.md.erb rename to source/documentation/modules/map.html.md.erb index d3e86981d..d40c921bd 100644 --- a/source/documentation/functions/map.html.md.erb +++ b/source/documentation/modules/map.html.md.erb @@ -1,22 +1,10 @@ --- -title: Map Functions +title: sass:map --- -<% function 'keywords($args)', returns: 'map' do %> - Returns the keywords passed to a mixin or function that takes [arbitrary - arguments][]. The `$args` argument must be an [argument list][]. +<%= partial '../snippets/built-in-module-status' %> - [arbitrary arguments]: ../at-rules/mixin#taking-arbitrary-arguments - [argument list]: ../values/lists#argument-lists - - The keywords are returned as a map from argument names as unquoted strings (not - including `$`) to the values of those arguments. - - <%= partial 'code-snippets/example-mixin-arbitrary-keyword-arguments' %> -<% end %> - - -<% function 'map-get($map, $key)' do %> +<% function 'map.get($map, $key)', 'map-get($map, $key)' do %> Returns the value in `$map` associated with `$key`. If `$map` doesn't have a value associated with `$key`, returns [`null`][]. @@ -27,39 +15,43 @@ title: Map Functions <% end %> -<% function 'map-has-key($map, $key)', returns: 'boolean' do %> +<% function 'map.has-key($map, $key)', + 'map-has-key($map, $key)', + returns: 'boolean' do %> Returns whether `$map` contains a value associated with `$key`. <% example(autogen_css: false) do %> $font-weights: ("regular": 400, "medium": 500, "bold": 700); - @debug map-has-key($font-weights, "regular"); // true - @debug map-has-key($font-weights, "bolder"); // false + @debug map.has-key($font-weights, "regular"); // true + @debug map.has-key($font-weights, "bolder"); // false === $font-weights: ("regular": 400, "medium": 500, "bold": 700) - @debug map-has-key($font-weights, "regular") // true - @debug map-has-key($font-weights, "bolder") // false + @debug map.has-key($font-weights, "regular") // true + @debug map.has-key($font-weights, "bolder") // false <% end %> <% end %> -<% function 'map-keys($map)', returns: 'list' do %> +<% function 'map.keys($map)', 'map-keys($map)', returns: 'list' do %> Returns a comma-separated list of all the keys in `$map`. <% example(autogen_css: false) do %> $font-weights: ("regular": 400, "medium": 500, "bold": 700); - @debug map-keys($font-weights); // "regular", "medium", "bold" + @debug map.keys($font-weights); // "regular", "medium", "bold" === $font-weights: ("regular": 400, "medium": 500, "bold": 700) - @debug map-keys($font-weights) // "regular", "medium", "bold" + @debug map.keys($font-weights) // "regular", "medium", "bold" <% end %> <% end %> -<% function 'map-merge($map1, $map2)', returns: 'map' do %> +<% function 'map.merge($map1, $map2)', + 'map-merge($map1, $map2)', + returns: 'map' do %> Returns a new map with all the keys and values from both `$map1` and `$map2`. This can also be used to add a new value or overrwrite a value in `$map1`, by @@ -74,7 +66,7 @@ title: Map Functions $light-weights: ("lightest": 100, "light": 300); $heavy-weights: ("medium": 500, "bold": 700); - @debug map-merge($light-weights, $heavy-weights); + @debug map.merge($light-weights, $heavy-weights); // ( // "lightest": 100, // "light": 300, @@ -82,18 +74,18 @@ title: Map Functions // "bold": 700 // ) - // map-merge() can be used to add a single key/value pair to a map. - @debug map-merge($light-weights, ("lighter": 200)); + // map.merge() can be used to add a single key/value pair to a map. + @debug map.merge($light-weights, ("lighter": 200)); // ("lightest": 100, "light": 300, "lighter": 200) // It can also be used to overwrite a value in a map. - @debug map-merge($light-weights, ("light": 200)); + @debug map.merge($light-weights, ("light": 200)); // ("lightest": 100, "light": 200) === $light-weights: ("lightest": 100, "light": 300) $heavy-weights: ("medium": 500, "bold": 700) - @debug map-merge($light-weights, $heavy-weights) + @debug map.merge($light-weights, $heavy-weights) // ( // "lightest": 100, // "light": 300, @@ -101,18 +93,20 @@ title: Map Functions // "bold": 700 // ) - // map-merge() can be used to add a single key/value pair to a map. - @debug map-merge($light-weights, ("lighter": 200)) + // map.merge() can be used to add a single key/value pair to a map. + @debug map.merge($light-weights, ("lighter": 200)) // ("lightest": 100, "light": 300, "lighter": 200) // It can also be used to overwrite a value in a map. - @debug map-merge($light-weights, ("light": 200)) + @debug map.merge($light-weights, ("light": 200)) // ("lightest": 100, "light": 200) <% end %> <% end %> -<% function 'map-remove($map, $keys...)', returns: 'map' do %> +<% function 'map.remove($map, $keys...)', + 'map-remove($map, $keys...)', + returns: 'map' do %> Returns a copy of `$map` without any values associated with `$keys`. If a key in `$keys` doesn't have an associated value in `$map`, it's ignored. @@ -120,31 +114,31 @@ title: Map Functions <% example(autogen_css: false) do %> $font-weights: ("regular": 400, "medium": 500, "bold": 700); - @debug map-remove($font-weights, "regular"); // ("medium": 500, "bold": 700) - @debug map-remove($font-weights, "regular", "bold"); // ("medium": 500) - @debug map-remove($font-weights, "bolder"); + @debug map.remove($font-weights, "regular"); // ("medium": 500, "bold": 700) + @debug map.remove($font-weights, "regular", "bold"); // ("medium": 500) + @debug map.remove($font-weights, "bolder"); // ("regular": 400, "medium": 500, "bold": 700) === $font-weights: ("regular": 400, "medium": 500, "bold": 700) - @debug map-remove($font-weights, "regular") // ("medium": 500, "bold": 700) - @debug map-remove($font-weights, "regular", "bold") // ("medium": 500) - @debug map-remove($font-weights, "bolder") + @debug map.remove($font-weights, "regular") // ("medium": 500, "bold": 700) + @debug map.remove($font-weights, "regular", "bold") // ("medium": 500) + @debug map.remove($font-weights, "bolder") // ("regular": 400, "medium": 500, "bold": 700) <% end %> <% end %> -<% function 'map-values($map)', returns: 'list' do %> +<% function 'map.values($map)', 'map-values($map)', returns: 'list' do %> Returns a comma-separated list of all the values in `$map`. <% example(autogen_css: false) do %> $font-weights: ("regular": 400, "medium": 500, "bold": 700); - @debug map-values($font-weights); // 400, 500, 700 + @debug map.values($font-weights); // 400, 500, 700 === $font-weights: ("regular": 400, "medium": 500, "bold": 700) - @debug map-values($font-weights) // 400, 500, 700 + @debug map.values($font-weights) // 400, 500, 700 <% end %> <% end %> diff --git a/source/documentation/modules/math.html.erb b/source/documentation/modules/math.html.erb new file mode 100644 index 000000000..062890492 --- /dev/null +++ b/source/documentation/modules/math.html.erb @@ -0,0 +1,225 @@ +--- +title: sass:math +--- + +<%= partial '../snippets/built-in-module-status' %> + +<% function 'math.abs($number)', 'abs($number)', returns: 'number' do %> + Returns the [absolute value][] of `$number`. If `$number` is negative, this + returns `-$number`, and if `$number` is positive, it returns `$number` as-is. + + [absolute value]: https://en.wikipedia.org/wiki/Absolute_value + + <% example(autogen_css: false) do %> + @debug math.abs(10px); // 10px + @debug math.abs(-10px); // 10px + === + @debug math.abs(10px) // 10px + @debug math.abs(-10px) // 10px + <% end %> +<% end %> + + +<% function 'math.ceil($number)', 'ceil($number)', returns: 'number' do %> + Rounds `$number` up to the next highest whole number. + + <% example(autogen_css: false) do %> + @debug math.ceil(4); // 4 + @debug math.ceil(4.2); // 5 + @debug math.ceil(4.9); // 5 + === + @debug math.ceil(4) // 4 + @debug math.ceil(4.2) // 5 + @debug math.ceil(4.9) // 5 + <% end %> +<% end %> + + +<% function 'math.compatible($number1, $number2)', + 'comparable($number1, $number2)', + returns: 'boolean' do %> + Returns whether `$number1` and `$number2` have compatible units. + + If this returns `true`, `$number1` and `$number2` can safely be [added][], + [subtracted][], and [compared][]. Otherwise, doing so will produce errors. + + [added]: ../operators/numeric + [subtracted]: ../operators/numeric + [compared]: ../operators/relational + + <% heads_up do %> + The global name of this function + is comparable, but when it was added to the + `sass:math` module the name was changed + to compatible to more clearly convey what the + function does. + <% end %> + + <% example(autogen_css: false) do %> + @debug math.compatible(2px, 1px); // true + @debug math.compatible(100px, 3em); // false + @debug math.compatible(10cm, 3mm); // true + === + @debug math.compatible(2px, 1px) // true + @debug math.compatible(100px, 3em) // false + @debug math.compatible(10cm, 3mm) // true + <% end %> +<% end %> + + +<% function 'math.floor($number)', 'floor($number)', returns: 'number' do %> + Rounds `$number` down to the next lowest whole number. + + <% example(autogen_css: false) do %> + @debug math.floor(4); // 4 + @debug math.floor(4.2); // 4 + @debug math.floor(4.9); // 4 + === + @debug math.floor(4) // 4 + @debug math.floor(4.2) // 4 + @debug math.floor(4.9) // 4 + <% end %> +<% end %> + + +<% function 'math.max($number...)', 'max($number...)', returns: 'number' do %> + Returns the highest of one or more numbers. A list of numbers can be passed + [using `...`][]. + + [using `...`]: ../at-rules/function#passing-arbitrary-arguments + + <% example(autogen_css: false) do %> + @debug math.max(1px, 4px); // 4px + + $widths: 50px, 30px, 100px; + @debug math.max($widths...); // 100px + === + @debug math.max(1px, 4px) // 4px + + $widths: 50px, 30px, 100px + @debug math.max($widths...) // 100px + <% end %> +<% end %> + + +<% function 'math.min($number...)', 'min($number...)', returns: 'number' do %> + Returns the lowest of one or more numbers. A list of numbers can be passed + [using `...`][]. + + [using `...`]: ../at-rules/function#passing-arbitrary-arguments + + <% example(autogen_css: false) do %> + @debug math.min(1px, 4px); // 1px + + $widths: 50px, 30px, 100px; + @debug math.min($widths...); // 30px + === + @debug math.min(1px, 4px) // 1px + + $widths: 50px, 30px, 100px + @debug math.min($widths...) // 30px + <% end %> +<% end %> + + +<% function 'math.percentage($number)', + 'percentage($number)', + returns: 'number' do %> + Converts a unitless `$number` (usually a decimal between 0 and 1) to a + percentage. + + <% fun_fact do %> + This function is identical to `$number * 100%`. + <% end %> + + <% example(autogen_css: false) do %> + @debug math.percentage(0.2); // 20% + @debug math.percentage(100px / 50px); // 200% + === + @debug math.percentage(0.2) // 20% + @debug math.percentage(100px / 50px) // 200% + <% end %> +<% end %> + + +<% function 'math.random($limit: null)', + 'random($limit: null)', + returns: 'number' do %> + If `$limit` is [`null`][], returns a random decimal number between 0 and 1. + + [`null`]: ../values/null + + <% example(autogen_css: false) do %> + @debug math.random(); // 0.2821251858 + @debug math.random(); // 0.6221325814 + === + @debug math.random() // 0.2821251858 + @debug math.random() // 0.6221325814 + <% end %> + + * * * + + If `$limit` is a number greater than or equal to 1, returns a random whole + number between 1 and `$limit`. + + <% example(autogen_css: false) do %> + @debug math.random(10); // 4 + @debug math.random(10000); // 5373 + === + @debug math.random(10) // 4 + @debug math.random(10000) // 5373 + <% end %> +<% end %> + + +<% function 'math.round($number)', 'round($number)', returns: 'number' do %> + Rounds `$number` to the nearest whole number. + + <% example(autogen_css: false) do %> + @debug math.round(4); // 4 + @debug math.round(4.2); // 4 + @debug math.round(4.9); // 5 + === + @debug math.round(4) // 4 + @debug math.round(4.2) // 4 + @debug math.round(4.9) // 5 + <% end %> +<% end %> + + +<% function 'math.unit($number)', + 'unit($number)', + returns: 'quoted string' do %> + Returns a string representation of `$number`'s units. + + <% heads_up do %> + This function is intended for debugging; its output format is not guaranteed + to be consistent across Sass versions or implementations. + <% end %> + + <% example(autogen_css: false) do %> + @debug math.unit(100); // "" + @debug math.unit(100px); // "px" + @debug math.unit(5px * 10px); // "px*px" + @debug math.unit(5px / 1s); // "px/s" + === + @debug math.unit(100) // "" + @debug math.unit(100px) // "px" + @debug math.unit(5px * 10px) // "px*px" + @debug math.unit(5px / 1s) // "px/s" + <% end %> +<% end %> + +<% function 'math.is-unitless($number)', + 'unitless($number)', + returns: 'boolean' do %> + Returns whether `$number` has no units. + + <% example(autogen_css: false) do %> + @debug math.is-unitless(100); // true + @debug math.is-unitless(100px); // false + === + @debug math.is-unitless(100) // true + @debug math.is-unitless(100px) // false + <% end %> +<% end %> diff --git a/source/documentation/modules/meta.html.md.erb b/source/documentation/modules/meta.html.md.erb new file mode 100644 index 000000000..017d87dd3 --- /dev/null +++ b/source/documentation/modules/meta.html.md.erb @@ -0,0 +1,503 @@ +--- +title: sass:meta +--- + +<%= partial '../snippets/built-in-module-status' %> + +## Mixins + +<% function 'meta.load-css($url, $with: null)' do %> + <% impl_status dart: '(unreleased)', libsass: false, ruby: false do %> + Only Dart Sass currently supports this mixin. + <% end %> + + Loads the [module][] at `$url` and includes its CSS as though it were written + as the contents of this mixin. The `$with` parameter provides + [configuration][] for the modules; if it's passed, it must be a map from + variable names (without `$`) to the values of those variables to use in the + loaded module. + + [module]: ../at-rules/use + [configuration]: ../at-rules/use#configuring-modules + + If `$url` is relative, it's interpreted as relative to the file in which + `meta.load-css()` is included. + + **Like the [`@use` rule][]**: + + [`@use` rule]: ../at-rules/use + + * This will only evaluate the given module once, even if it's loaded multiple + times in different ways. + + * This cannot provide configuration to a module that's already been loaded, + whether or not it was already loaded with configuration. + + **Unlike the [`@use` rule][]**: + + * This doesn't make any members from the loaded module available in the + current module. + + * This can be used anywhere in a stylesheet. It can even be nested within + style rules to create nested styles! + + * The module URL being loaded can come from a variable and include + [interpolation][]. + + [interpolation]: ../interpolation + + <% heads_up do %> + The `$url` parameter should be a string containing a URL like you'd pass to + the `@use` rule. It shouldn't be a CSS `url()`! + <% end %> + + <% example(autogen_css: false) do %> + // dark-theme/_code.scss + $border-contrast: false !default; + + code { + background-color: #6b717f; + color: #d2e1dd; + @if $border-contrast { + border-color: #dadbdf; + } + } + --- + // style.scss + @use "sass:meta"; + + body.dark { + @include meta.load-css("dark-theme/code", + $with: ("border-contrast": true)); + } + === + // dark-theme/_code.sass + $border-contrast: false !default + + code + background-color: #6b717f + color: #d2e1dd + @if $border-contrast + border-color: #dadbdf + --- + // style.sass + @use "sass:meta" + + body.dark + $configuration: ("border-contrast": true) + @include meta.load-css("dark-theme/code", $with: $configuration) + === + body.dark code { + background-color: #6b717f; + color: #d2e1dd; + border-color: #dadbdf; + } + <% end %> +<% end %> + +## Functions + +<% function 'meta.call($function, $args...)', 'call($function, $args...)' do %> + <%= partial 'documentation/snippets/call-impl-status' %> + + Invokes `$function` with `$args` and returns the result. + + The `$function` should be a [function][] returned by + [`meta.get-function()`][]. + + [function]: ../values/functions + [`meta.get-function()`]: #get-function + + <%= partial 'code-snippets/example-first-class-function' %> +<% end %> + + +<% function 'meta.content-exists()', + 'content-exists()', + returns: 'boolean' do %> + Returns whether the current mixin was passed a [`@content` block][]. + + [`@content` block]: ../at-rules/mixin#content-blocks + + Throws an error if called outside of a mixin. + + <% example(autogen_css: false) do %> + @mixin debug-content-exists { + @debug meta.content-exists(); + @content; + } + + @include debug-content-exists; // false + @include debug-content-exists { // true + // Content! + } + === + @mixin debug-content-exists + @debug meta.content-exists() + @content + + + @include debug-content-exists // false + @include debug-content-exists // true + // Content! + <% end %> +<% end %> + + +<% function 'meta.feature-exists($feature)', + 'feature-exists($feature)', + returns: 'boolean' do %> + Returns whether the current Sass implementation supports `$feature`. + + The `$feature` must be a string. The currently recognized features are: + + * `global-variable-shadowing`, which means that a local variable will + [shadow][] a global variable unless it has the `!global` flag. + * `extend-selector-pseudoclass`, which means that the [`@extend` rule][] will + affect selectors nested in pseudo-classes like `:not()`. + * `units-level3`, which means that [unit arithmetic][] supports units defined + in [CSS Values and Units Level 3][]. + * `at-error`, which means that the [`@error` rule][] is supported. + * `custom-property`, which means that [custom property declaration][] values + don't support any [expressions][] other than [interpolation][]. + + [shadow]: ../variables#shadowing + [`@extend` rule]: ../at-rules/extend + [unit arithmetic]: ../values/numbers#units + [CSS Values and Units Level 3]: http://www.w3.org/TR/css3-values + [`@error` rule]: ../at-rules/error + [custom property declaration]: ../style-rules/declarations#custom-properties + [expressions]: ../syntax/structure#expressions + [interpolation]: ../interpolation + + Returns `false` for any unrecognized `$feature`. + + <% example(autogen_css: false) do %> + @debug meta.feature-exists("at-error"); // true + @debug meta.feature-exists("unrecognized"); // false + === + @debug meta.feature-exists("at-error") // true + @debug meta.feature-exists("unrecognized") // false + <% end %> +<% end %> + + +<% function 'meta.function-exists($name)', + 'function-exists($name)', + returns: 'boolean' do %> + Returns whether a function named `$name` is defined, either as a built-in + function or a user-defined function. + + <% example(autogen_css: false) do %> + @debug meta.function-exists("scale-color"); // true + @debug meta.function-exists("add"); // false + + @function add($num1, $num2) { + @return $num1 + $num2; + } + @debug meta.function-exists("add"); // true + === + @debug meta.function-exists("scale-color") // true + @debug meta.function-exists("add") // false + + @function add($num1, $num2) + @return $num1 + $num2 + + @debug meta.function-exists("add") // true + <% end %> +<% end %> + + +<% function 'meta.get-function($name, $css: false)', + 'get-function($name, $css: false)', + returns: 'function' do %> + Returns the [function][] named `$name`. + + [function]: ../values/functions + + This can access both built-in and [user-defined][] functions. By default, it + throws an error if `$name` doesn't refer to either a built-in or user-defined + function. However, if `$css` is `true`, it instead returns a + [plain CSS function][]. + + [user-defined]: ../at-rules/function + [plain CSS function]: ../at-rules/function#plain-css-functions + + The returned function can be called using [`meta.call()`](#call). + + <%= partial 'code-snippets/example-first-class-function' %> +<% end %> + + +<% function 'meta.global-variable-exists($name)', + 'global-variable-exists($name)', + returns: 'boolean' do %> + Returns whether a [global variable][] named `$name` (without the `$`) exists. + + [global variable]: ../variables#scope + + See also [`meta.variable-exists()`](#variable-exists). + + <% example(autogen_css: false) do %> + @debug meta.global-variable-exists("var1"); // false + + $var1: value; + @debug meta.global-variable-exists("var1"); // true + + h1 { + // $var2 is local. + $var2: value; + @debug meta.global-variable-exists("var2"); // false + } + === + @debug meta.global-variable-exists("var1") // false + + $var1: value + @debug meta.global-variable-exists("var1") // true + + h1 + // $var2 is local. + $var2: value + @debug meta.global-variable-exists("var2") // false + <% end %> +<% end %> + + +<% function 'meta.inspect($value)', + 'inspect($value)', + returns: 'unquoted string' do %> + Returns a string representation of `$value`. + + Returns a representation of *any* Sass value, not just those that can be + represented in CSS. As such, its return value is not guaranteed to be valid + CSS. + + <% heads_up do %> + This function is intended for debugging; its output format is not guaranteed + to be consistent across Sass versions or implementations. + <% end %> + + <% example(autogen_css: false) do %> + @debug meta.inspect(10px 20px 30px); // unquote("10px 20px 30px") + @debug meta.inspect(("width": 200px)); // unquote('("width": 200px)') + @debug meta.inspect(null); // unquote("null") + @debug meta.inspect("Helvetica"); // unquote('"Helvetica"') + === + @debug meta.inspect(10px 20px 30px) // unquote("10px 20px 30px") + @debug meta.inspect(("width": 200px)) // unquote('("width": 200px)') + @debug meta.inspect(null) // unquote("null") + @debug meta.inspect("Helvetica") // unquote('"Helvetica"') + <% end %> +<% end %> + + +<% function 'meta.keywords($args)', 'keywords($args)', returns: 'map' do %> + Returns the keywords passed to a mixin or function that takes [arbitrary + arguments][]. The `$args` argument must be an [argument list][]. + + [arbitrary arguments]: ../at-rules/mixin#taking-arbitrary-arguments + [argument list]: ../values/lists#argument-lists + + The keywords are returned as a map from argument names as unquoted strings (not + including `$`) to the values of those arguments. + + <%= partial 'code-snippets/example-mixin-arbitrary-keyword-arguments' %> +<% end %> + + +<% function 'meta.mixin-exists($name)', + 'mixin-exists($name)', + returns: 'boolean' do %> + Returns whether a [mixin][] named `$name` exists. + + [mixin]: ../at-rules/mixin + + <% example(autogen_css: false) do %> + @debug meta.mixin-exists("shadow-none"); // false + + @mixin shadow-none { + box-shadow: none; + } + + @debug meta.mixin-exists("shadow-none"); // true + === + @debug meta.mixin-exists("shadow-none") // false + + @mixin shadow-none + box-shadow: none + + + @debug meta.mixin-exists("shadow-none") // true + <% end %> +<% end %> + + +<% function 'meta.module-functions($module)', + returns: 'map' do %> + <%= partial '../snippets/module-system-function-status' %> + + Returns all the functions defined in a module, as a map from function names to + [function values][]. + + [function values]: ../values/functions + + The `$module` parameter must be a string matching the namespace of a [`@use` + rule][] in the current file. + + [`@use` rule]: ../at-rules/use + + <% example(autogen_css: false) do %> + // _functions.scss + @function pow($base, $exponent) { + $result: 1; + @for $_ from 1 through $exponent { + $result: $result * $base; + } + @return $result; + } + --- + @use "sass:map"; + @use "sass:meta"; + + @use "functions"; + + @debug meta.module-functions("functions"); // ("pow": get-function("pow")) + + @debug meta.call(map.get(meta.module-variables("functions"), "pow"), 3, 4); // 16 + === + // _functions.sass + @function pow($base, $exponent) + $result: 1 + @for $_ from 1 through $exponent + $result: $result * $base + + @return $result + --- + @use "sass:map" + @use "sass:meta" + + @use "functions" + + @debug meta.module-functions("functions") // ("pow": get-function("pow")) + + @debug meta.call(map.get(meta.module-variables("functions"), "pow"), 3, 4) // 16 + <% end %> +<% end %> + + +<% function 'meta.module-variables($module)', + returns: 'map' do %> + <%= partial '../snippets/module-system-function-status' %> + + Returns all the variables defined in a module, as a map from variable names + (without `$`) to the values of those variables. + + The `$module` parameter must be a string matching the namespace of a [`@use` + rule][] in the current file. + + [`@use` rule]: ../at-rules/use + + <% example(autogen_css: false) do %> + // _variables.scss + $hopbush: #c69; + $midnight-blue: #036; + $wafer: #e1d7d2; + --- + @use "sass:meta"; + + @use "variables"; + + @debug meta.module-variables("variables"); + // ( + // "hopbush": #c69, + // "midnight-blue": #036, + // "wafer": #e1d7d2 + // ) + === + // _variables.sass + $hopbush: #c69 + $midnight-blue: #036 + $wafer: #e1d7d2 + --- + @use "sass:meta" + + @use "variables" + + @debug meta.module-variables("variables") + // ( + // "hopbush": #c69, + // "midnight-blue": #036, + // "wafer": #e1d7d2 + // ) + <% end %> +<% end %> + + +<% function 'meta.type-of($value)', + 'type-of($value)', + returns: 'unquoted string' do %> + Returns the type of `$value`. + + This can return the following values: + + * [`number`](../values/numbers) + * [`string`](../values/strings) + * [`color`](../values/colors) + * [`list`](../values/lists) + * [`map`](../values/maps) + * [`bool`](../values/booleans) + * [`null`](../values/null) + * [`function`](../values/functions) + * [`arglist`](../values/lists#argument-lists) + + New possible values may be added in the future. It may return either `list` or + `map` for `()`, depending on whether or not it was returned by a + [map function][]. + + [map function]: map + + <% example(autogen_css: false) do %> + @debug meta.type-of(10px); // number + @debug meta.type-of(10px 20px 30px); // list + @debug meta.type-of(()); // list + === + @debug meta.type-of(10px) // number + @debug meta.type-of(10px 20px 30px) // list + @debug meta.type-of(()) // list + <% end %> +<% end %> + + +<% function 'meta.variable-exists($name)', + 'variable-exists($name)', + returns: 'boolean' do %> + Returns whether a variable named `$name` (without the `$`) exists in the + current [scope][]. + + [scope]: ../variables#scope + + See also [`meta.global-variable-exists()`](#global-variable-exists). + + <% example(autogen_css: false) do %> + @debug meta.variable-exists("var1"); // false + + $var1: value; + @debug meta.variable-exists("var1"); // true + + h1 { + // $var2 is local. + $var2: value; + @debug meta.variable-exists("var2"); // true + } + === + @debug meta.variable-exists("var1") // false + + $var1: value + @debug meta.variable-exists("var1") // true + + h1 + // $var2 is local. + $var2: value + @debug meta.variable-exists("var2") // true + <% end %> +<% end %> diff --git a/source/documentation/functions/selector.html.md.erb b/source/documentation/modules/selector.html.md.erb similarity index 52% rename from source/documentation/functions/selector.html.md.erb rename to source/documentation/modules/selector.html.md.erb index fa6d9f7a8..da33aab34 100644 --- a/source/documentation/functions/selector.html.md.erb +++ b/source/documentation/modules/selector.html.md.erb @@ -1,20 +1,22 @@ --- -title: Selector Functions +title: sass:selector --- +<%= partial '../snippets/built-in-module-status' %> + ## Selector Values -These functions inspect and manipulate selectors. Whenever they return a -selector, it's always a comma-separated [list][] (the selector list) that -contains space-separated lists (the complex selectors) that contain [unquoted -strings][] (the compound selectors). For example, the selector `.main +The functions in this module inspect and manipulate selectors. Whenever they +return a selector, it's always a comma-separated [list][] (the selector list) +that contains space-separated lists (the complex selectors) that contain +[unquoted strings][] (the compound selectors). For example, the selector `.main aside:hover, .sidebar p` would be returned as: [list]: ../values/lists [unquoted strings]: ../values/strings#unquoted ```scss -@debug ((unquote(".main") unquote("aside:hover")), +@debug selector.((unquote(".main") unquote("aside:hover")), (unquote(".sidebar") unquote("p"))); // .main aside:hover, .sidebar p ``` @@ -24,8 +26,9 @@ also just be normal strings (quoted or unquoted), or a combination. For example, `".main aside:hover, .sidebar p"` is a valid selector argument. -<% function 'is-superselector($super, $sub)', returns: 'boolean' do %> - +<% function 'selector.is-superselector($super, $sub)', + 'is-superselector($super, $sub)', + returns: 'boolean' do %> Returns whether the selector `$super` matches all the elements that the selector `$sub` matches. @@ -38,22 +41,24 @@ also just be normal strings (quoted or unquoted), or a combination. For example, [parent selectors]: ../style-rules/parent-selector <% example(autogen_css: false) do %> - @debug is-superselector("a", "a.disabled"); // true - @debug is-superselector("a.disabled", "a"); // false - @debug is-superselector("a", "sidebar a"); // true - @debug is-superselector("sidebar a", "a"); // false - @debug is-superselector("a", "a"); // true + @debug selector.is-superselector("a", "a.disabled"); // true + @debug selector.is-superselector("a.disabled", "a"); // false + @debug selector.is-superselector("a", "sidebar a"); // true + @debug selector.is-superselector("sidebar a", "a"); // false + @debug selector.is-superselector("a", "a"); // true === - @debug is-superselector("a", "a.disabled") // true - @debug is-superselector("a.disabled", "a") // false - @debug is-superselector("a", "sidebar a") // true - @debug is-superselector("sidebar a", "a") // false - @debug is-superselector("a", "a") // true + @debug selector.is-superselector("a", "a.disabled") // true + @debug selector.is-superselector("a.disabled", "a") // false + @debug selector.is-superselector("a", "sidebar a") // true + @debug selector.is-superselector("sidebar a", "a") // false + @debug selector.is-superselector("a", "a") // true <% end %> <% end %> -<% function 'selector-append($selectors...)', returns: 'selector' do %> +<% function 'selector.append($selectors...)', + 'selector-append($selectors...)', + returns: 'selector' do %> Combines `$selectors` without [descendant combinators][]—that is, without whitespace between them. @@ -68,23 +73,25 @@ also just be normal strings (quoted or unquoted), or a combination. For example, [placeholder selectors]: ../style-rules/placeholder-selectors [parent selectors]: ../style-rules/parent-selector - See also [`selector-nest()`](#selector-nest). + See also [`selector.nest()`](#nest). <% example(autogen_css: false) do %> - @debug selector-append("a", ".disabled"); // a.disabled - @debug selector-append(".accordion", "__copy"); // .accordion__copy - @debug selector-append(".accordion", "__copy, __image"); + @debug selector.append("a", ".disabled"); // a.disabled + @debug selector.append(".accordion", "__copy"); // .accordion__copy + @debug selector.append(".accordion", "__copy, __image"); // .accordion__copy, .accordion__image === - @debug selector-append("a", ".disabled") // a.disabled - @debug selector-append(".accordion", "__copy") // .accordion__copy - @debug selector-append(".accordion", "__copy, __image") + @debug selector.append("a", ".disabled") // a.disabled + @debug selector.append(".accordion", "__copy") // .accordion__copy + @debug selector.append(".accordion", "__copy, __image") // .accordion__copy, .accordion__image <% end %> <% end %> -<% function 'selector-extend($selector, $extendee, $extender)', returns: 'selector' do %> +<% function 'selector.extend($selector, $extendee, $extender)', + 'selector-extend($selector, $extendee, $extender)', + returns: 'selector' do %> Extends `$selector` as with the [`@extend` rule][]. [`@extend` rule]: ../at-rules/extend @@ -107,23 +114,25 @@ also just be normal strings (quoted or unquoted), or a combination. For example, [placeholder selectors]: ../style-rules/placeholder-selectors [parent selectors]: ../style-rules/parent-selector - See also [`selector-replace()`](#selector-replace). + See also [`selector.replace()`](#replace). <% example(autogen_css: false) do %> - @debug selector-extend("a.disabled", "a", ".link"); // a.disabled, .link.disabled - @debug selector-extend("a.disabled", "h1", "h2"); // a.disabled - @debug selector-extend(".guide .info", ".info", ".content nav.sidebar"); + @debug selector.extend("a.disabled", "a", ".link"); // a.disabled, .link.disabled + @debug selector.extend("a.disabled", "h1", "h2"); // a.disabled + @debug selector.extend(".guide .info", ".info", ".content nav.sidebar"); // .guide .info, .guide .content nav.sidebar, .content .guide nav.sidebar === - @debug selector-extend("a.disabled", "a", ".link") // a.disabled, .link.disabled - @debug selector-extend("a.disabled", "h1", "h2") // a.disabled - @debug selector-extend(".guide .info", ".info", ".content nav.sidebar") + @debug selector.extend("a.disabled", "a", ".link") // a.disabled, .link.disabled + @debug selector.extend("a.disabled", "h1", "h2") // a.disabled + @debug selector.extend(".guide .info", ".info", ".content nav.sidebar") // .guide .info, .guide .content nav.sidebar, .content .guide nav.sidebar <% end %> <% end %> -<% function 'selector-nest($selectors...)', returns: 'selector' do %> +<% function 'selector.nest($selectors...)', + 'selector-nest($selectors...)', + returns: 'selector' do %> Combines `$selectors` as though they were nested within one another in the stylesheet. @@ -133,38 +142,42 @@ also just be normal strings (quoted or unquoted), or a combination. For example, [placeholder selectors]: ../style-rules/placeholder-selectors [parent selectors]: ../style-rules/parent-selector - See also [`selector-append()`][]. + See also [`selector.append()`](#append). <% example(autogen_css: false) do %> - @debug selector-nest("ul", "li"); // ul li - @debug selector-nest(".alert, .warning", "p"); // .alert p, .warning p - @debug selector-nest(".alert", "&:hover"); // .alert:hover - @debug selector-nest(".accordion", "&__copy"); // .accordion__copy + @debug selector.nest("ul", "li"); // ul li + @debug selector.nest(".alert, .warning", "p"); // .alert p, .warning p + @debug selector.nest(".alert", "&:hover"); // .alert:hover + @debug selector.nest(".accordion", "&__copy"); // .accordion__copy === - @debug selector-nest("ul", "li") // ul li - @debug selector-nest(".alert, .warning", "p") // .alert p, .warning p - @debug selector-nest(".alert", "&:hover") // .alert:hover - @debug selector-nest(".accordion", "&__copy") // .accordion__copy + @debug selector.nest("ul", "li") // ul li + @debug selector.nest(".alert, .warning", "p") // .alert p, .warning p + @debug selector.nest(".alert", "&:hover") // .alert:hover + @debug selector.nest(".accordion", "&__copy") // .accordion__copy <% end %> <% end %> -<% function 'selector-parse($selector)', returns: 'selector' do %> +<% function 'selector.parse($selector)', + 'selector-parse($selector)', + returns: 'selector' do %> Returns `$selector` in the [selector value](#selector-values) format. <% example(autogen_css: false) do %> - @debug selector-parse(".main aside:hover, .sidebar p"); + @debug selector.parse(".main aside:hover, .sidebar p"); // ((unquote(".main") unquote("aside:hover")), // (unquote(".sidebar") unquote("p"))) === - @debug selector-parse(".main aside:hover, .sidebar p") + @debug selector.parse(".main aside:hover, .sidebar p") // ((unquote(".main") unquote("aside:hover")), // (unquote(".sidebar") unquote("p"))) <% end %> <% end %> -<% function 'selector-replace($selector, $original, $replacement)', returns: 'selector' do %> +<% function 'selector.replace($selector, $original, $replacement)', + 'selector-replace($selector, $original, $replacement)', + returns: 'selector' do %> Returns a copy of `$selector` with all instances of `$original` replaced by `$replacement`. @@ -181,24 +194,25 @@ also just be normal strings (quoted or unquoted), or a combination. For example, [placeholder selectors]: ../style-rules/placeholder-selectors [parent selectors]: ../style-rules/parent-selector - See also [`selector-extend()`](#selector-extend). + See also [`selector.extend()`](#extend). <% example(autogen_css: false) do %> - @debug selector-replace("a.disabled", "a", ".link"); // .link.disabled - @debug selector-replace("a.disabled", "h1", "h2"); // a.disabled - @debug selector-replace(".guide .info", ".info", ".content nav.sidebar"); + @debug selector.replace("a.disabled", "a", ".link"); // .link.disabled + @debug selector.replace("a.disabled", "h1", "h2"); // a.disabled + @debug selector.replace(".guide .info", ".info", ".content nav.sidebar"); // .guide .content nav.sidebar, .content .guide nav.sidebar === - @debug selector-replace("a.disabled", "a", ".link") // .link.disabled - @debug selector-replace("a.disabled", "h1", "h2") // a.disabled - @debug selector-replace(".guide .info", ".info", ".content nav.sidebar") + @debug selector.replace("a.disabled", "a", ".link") // .link.disabled + @debug selector.replace("a.disabled", "h1", "h2") // a.disabled + @debug selector.replace(".guide .info", ".info", ".content nav.sidebar") // .guide .content nav.sidebar, .content .guide nav.sidebar <% end %> <% end %> -<% function 'selector-unify($selector1, $selector2)', returns: 'selector | null' do %> - +<% function 'selector.unify($selector1, $selector2)', + 'selector.unify($selector1, $selector2)', + returns: 'selector | null' do %> Returns a selector that matches only elements matched by *both* `$selector1` and `$selector2`. @@ -212,21 +226,22 @@ also just be normal strings (quoted or unquoted), or a combination. For example, [`@extend` rule]: ../at-rules/extend#html-heuristics <% example(autogen_css: false) do %> - @debug selector-unify("a", ".disabled"); // a.disabled - @debug selector-unify("a.disabled", "a.outgoing"); // a.disabled.outgoing - @debug selector-unify("a", "h1"); // null - @debug selector-unify(".warning a", "main a"); // .warning main a, main .warning a + @debug selector.unify("a", ".disabled"); // a.disabled + @debug selector.unify("a.disabled", "a.outgoing"); // a.disabled.outgoing + @debug selector.unify("a", "h1"); // null + @debug selector.unify(".warning a", "main a"); // .warning main a, main .warning a === - @debug selector-unify("a", ".disabled") // a.disabled - @debug selector-unify("a.disabled", "a.outgoing") // a.disabled.outgoing - @debug selector-unify("a", "h1") // null - @debug selector-unify(".warning a", "main a") // .warning main a, main .warning a + @debug selector.unify("a", ".disabled") // a.disabled + @debug selector.unify("a.disabled", "a.outgoing") // a.disabled.outgoing + @debug selector.unify("a", "h1") // null + @debug selector.unify(".warning a", "main a") // .warning main a, main .warning a <% end %> <% end %> -<% function 'simple-selectors($selector)', returns: 'list' do %> - +<% function 'selector.simple-selectors($selector)', + 'simple-selectors($selector)', + returns: 'list' do %> Returns a list of simple selectors in `$selector`. The `$selector` must be a single string that contains a compound selector. @@ -236,10 +251,10 @@ also just be normal strings (quoted or unquoted), or a combination. For example, strings. <% example(autogen_css: false) do %> - @debug compound-selectors("a.disabled"); // a, .disabled - @debug compound-selectors("main.blog:after"); // main, .blog, :after + @debug selector.compound-selectors("a.disabled"); // a, .disabled + @debug selector.compound-selectors("main.blog:after"); // main, .blog, :after === - @debug compound-selectors("a.disabled") // a, .disabled - @debug compound-selectors("main.blog:after") // main, .blog, :after + @debug selector.compound-selectors("a.disabled") // a, .disabled + @debug selector.compound-selectors("main.blog:after") // main, .blog, :after <% end %> <% end %> diff --git a/source/documentation/modules/string.html.md.erb b/source/documentation/modules/string.html.md.erb new file mode 100644 index 000000000..b23bb52b9 --- /dev/null +++ b/source/documentation/modules/string.html.md.erb @@ -0,0 +1,163 @@ +--- +title: sass:string +--- + +<%= partial '../snippets/built-in-module-status' %> + +<% function 'string.quote($string)', 'quote($string)', returns: 'string' do %> + Returns `$string` as a quoted string. + + <% example(autogen_css: false) do %> + @debug string.quote(Helvetica); // "Helvetica" + @debug string.quote("Helvetica"); // "Helvetica" + === + @debug string.quote(Helvetica) // "Helvetica" + @debug string.quote("Helvetica") // "Helvetica" + <% end %> +<% end %> + + +<% function 'string.index($string, $substring)', + 'str-index($string, $substring)', + returns: 'number' do %> + Returns the first [index][] of `$substring` in `$string`, or `null` if + `$string` doesn't contain `$substring`. + + [index]: ../values/strings#string-indexes + + <% example(autogen_css: false) do %> + @debug string.index("Helvetica Neue", "Helvetica"); // 1 + @debug string.index("Helvetica Neue", "Neue"); // 11 + === + @debug string.index("Helvetica Neue", "Helvetica") // 1 + @debug string.index("Helvetica Neue", "Neue") // 11 + <% end %> +<% end %> + + +<% function 'string.insert($string, $insert, $index)', + 'str-insert($string, $insert, $index)', + returns: 'string' do %> + Returns a copy of `$string` with `$insert` inserted at [`$index`][]. + + [`$index`]: ../values/strings#string-indexes + + <% example(autogen_css: false) do %> + @debug string.insert("Roboto Bold", " Mono", 7); // "Roboto Mono Bold" + @debug string.insert("Roboto Bold", " Mono", -6); // "Roboto Mono Bold" + === + @debug string.insert("Roboto Bold", " Mono", 7) // "Roboto Mono Bold" + @debug string.insert("Roboto Bold", " Mono", -6) // "Roboto Mono Bold" + <% end %> + + If of `$index` is higher than the length of `$string`, `$insert` is added to + the end. If `$index` is smaller than the negative length of the string, + `$insert` is added to the beginning. + + <% example(autogen_css: false) do %> + @debug string.insert("Roboto", " Bold", 100); // "Roboto Bold" + @debug string.insert("Bold", "Roboto ", -100); // "Roboto Bold" + === + @debug string.insert("Roboto", " Bold", 100) // "Roboto Bold" + @debug string.insert("Bold", "Roboto ", -100) // "Roboto Bold" + <% end %> +<% end %> + + +<% function 'string.length($string)', + 'str-length($string)', + returns: 'number' do %> + Returns the number of characters in `$string`. + + <% example(autogen_css: false) do %> + @debug string.length("Helvetica Neue"); // 14 + @debug string.length(bold); // 4 + @debug string.index(""); // 0 + === + @debug string.length("Helvetica Neue") // 14 + @debug string.length(bold) // 4 + @debug string.index("") // 0 + <% end %> +<% end %> + + +<% function 'string.slice($string, $start-at, $end-at: -1)', + 'str-slice($string, $start-at, $end-at: -1)', + returns: 'string' do %> + Returns the slice of `$string` starting at [index][] `$start-at` and ending at + index `$end-at` (both inclusive). + + [index]: ../values/strings#string-indexes + + <% example(autogen_css: false) do %> + @debug string.slice("Helvetica Neue", 11); // "Neue" + @debug string.slice("Helvetica Neue", 1, 3); // "Hel" + @debug string.slice("Helvetica Neue", 1, -6); // "Helvetica" + === + @debug string.slice("Helvetica Neue", 11) // "Neue" + @debug string.slice("Helvetica Neue", 1, 3) // "Hel" + @debug string.slice("Helvetica Neue", 1, -6) // "Helvetica" + <% end %> +<% end %> + + +<% function 'string.to-upper-case($string)', + 'to-upper-case($string)', + returns: 'string' do %> + Returns a copy of `$string` with the [ASCII][] letters converted to upper case. + + [ASCII]: https://en.wikipedia.org/wiki/ASCII + + <% example(autogen_css: false) do %> + @debug string.to-upper-case("Bold"); // "BOLD" + @debug string.to-upper-case(sans-serif); // SANS-SERIF + === + @debug string.to-upper-case("Bold") // "BOLD" + @debug string.to-upper-case(sans-serif) // SANS-SERIF + <% end %> +<% end %> + + +<% function 'string.to-lower-case($string)', + 'to-lower-case($string)', + returns: 'string' do %> + Returns a copy of `$string` with the [ASCII][] letters converted to lower case. + + [ASCII]: https://en.wikipedia.org/wiki/ASCII + + <% example(autogen_css: false) do %> + @debug string.to-lower-case("Bold"); // "bold" + @debug string.to-lower-case(SANS-SERIF); // sans-serif + === + @debug string.to-lower-case("Bold") // "bold" + @debug string.to-lower-case(SANS-SERIF) // sans-serif + <% end %> +<% end %> + + +<% function 'string.unique-id()', 'unique-id()', returns: 'string' do %> + Returns a randomly-generated unquoted string that's guaranteed to be a valid + CSS identifier and to be unique within the current Sass compilation. + + <% example(autogen_css: false) do %> + @debug string.unique-id(); // uabtrnzug + @debug string.unique-id(); // u6w1b1def + === + @debug string.unique-id(); // uabtrnzug + @debug string.unique-id(); // u6w1b1def + <% end %> +<% end %> + + +<% function 'string.unquote()', 'unquote()', returns: 'string' do %> + Returns `$string` as an unquoted string. This can produce strings that aren't + valid CSS, so use with caution. + + <% example(autogen_css: false) do %> + @debug string.unquote("Helvetica"); // Helvetica + @debug string.unquote(".widget:hover"); // .widget:hover + === + @debug string.unquote("Helvetica") // Helvetica + @debug string.unquote(".widget:hover") // .widget:hover + <% end %> +<% end %> diff --git a/source/documentation/operators.html.md.erb b/source/documentation/operators.html.md.erb index e09fc83a6..e5b0e8baa 100644 --- a/source/documentation/operators.html.md.erb +++ b/source/documentation/operators.html.md.erb @@ -22,7 +22,7 @@ introduction: > They're still supported in LibSass and Ruby Sass, but they'll produce warnings and users are strongly encouraged to avoid them. - [Color functions]: functions/color + [Color functions]: modules/color <% end %> ## Order of Operations diff --git a/source/documentation/snippets/_built-in-module-status.erb b/source/documentation/snippets/_built-in-module-status.erb new file mode 100644 index 000000000..657dcfd4d --- /dev/null +++ b/source/documentation/snippets/_built-in-module-status.erb @@ -0,0 +1,4 @@ +<% impl_status dart: '(unreleased)', libsass: false, ruby: false do %> + Only Dart Sass currently supports loading built-in modules with `@use`. Users + of other implementations must call functions using their global names instead. +<% end %> diff --git a/source/documentation/snippets/_call-impl-status.html.erb b/source/documentation/snippets/_call-impl-status.html.erb index 14d5972b5..ecc2104f0 100644 --- a/source/documentation/snippets/_call-impl-status.html.erb +++ b/source/documentation/snippets/_call-impl-status.html.erb @@ -4,7 +4,7 @@ value instead in preparation for a new module system where functions are no longer global and so a given name may not always refer to the same function. - [`call()` function]: /documentation/functions/meta#call + [`call()` function]: /documentation/modules/meta#call Passing a string to `call()` still works in all implementations, but it's deprecated and will be disallowed in future versions. diff --git a/source/documentation/snippets/_module-system-function-status.erb b/source/documentation/snippets/_module-system-function-status.erb new file mode 100644 index 000000000..8a462db2c --- /dev/null +++ b/source/documentation/snippets/_module-system-function-status.erb @@ -0,0 +1,3 @@ +<% impl_status dart: '(unreleased)', libsass: false, ruby: false do %> + Only Dart Sass currently supports this function. +<% end %> diff --git a/source/documentation/snippets/_module-system-status.erb b/source/documentation/snippets/_module-system-status.erb new file mode 100644 index 000000000..45073ecc2 --- /dev/null +++ b/source/documentation/snippets/_module-system-status.erb @@ -0,0 +1,6 @@ +<% impl_status dart: '(unreleased)', libsass: false, ruby: false do %> + Only Dart Sass currently supports `@use`. Users of other implementations must + use the [`@import` rule][] instead. + + [`@import` rule]: /documentation/at-rules/import +<% end %> diff --git a/source/documentation/snippets/_number-units.erb b/source/documentation/snippets/_number-units.erb index e8146bc8b..615b002e6 100644 --- a/source/documentation/snippets/_number-units.erb +++ b/source/documentation/snippets/_number-units.erb @@ -128,7 +128,7 @@ to get the time it should take. [unquoted string]: /documentation/values/strings#unquoted [number operations]: /documentation/operators/numeric - [functions]: /documentation/functions/math + [functions]: /documentation/modules/math <% end %> <% heads_up do %> @@ -140,8 +140,8 @@ to get the time it should take. You can convert between decimals and percentages using unit arithmetic. `$percentage / 100%` will return the corresponding decimal, and `$decimal * 100%` will return the corresponding percentage. You can also use the - [`percentage()` function][] as a more explicit way of writing `$decimal * + [`math.percentage()` function][] as a more explicit way of writing `$decimal * 100%`. - [`percentage()` function]: /documentation/functions/math#percentage + [`math.percentage()` function]: /documentation/modules/math#percentage <% end %> diff --git a/source/documentation/snippets/_truthiness-and-falsiness.erb b/source/documentation/snippets/_truthiness-and-falsiness.erb index 673329dcc..678dc920b 100644 --- a/source/documentation/snippets/_truthiness-and-falsiness.erb +++ b/source/documentation/snippets/_truthiness-and-falsiness.erb @@ -9,10 +9,10 @@ succeed. [`null`]: /documentation/values/null For example, if you want to check if a string contains a space, you can just -write `index($string, " ")`. The [`str-index()` function][] returns `null` if -the string isn't found and a number otherwise. +write `string.index($string, " ")`. The [`string.index()` function][] returns +`null` if the string isn't found and a number otherwise. -[`str-index()` function]: /documentation/functions/string#str-index +[`string.index()` function]: /documentation/modules/string#index <% heads_up do %> Some languages consider more values falsey than just `false` and `null`. Sass diff --git a/source/documentation/style-rules.html.md.erb b/source/documentation/style-rules.html.md.erb index c2236dc68..70814708e 100644 --- a/source/documentation/style-rules.html.md.erb +++ b/source/documentation/style-rules.html.md.erb @@ -163,4 +163,4 @@ generating selectors. For more information, see the [parent selector documentation][]. [`@at-root` rule]: at-rules/at-root -[selector functions]: functions/selector +[selector functions]: modules/selector diff --git a/source/documentation/style-rules/declarations.html.md.erb b/source/documentation/style-rules/declarations.html.md.erb index 9caa0e8b3..9ede40f35 100644 --- a/source/documentation/style-rules/declarations.html.md.erb +++ b/source/documentation/style-rules/declarations.html.md.erb @@ -196,26 +196,35 @@ is the only way to inject dynamic values into a custom property. <% heads_up do %> Unfortunately, [interpolation][] removes quotes from strings, which makes it difficult to use quoted strings as values for custom properties when they come - from Sass variables. As a workaround, you can use the [`inspect()` function][] - to preserve the quotes. + from Sass variables. As a workaround, you can use the [`meta.inspect()` + function][] to preserve the quotes. [interpolation]: ../interpolation - [`inspect()` function]: ../functions/meta#inspect + [`meta.inspect()` function]: ../modules/meta#inspect <% example do %> + @use "sass:meta"; + $font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto; $font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas; :root { - --font-family-sans-serif: #{inspect($font-family-sans-serif)}; - --font-family-monospace: #{inspect($font-family-monospace)}; + --font-family-sans-serif: #{meta.inspect($font-family-sans-serif)}; + --font-family-monospace: #{meta.inspect($font-family-monospace)}; } === + @use "sass:meta" + $font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto $font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas :root - --font-family-sans-serif: #{inspect($font-family-sans-serif)} - --font-family-monospace: #{inspect($font-family-monospace)} + --font-family-sans-serif: #{meta.inspect($font-family-sans-serif)} + --font-family-monospace: #{meta.inspect($font-family-monospace)} + === + :root { + --font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto; + --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas; + } <% end %> <% end %> diff --git a/source/documentation/style-rules/parent-selector.html.md.erb b/source/documentation/style-rules/parent-selector.html.md.erb index d8105acdc..947b5b1c3 100644 --- a/source/documentation/style-rules/parent-selector.html.md.erb +++ b/source/documentation/style-rules/parent-selector.html.md.erb @@ -138,7 +138,7 @@ strings (the compound selectors). // (unquote(".sidebar") unquote("p"))) <% end %> -[selector functions]: ../functions/selector#selector-values +[selector functions]: ../modules/selector#selector-values If the `&` expression is used outside any style rules, it returns `null`. Since `null` is [falsey][], this means you can easily use it to determine whether a diff --git a/source/documentation/syntax.html.md b/source/documentation/syntax.html.md index 2e686adcc..84540b952 100644 --- a/source/documentation/syntax.html.md +++ b/source/documentation/syntax.html.md @@ -1,7 +1,7 @@ --- title: Syntax introduction: > - Sass supports two different syntaxes. Each one can import the other, so it's + Sass supports two different syntaxes. Each one can load the other, so it's up to you and your team which one to choose. --- diff --git a/source/documentation/syntax/special-functions.html.md.erb b/source/documentation/syntax/special-functions.html.md.erb index 7dc2aa2c6..27d9ba0c7 100644 --- a/source/documentation/syntax/special-functions.html.md.erb +++ b/source/documentation/syntax/special-functions.html.md.erb @@ -4,10 +4,10 @@ table_of_contents: true introduction: > CSS defines many functions, and most of them work just fine with Sass’s normal function syntax. They’re parsed as function calls, resolved to [plain CSS - functions](../functions/css), and compiled as-is to CSS. There are a few - exceptions, though, which have special syntax that can’t just be parsed as a - [SassScript expression](structure#expressions). All special function calls - return [unquoted strings](../values/strings#unquoted). + functions](../at-rules/function#plain-css-functions), and compiled as-is to + CSS. There are a few exceptions, though, which have special syntax that can’t + just be parsed as a [SassScript expression](structure#expressions). All + special function calls return [unquoted strings](../values/strings#unquoted). --- ## `url()` @@ -27,7 +27,7 @@ calls][]—it's parsed as a normal [plain CSS function call][]. [interpolation]: ../interpolation [variables]: ../variables [function calls]: ../at-rules/function -[plain CSS function call]: ../functions/css +[plain CSS function call]: ../at-rules/function#plain-css-functions <% example do %> $roboto-font-path: "../fonts/roboto"; @@ -140,8 +140,8 @@ cleverness. [`min()` and `max()` functions]: https://drafts.csswg.org/css-values-4/#calc-notation [to support the iPhoneX]: https://webkit.org/blog/7929/designing-websites-for-iphone-x/ -[`min()`]: ../functions/math#min -[`max()`]: ../functions/math#max +[`min()`]: ../modules/math#min +[`max()`]: ../modules/math#max If a `min()` or `max()` function call is valid plain CSS, it will be compiled to a CSS `min()` or `max()` call. "Plain CSS" includes nested calls to diff --git a/source/documentation/syntax/structure.html.md.erb b/source/documentation/syntax/structure.html.md.erb index d5810ec46..f92361361 100644 --- a/source/documentation/syntax/structure.html.md.erb +++ b/source/documentation/syntax/structure.html.md.erb @@ -43,6 +43,7 @@ These statements produce CSS. They can be used anywhere except within a These statements can only be used at the top level of a stylesheet, or nested within a CSS statement at the top level: +* [Module loads](../at-rules/use), using `@use`. * [Imports](../at-rules/import), using `@import`. * [Mixin definitions](../at-rules/mixin) using `@mixin`. * [Function definitions](../at-rules/function) using `@function`. diff --git a/source/documentation/values.html.md b/source/documentation/values.html.md index d432afeeb..f53029399 100644 --- a/source/documentation/values.html.md +++ b/source/documentation/values.html.md @@ -33,5 +33,5 @@ A few more are specific to Sass: * [Function references](values/functions) returned by [`get-function()`][] and called with [`call()`][]. -[`get-function()`]: functions/meta#get-function -[`call()`]: functions/meta#call +[`get-function()`]: modules/meta#get-function +[`call()`]: modules/meta#call diff --git a/source/documentation/values/booleans.html.md.erb b/source/documentation/values/booleans.html.md.erb index b70005760..7dfc041fa 100644 --- a/source/documentation/values/booleans.html.md.erb +++ b/source/documentation/values/booleans.html.md.erb @@ -4,20 +4,24 @@ introduction: > Booleans are the logical values `true` and `false`. In addition their literal forms, booleans are returned by [equality](../operators/equality) and [relational](../operators/relational) operators, as well as many built-in - functions like [`comparable()`](../functions/math#comparable) and - [`map-has-key()`](../functions/map#map-has-key). + functions like [`math.comparable()`](../modules/math#comparable) and + [`map.has-key()`](../modules/map#has-key). --- <% example(autogen_css: false) do %> + @use "sass:math"; + @debug 1px == 2px; // false @debug 1px == 1px; // true @debug 10px < 3px; // false - @debug comparable(100px, 3in); // true + @debug math.comparable(100px, 3in); // true === + @use "sass:math"; + @debug 1px == 2px // false @debug 1px == 1px // true @debug 10px < 3px // false - @debug comparable(100px, 3in) // true + @debug math.comparable(100px, 3in) // true <% end %> You can work with booleans using [boolean operators][]. The `and` operator @@ -59,7 +63,7 @@ You can use booleans to choose whether or not to do various things in Sass. The The [`if()` function][] chooses returns one value if its argument is `true` and another if its argument is `false`: -[`if()` function]: ../functions#if +[`if()` function]: ../modules#if <% example(autogen_css: false) do %> @debug if(true, 10px, 30px); // 10px diff --git a/source/documentation/values/colors.html.md.erb b/source/documentation/values/colors.html.md.erb index ff4f1cdad..40d4f419c 100644 --- a/source/documentation/values/colors.html.md.erb +++ b/source/documentation/values/colors.html.md.erb @@ -17,13 +17,13 @@ codes (`#f2ece4` or `#b37399aa`), [CSS color names][] (`midnightblue`, [`hsla()`][]. [sRGB color space]: https://en.wikipedia.org/wiki/SRGB -[color functions]: ../functions/color +[color functions]: ../modules/color [HSL color space]: https://en.wikipedia.org/wiki/HSL_and_HSV [CSS color names]: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords -[`rgb()`]: ../functions/color#rgb -[`rgba()`]: ../functions/color#rgba -[`hsl()`]: ../functions/color#hsl -[`hsla()`]: ../functions/color#hsla +[`rgb()`]: ../modules#rgb +[`rgba()`]: ../modules#rgba +[`hsl()`]: ../modules#hsl +[`hsla()`]: ../modules#hsla <% example(autogen_css: false) do %> @debug #f2ece4; // #f2ece4 @@ -61,8 +61,8 @@ Sass supports many useful [color functions][] that can be used to create new colors based on existing ones by [mixing colors together][] or [scaling their hue, saturation, or lightness][]. -[mixing colors together]: ../functions/color#mix -[scaling their hue, saturation, or lightness]: ../functions/color#scale-color +[mixing colors together]: ../modules/color#mix +[scaling their hue, saturation, or lightness]: ../modules/color#scale <% example(autogen_css: false) do %> $venus: #998099; diff --git a/source/documentation/values/functions.html.md.erb b/source/documentation/values/functions.html.md.erb index 7a27ae1d1..f9f3606c0 100644 --- a/source/documentation/values/functions.html.md.erb +++ b/source/documentation/values/functions.html.md.erb @@ -5,13 +5,13 @@ title: Functions <%= partial 'documentation/snippets/call-impl-status' %> [Functions][] can be values too! You can't directly write a function as a value, -but you can pass a function's name to the [`get-function()` function][] to get -it as a value. Once you have a function value, you can pass it to the [`call()` -function][] to call it. This is useful for writing *higher-order functions* that -call other functions. +but you can pass a function's name to the [`meta.get-function()` function][] to +get it as a value. Once you have a function value, you can pass it to the +[`meta.call()` function][] to call it. This is useful for writing *higher-order +functions* that call other functions. [Functions]: ../at-rules/function -[`get-function` function]: ../functions/meta#get-function -[`call()` function]: ../functions/meta#call +[`meta.get-function` function]: ../modules/meta#get-function +[`meta.call()` function]: ../modules/meta#call <%= partial 'code-snippets/example-first-class-function' %> diff --git a/source/documentation/values/lists.html.md.erb b/source/documentation/values/lists.html.md.erb index f984373bf..c8c74ace5 100644 --- a/source/documentation/values/lists.html.md.erb +++ b/source/documentation/values/lists.html.md.erb @@ -25,7 +25,7 @@ can be written either `()` or `[]`. Also, all [list functions][] will treat individual values that aren't in lists as though they're lists containing that value, which means you rarely need to explicitly create single-element lists. -[list functions]: ../functions/list +[list functions]: ../modules/list <% heads_up do %> Empty lists without brackets aren't valid CSS, so Sass won't let you use one @@ -38,7 +38,7 @@ Sass provides a handful of [functions][] that make it possible to use lists to write powerful style libraries, or to make your app's stylesheet cleaner and more maintainable. -[functions]: ../functions/list +[functions]: ../modules/list ### Indexes @@ -51,11 +51,11 @@ to the last element in a list, -2 refers to the second-to-last, and so on. ### Access an Element Lists aren't much use if you can't get values out of them. You can use the -[`nth($list, $n)` function][] to get the element at a given index in a list. The -first argument is the list itself, and the second is the index of the value you -want to get out. +[`list.nth($list, $n)` function][] to get the element at a given index in a +list. The first argument is the list itself, and the second is the index of the +value you want to get out. -[`nth($list, $n)` function]: ../functions/list#nth +[`list.nth($list, $n)` function]: ../modules/list#nth <%= partial 'code-snippets/example-list-nth' %> @@ -71,12 +71,12 @@ in a list, and assigns that element to a variable. ### Add to a List -It's also useful to add elements to a list. The [`append($list, $val)` +It's also useful to add elements to a list. The [`list.append($list, $val)` function][] takes a list and a value, and returns a copy of the list with the value added to the end. Note that because Sass lists are [immutable][], it doesn't modify the original list. -[`append($list, $val)` function]: ../functions/list#append +[`list.append($list, $val)` function]: ../modules/list#append [immutable]: #immutability <% example(autogen_css: false) do %> @@ -90,37 +90,41 @@ modify the original list. ### Find an Element in a List If you need to check if an element is in a list or figure out what index it's -at, use the [`index($list, $value)` function][]. This takes a list and a value +at, use the [`list.index($list, $value)` function][]. This takes a list and a value to locate in that list, and returns the index of that value. -[`index($list, $value)` function]: ../functions/list#index +[`list.index($list, $value)` function]: ../modules/list#index <%= partial 'code-snippets/example-list-index' %> -If the value isn't in the list at all, `index()` returns [`null`][]. Because -`null` is [falsey][], you can use `index()` with [`@if`][] or [`if()`][] to +If the value isn't in the list at all, `list.index()` returns [`null`][]. Because +`null` is [falsey][], you can use `list.index()` with [`@if`][] or [`if()`][] to check whether a list does or doesn't contain a given value. [`null`]: null [falsey]: ../at-rules/control/if#truthiness-and-falsiness [`@if`]: ../at-rules/control/if -[`if()`]: ../functions#if +[`if()`]: ../modules#if + +<% example(autogen_css: false) do %> + @use "sass:list"; -<% example do %> $valid-sides: top, bottom, left, right; @mixin attach($side) { - @if not index($valid-sides, $side) { + @if not list.index($valid-sides, $side) { @error "#{$side} is not a valid side. Expected one of #{$sides}."; } // ... } === + @use "sass:list" + $valid-sides: top, bottom, left, right @mixin attach($side) - @if not index($valid-sides, $side) + @if not list.index($valid-sides, $side) @error "#{$side} is not a valid side. Expected one of #{$sides}." @@ -138,25 +142,31 @@ You can still update your state over time by assigning new lists to the same variable, though. This is often used in functions and mixins to collect a bunch of values into one list. -<% example do %> +<% example(autogen_css: false) do %> + @use "sass:list"; + @use "sass:map"; + $prefixes-by-browser: ("firefox": moz, "safari": webkit, "ie": ms); @function prefixes-for-browsers($browsers) { $prefixes: (); @each $browser in $browsers { - $prefixes: append($prefixes, map-get($prefixes-by-browser, $browser)); + $prefixes: list.append($prefixes, map.get($prefixes-by-browser, $browser)); } @return $prefixes; } @debug prefixes-for-browsers("firefox" "ie"); // moz ms === + @use "sass:list" + @use "sass:map" + $prefixes-by-browser: ("firefox": moz, "safari": webkit, "ie": ms) @function prefixes-for-browsers($browsers) $prefixes: () @each $browser in $browsers - $prefixes: append($prefixes, map-get($prefixes-by-browser, $browser)) + $prefixes: list.append($prefixes, map.get($prefixes-by-browser, $browser)) @return $prefixes @@ -170,9 +180,9 @@ When you declare a mixin or function that takes [arbitrary arguments][], the value you get is a special list known as an *argument list*. It acts just like a list that contains all the arguments passed to the mixin or function, with one extra feature: if the user passed keyword arguments, they can be accessed as a -map by passing the argument list to the [`keywords()` function][]. +map by passing the argument list to the [`meta.keywords()` function][]. <%= partial 'code-snippets/example-mixin-arbitrary-keyword-arguments' %> [arbitrary arguments]: ../at-rules/mixin#taking-arbitrary-arguments -[`keywords()` function]: ../functions/map#keywords +[`meta.keywords()` function]: ../modules/meta#keywords diff --git a/source/documentation/values/maps.html.md.erb b/source/documentation/values/maps.html.md.erb index ca38323a8..80ea60d99 100644 --- a/source/documentation/values/maps.html.md.erb +++ b/source/documentation/values/maps.html.md.erb @@ -40,16 +40,16 @@ Since maps aren't valid CSS values, they don't do much of anything on their own. That's why Sass provides a bunch of [functions][] to create maps and access the values they contain. With -[functions]: ../functions/map +[functions]: ../modules/map ### Look Up a Value Maps are all about associating keys and values, so naturally there's a way to -get the value associated with a key: the [`map-get($map, $key)` function][]! +get the value associated with a key: the [`map.get($map, $key)` function][]! This function returns the value in the map associated with the given key. It returns [`null`][] if the map doesn't contain the key. -[`map-get($map, $key)` function]: ../functions/map#map-get +[`map.get($map, $key)` function]: ../modules/map#get [`null`]: null <%= partial 'code-snippets/example-map-get' %> @@ -68,16 +68,18 @@ easily be accessed in the block. ### Add to a Map It's also useful to add new pairs to a map, or to replace the value for an -existing key. The [`map-merge($map1, $map2)` function][] does this: it returns a +existing key. The [`map.merge($map1, $map2)` function][] does this: it returns a new map that contains all the key/value pairs in *both* arguments. -[`map-merge($map1, $map2)` function]: ../functions/map#map-merge +[`map.merge($map1, $map2)` function]: ../modules/map#merge <% example(autogen_css: false) do %> + @use "sass:map"; + $light-weights: ("lightest": 100, "light": 300); $heavy-weights: ("medium": 500, "bold": 700); - @debug map-merge($light-weights, $heavy-weights); + @debug map.merge($light-weights, $heavy-weights); // ( // "lightest": 100, // "light": 300, @@ -85,10 +87,12 @@ new map that contains all the key/value pairs in *both* arguments. // "bold": 700 // ) === + @use "sass:map" + $light-weights: ("lightest": 100, "light": 300) $heavy-weights: ("medium": 500, "bold": 700) - @debug map-merge($light-weights, $heavy-weights) + @debug map.merge($light-weights, $heavy-weights) // ( // "lightest": 100, // "light": 300, @@ -97,17 +101,21 @@ new map that contains all the key/value pairs in *both* arguments. // ) <% end %> -`map-merge()` is often used with an inline map to add a single key/value pair. +`map.merge()` is often used with an inline map to add a single key/value pair. <% example(autogen_css: false) do %> + @use "sass:map"; + $font-weights: ("regular": 400, "medium": 500, "bold": 700); - @debug map-merge($font-weights, ("extra-bold": 900)); + @debug map.merge($font-weights, ("extra-bold": 900)); // ("regular": 400, "medium": 500, "bold": 700, "extra-bold": 900) === + @use "sass:map" + $font-weights: ("regular": 400, "medium": 500, "bold": 700) - @debug map-merge($font-weights, ("extra-bold": 900)) + @debug map.merge($font-weights, ("extra-bold": 900)) // ("regular": 400, "medium": 500, "bold": 700, "extra-bold": 900) <% end %> @@ -115,18 +123,22 @@ If both maps have the same keys, the second map's values are used in the map that gets returned. <% example(autogen_css: false) do %> + @use "sass:map"; + $font-weights: ("regular": 400, "medium": 500, "bold": 700); - @debug map-merge($font-weights, ("medium": 600)); + @debug map.merge($font-weights, ("medium": 600)); // ("regular": 400, "medium": 600, "bold": 700) === + @use "sass:map" + $font-weights: ("regular": 400, "medium": 500, "bold": 700) - @debug map-merge($font-weights, ("medium": 600)) + @debug map.merge($font-weights, ("medium": 600)) // ("regular": 400, "medium": 600, "bold": 700) <% end %> -Note that because Sass maps are [immutable][], `map-merge()` doesn't modify the +Note that because Sass maps are [immutable][], `map.merge()` doesn't modify the original list. [immutable]: #immutability @@ -143,20 +155,24 @@ variable, though. This is often used in functions and mixins to track configuration in a map. <% example(autogen_css: false) do %> + @use "sass:map"; + $prefixes-by-browser: ("firefox": moz, "safari": webkit, "ie": ms); @mixin add-browser-prefix($browser, $prefix) { - $prefixes-by-browser: map-merge($prefixes-by-browser, ($browser: $prefix)); + $prefixes-by-browser: map.merge($prefixes-by-browser, ($browser: $prefix)); } @include add-browser-prefix("opera", o); @debug $prefixes-by-browser; // ("firefox": moz, "safari": webkit, "ie": ms, "opera": o) === + @use "sass:map"; + $prefixes-by-browser: ("firefox": moz, "safari": webkit, "ie": ms) @mixin add-browser-prefix($browser, $prefix) - $prefixes-by-browser: map-merge($prefixes-by-browser, ($browser: $prefix)) + $prefixes-by-browser: map.merge($prefixes-by-browser, ($browser: $prefix)) @include add-browser-prefix("opera", o) diff --git a/source/documentation/values/null.html.md.erb b/source/documentation/values/null.html.md.erb index 970a531ea..e4cf1cd1a 100644 --- a/source/documentation/values/null.html.md.erb +++ b/source/documentation/values/null.html.md.erb @@ -7,12 +7,18 @@ introduction: > --- <% example(autogen_css: false) do %> - @debug str-index("Helvetica Neue", "Roboto"); // null - @debug map-get(("large": 20px), "small"); // null + @use "sass:map"; + @use "sass:string"; + + @debug string.index("Helvetica Neue", "Roboto"); // null + @debug map.get(("large": 20px), "small"); // null @debug &; // null === - @debug str-index("Helvetica Neue", "Roboto") // null - @debug map-get(("large": 20px), "small") // null + @use "sass:map"; + @use "sass:string"; + + @debug string.index("Helvetica Neue", "Roboto") // null + @debug map.get(("large": 20px), "small") // null @debug & // null <% end %> @@ -62,6 +68,6 @@ If a property value is `null`, that property is omitted entirely. [*falsey*]: ../at-rules/control/if#truthiness-and-falsiness [operators]: ../operators/boolean [`@if`]: ../at-rules/control/if -[`if()`]: ../functions#if +[`if()`]: ../modules#if <%= partial 'code-snippets/example-if-parent-selector' %> diff --git a/source/documentation/values/numbers.html.md.erb b/source/documentation/values/numbers.html.md.erb index bc945f75e..2bbdcd793 100644 --- a/source/documentation/values/numbers.html.md.erb +++ b/source/documentation/values/numbers.html.md.erb @@ -61,12 +61,12 @@ means a few different things: they're the same up to the tenth digit after the decimal point. * If a number is less than `0.0000000001` away from an integer, it's considered - to be an integer for the purposes of functions like [`nth()`][] that require + to be an integer for the purposes of functions like [`list.nth()`][] that require integer arguments. [`==`]: ../operators/equality [`>=`]: ../operators/relational -[`nth()`]: ../functions/list#nth +[`list.nth()`]: ../modules/list#nth <% example(autogen_css: false) do %> @debug 0.012345678912345; // 0.0123456789 diff --git a/source/documentation/values/strings.html.md.erb b/source/documentation/values/strings.html.md.erb index 8b794f387..a925486ca 100644 --- a/source/documentation/values/strings.html.md.erb +++ b/source/documentation/values/strings.html.md.erb @@ -11,19 +11,23 @@ introduction: > --- <% fun_fact do %> - You can convert a quoted string to an unquoted string using the [`unquote()` - function][], and you can convert an unquoted string to a quoted string using - the [`quote()` function][]. + You can convert a quoted string to an unquoted string using the + [`string.unquote()` function][], and you can convert an unquoted string to a + quoted string using the [`string.quote()` function][]. - [`unquote()` function]: ../functions/string#unquote - [`quote()` function]: ../functions/string#quote + [`string.unquote()` function]: ../modules/string#unquote + [`string.quote()` function]: ../modules/string#quote <% example(autogen_css: false) do %> - @debug unquote(".widget:hover"); // .widget:hover - @debug quote(bold); // "bold" + @use "sass:string"; + + @debug string.unquote(".widget:hover"); // .widget:hover + @debug string.quote(bold); // "bold" === - @debug unquote(".widget:hover") // .widget:hover - @debug quote(bold) // "bold" + @use "sass:string" + + @debug string.unquote(".widget:hover") // .widget:hover + @debug string.quote(bold) // "bold" <% end %> <% end %> @@ -182,16 +186,20 @@ code point, whether it's escaped or unescaped: * Otherwise, the lowercase Unicode escape is included with a trailing space. For example, `\7Fx` returns the unquoted string `\7f x`. -<% example do %> +<% example(autogen_css: false) do %> + @use "sass:string"; + @debug \1F46D; // 👭 @debug \21; // \! @debug \7Fx; // \7f x - @debug str-length(\7Fx); // 5 + @debug string.length(\7Fx); // 5 === + @use "sass:string" + @debug \1F46D // 👭 @debug \21 // \! @debug \7Fx // \7f x - @debug str-length(\7Fx) // 5 + @debug string.length(\7Fx) // 5 <% end %> ## String Indexes @@ -203,14 +211,18 @@ languages where indexes start at 0! Sass also makes it easy to refer to the end of a string. The index -1 refers to the last character in a string, -2 refers to the second-to-last, and so on. -[string functions]: ../functions/string +[string functions]: ../modules/string -<% example do %> - @debug str-index("Helvetica Neue", "Helvetica"); // 1 - @debug str-index("Helvetica Neue", "Neue"); // 11 - @debug str-slice("Roboto Mono", -4); // "Mono" +<% example(autogen_css: false) do %> + @use "sass:string"; + + @debug string.index("Helvetica Neue", "Helvetica"); // 1 + @debug string.index("Helvetica Neue", "Neue"); // 11 + @debug string.slice("Roboto Mono", -4); // "Mono" === - @debug str-index("Helvetica Neue", "Helvetica") // 1 - @debug str-index("Helvetica Neue", "Neue") // 11 - @debug str-slice("Roboto Mono", -4) // "Mono" + @use "sass:string" + + @debug string.index("Helvetica Neue", "Helvetica") // 1 + @debug string.index("Helvetica Neue", "Neue") // 11 + @debug string.slice("Roboto Mono", -4) // "Mono" <% end %> diff --git a/source/documentation/variables.html.md.erb b/source/documentation/variables.html.md.erb index bf0e2ee91..922c1a478 100644 --- a/source/documentation/variables.html.md.erb +++ b/source/documentation/variables.html.md.erb @@ -83,61 +83,39 @@ variable, just include it in a value. Normally when you assign a value to a variable, if that variable already had a value, its old value is overwritten. But if you're writing a Sass library, you -might want to allow your users to customize your library's variables before you +might want to allow your users to configure your library's variables before you use them to generate CSS. To make this possible, Sass provides the `!default` flag. This assigns a value to a variable *only if* that variable isn't defined or its value is [`null`][]. -Otherwise, the existing value will be used. This way, users can set variables -before they import your library to customize its behavior. +Otherwise, the existing value will be used. [`null`]: values/null -<% example do %> - // _library.scss - $black: #000 !default; - $border-radius: 0.25rem !default; - $box-shadow: 0 0.5rem 1rem rgba($black, 0.15) !default; - - code { - border-radius: $border-radius; - box-shadow: $box-shadow; - } - --- - // style.scss - $black: #222; - $border-radius: 0.1rem; +### Configuring Modules - @import 'library'; - === - // _library.sass - $black: #000 !default - $border-radius: 0.25rem !default - $box-shadow: 0 0.5rem 1rem rgba($black, 0.15) !default - - code - border-radius: $border-radius - box-shadow: $box-shadow - --- - // style.sass - $black: #222 - $border-radius: 0.1rem - - @import 'library' - === - code { - border-radius: 0.1rem; - box-shadow: 0 0.5rem 1rem rgba(#222, 0.15); - } -<% end %> +<%= partial 'snippets/module-system-status' %> + +Variables defined with `!default` can be configured when loading a module with +the [`@use` rule][]. Sass libraries often use `!default` variables to allow +their users to configure the library's CSS. + +[`@use` rule]: at-rules/use + +To load a module with configuration, write `@use with (: +, : )`. The configured values will override the +variables' default values. Only variables written at the top level of the +stylesheet with a `!default` flag can be configured. + +<%= partial '../code-snippets/example-use-with' %> ## Scope Variables declared at the top level of a stylesheet are *global*. This means -that they can be accessed anywhere after they've been declared—even in another -stylesheet! But that's not true for all variables. Those declared in blocks -(curly braces in SCSS or indented code in Sass) are usually *local*, and can -only be accessed within the block they were declared. +that they can be accessed anywhere in their module after they've been declared. +But that's not true for all variables. Those declared in blocks (curly braces in +SCSS or indented code in Sass) are usually *local*, and can only be accessed +within the block they were declared. <% example do %> $global-variable: global value; @@ -291,12 +269,13 @@ assign a value to a variable, or build up a value as part of a loop. ## Advanced Variable Functions The Sass core library provides a couple advanced functions for working with -variables. The [`variable-exists()` function][] returns whether a variable with -the given name exists in the current scope, and the [`global-variable-exists()` -function][] does the same but only for the global scope. +variables. The [`meta.variable-exists()` function][] returns whether a variable +with the given name exists in the current scope, and the +[`meta.global-variable-exists()` function][] does the same but only for the +global scope. -[`variable-exists()` function]: functions/meta#variable-exists -[`global-variable-exists()` function]: functions/meta#global-variable-exists +[`meta.variable-exists()` function]: modules/meta#variable-exists +[`meta.global-variable-exists()` function]: modules/meta#global-variable-exists <% heads_up do %> Users occasionally want to use interpolation to define a variable name based @@ -308,6 +287,8 @@ function][] does the same but only for the global scope. [map]: values/maps <% example do %> + @use "sass:map"; + $theme-colors: ( "success": #28a745, "info": #17a2b8, @@ -316,13 +297,19 @@ function][] does the same but only for the global scope. .alert { // Instead of $theme-color-#{warning} - background-color: map-get($theme-colors, "warning"); + background-color: map.get($theme-colors, "warning"); } === + @use "sass:map" + $theme-colors: ("success": #28a745, "info": #17a2b8, "warning": #ffc107) .alert // Instead of $theme-color-#{warning} - background-color: map-get($theme-colors, "warning") + background-color: map.get($theme-colors, "warning") + === + .alert { + background-color: #ffc107; + } <% end %> <% end %> diff --git a/source/guide.html.haml b/source/guide.html.haml index 2eda441c3..3a5e1b86d 100644 --- a/source/guide.html.haml +++ b/source/guide.html.haml @@ -15,7 +15,7 @@ introduction: > - [Variables](#topic-2) - [Nesting](#topic-3) - [Partials](#topic-4) - - [Import](#topic-5) + - [Modules](#topic-5) - [Mixins](#topic-6) - [Inheritance](#topic-7) - [Operators](#topic-8) @@ -158,72 +158,72 @@ introduction: > Sass file named with a leading underscore. You might name it something like `_partial.scss`. The underscore lets Sass know that the file is only a partial file and that it should not be generated into a CSS file. Sass - partials are used with the `@import` directive. + partials are used with the `@use` rule. --- %section#topic-5 - :markdown - ## Import + %h2 Modules + = partial 'documentation/snippets/module-system-status' - CSS has an import option that lets you split your CSS into smaller, more - maintainable portions. The only drawback is that each time you use - `@import` in CSS it creates another HTTP request. Sass builds on top of - the current CSS `@import` but instead of requiring an HTTP request, Sass - will take the file that you want to import and combine it with the file - you're importing into so you can serve a single CSS file to the web browser. + :markdown + You don't have to write all your Sass in a single file. You can split it up + however you want with the `@use` rule. This rule loads another Sass file as + a *module*, which means you can refer to its variables, [mixins][], and + [functions][] in your Sass file with a namespace based on the filename. + Using a file will also include the CSS it generates in your compiled output! - Let's say you have a couple of Sass files, `_reset.scss` and `base.scss`. - We want to import `_reset.scss` into `base.scss`. + [mixins]: #topic-6 + [functions]: documentation/at-rules/function - example do :plain - // _reset.scss - html, - body, - ul, - ol { - margin: 0; - padding: 0; + // _base.scss + $font-stack: Helvetica, sans-serif; + $primary-color: #333; + + body { + font: 100% $font-stack; + color: $primary-color; } --- - // base.scss - @import 'reset'; - body { - font: 100% Helvetica, sans-serif; - background-color: #efefef; + // styles.scss + @use 'base'; + + .inverse { + background-color: base.$primary-color; + color: white; } === - // _reset.sass - html, - body, - ul, - ol - margin: 0 - padding: 0 - --- - // base.sass - @import reset + // _base.sass + $font-stack: Helvetica, sans-serif + $primary-color: #333 + body - font: 100% Helvetica, sans-serif - background-color: #efefef + font: 100% $font-stack + color: $primary-color + --- + // styles.sass + @use 'base' + + .inverse + background-color: base.$primary-color + color: white === - html, - body, - ul, - ol { - margin: 0; - padding: 0; - } body { font: 100% Helvetica, sans-serif; - background-color: #efefef; + color: #333; + } + + .inverse { + background-color: #333; + color: white; } :markdown - Notice we're using `@import 'reset';` in the `base.scss` file. When you - import a file you don't need to include the file extension `.scss`. Sass - is smart and will figure it out for you. + Notice we're using `@use 'reset';` in the `base.scss` file. When you use a + file you don't need to include the file extension. Sass is smart and will + figure it out for you. --- diff --git a/source/layouts/has_both_sidebars.haml b/source/layouts/has_both_sidebars.haml index 9afb64fb7..de6ef2a45 100644 --- a/source/layouts/has_both_sidebars.haml +++ b/source/layouts/has_both_sidebars.haml @@ -16,6 +16,7 @@ - container = current_page.data.no_container ? '' : 'sl-l-container sl-l-container--small' - container << ' sl-l-container--overview' if current_page.data.intro %div{class: container} + = yield_content :before_introduction - if current_page.data.introduction - center_introduction = current_page.data.center_introduction ? 'sl-c-introduction--center' : '' .sl-c-introduction{class: center_introduction} diff --git a/source/layouts/has_complementary.haml b/source/layouts/has_complementary.haml index c6250f3d1..2da3c0888 100644 --- a/source/layouts/has_complementary.haml +++ b/source/layouts/has_complementary.haml @@ -4,6 +4,7 @@ .sl-l-large-holy-grail__main - container = current_page.data.no_container ? '' : 'sl-l-container sl-l-container--small' %div{class: container} + = yield_content :before_introduction - if current_page.data.introduction - center_introduction = current_page.data.center_introduction ? 'sl-c-introduction--center' : '' .sl-c-introduction{class: center_introduction} diff --git a/source/layouts/has_navigation.haml b/source/layouts/has_navigation.haml index a2077668b..913878972 100644 --- a/source/layouts/has_navigation.haml +++ b/source/layouts/has_navigation.haml @@ -7,6 +7,7 @@ .sl-l-medium-holy-grail__main - container = current_page.data.no_container ? '' : 'sl-l-container sl-l-container--small' %div{class: container} + = yield_content :before_introduction - if current_page.data.introduction - center_introduction = current_page.data.center_introduction ? 'sl-c-introduction--center' : '' .sl-c-introduction{class: center_introduction} diff --git a/source/layouts/has_no_sidebars.haml b/source/layouts/has_no_sidebars.haml index 68c196a95..c508bd08d 100644 --- a/source/layouts/has_no_sidebars.haml +++ b/source/layouts/has_no_sidebars.haml @@ -1,6 +1,7 @@ = wrap_layout :layout do - container = current_page.data.no_container ? '' : 'sl-l-container sl-l-container--small' .docSearch-content{class: container} + = yield_content :before_introduction - if current_page.data.introduction - center_introduction = current_page.data.center_introduction ? 'sl-c-introduction--center' : '' .sl-c-introduction{class: center_introduction} diff --git a/source/layouts/layout.haml b/source/layouts/layout.haml index 9f19c685b..c9062cfa6 100644 --- a/source/layouts/layout.haml +++ b/source/layouts/layout.haml @@ -49,10 +49,10 @@ .sl-c-alert.sl-c-alert--info .sl-l-container %p - %strong Your laptop needs more Sass. - = succeed '.' do - = link_to 'http://devswag.com/products/sass-stickers-4' do - Grab a set of Sass stickers now + %strong Sass just launched a brand new module system. + = succeed '!' do + = link_to '/blog/7858341-the-module-system-is-launched' do + Learn all about it on the Sass blog .sl-c-pop-stripe