diff --git a/source/documentation/style-rules/declarations.liquid b/source/documentation/style-rules/declarations.md similarity index 53% rename from source/documentation/style-rules/declarations.liquid rename to source/documentation/style-rules/declarations.md index a348e12..497ca18 100644 --- a/source/documentation/style-rules/declarations.liquid +++ b/source/documentation/style-rules/declarations.md @@ -24,15 +24,13 @@ introduction: > border-radius: $size * 0.5 {% endcodeExample %} -{% markdown %} - ## Interpolation +## Interpolation - A property's name can include [interpolation][], which makes it possible to - dynamically generate properties as needed. You can even interpolate the entire - property name! +A property's name can include [interpolation][], which makes it possible to +dynamically generate properties as needed. You can even interpolate the entire +property name! - [interpolation]: /documentation/interpolation -{% endmarkdown %} +[interpolation]: /documentation/interpolation {% codeExample 'interpolation' %} @mixin prefix($property, $value, $prefixes) { @@ -57,15 +55,13 @@ introduction: > @include prefix(filter, grayscale(50%), moz webkit) {% endcodeExample %} -{% markdown %} - ## Nesting +## Nesting - Many CSS properties start with the same prefix that acts as a kind of - namespace. For example, `font-family`, `font-size`, and `font-weight` all - start with `font-`. Sass makes this easier and less redundant by allowing - property declarations to be nested. The outer property names are added to the - inner, separated by a hyphen. -{% endmarkdown %} +Many CSS properties start with the same prefix that acts as a kind of namespace. +For example, `font-family`, `font-size`, and `font-weight` all start with +`font-`. Sass makes this easier and less redundant by allowing property +declarations to be nested. The outer property names are added to the inner, +separated by a hyphen. {% codeExample 'nesting' %} .enlarge { @@ -90,11 +86,9 @@ introduction: > font-size: 36px {% endcodeExample %} -{% markdown %} - Some of these CSS properties have shorthand versions that use the namespace as - the property name. For these, you can write both the shorthand value *and* the - more explicit nested versions. -{% endmarkdown %} +Some of these CSS properties have shorthand versions that use the namespace as +the property name. For these, you can write both the shorthand value *and* the +more explicit nested versions. {% codeExample 'nesting-shorthand' %} .info-page { @@ -110,16 +104,14 @@ introduction: > top: 2px {% endcodeExample %} -{% markdown %} - ## Hidden Declarations +## Hidden Declarations - Sometimes you only want a property declaration to show up some of the time. If - a declaration's value is [`null`][] or an empty [unquoted string][], Sass - won't compile that declaration to CSS at all. +Sometimes you only want a property declaration to show up some of the time. If a +declaration's value is [`null`][] or an empty [unquoted string][], Sass won't +compile that declaration to CSS at all. - [`null`]: /documentation/values/null - [unquoted string]: /documentation/values/strings#unquoted -{% endmarkdown %} +[`null`]: /documentation/values/null +[unquoted string]: /documentation/values/strings#unquoted {% codeExample 'hidden-declarations' %} $rounded-corners: false; @@ -136,37 +128,34 @@ introduction: > border-radius: if($rounded-corners, 5px, null) {% endcodeExample %} -{% markdown %} - ## Custom Properties +## Custom Properties - {% compatibility 'dart: true', 'libsass: "3.5.0"', 'ruby: "3.5.0"', 'feature: "SassScript Syntax"' %} - Older versions of LibSass and Ruby Sass parsed custom property declarations - just like any other property declaration, allowing the full range of - SassScript expressions as values. Even when using these versions, it's - recommended that you use interpolation to inject SassScript values for - forwards-compatibility. +{% compatibility 'dart: true', 'libsass: "3.5.0"', 'ruby: "3.5.0"', 'feature: "SassScript Syntax"' %} + Older versions of LibSass and Ruby Sass parsed custom property declarations + just like any other property declaration, allowing the full range of + SassScript expressions as values. Even when using these versions, it's + recommended that you use interpolation to inject SassScript values for + forwards-compatibility. - See [the breaking change page][] for more details. + See [the breaking change page][] for more details. - [the breaking change page]: /documentation/breaking-changes/css-vars - {% endcompatibility %} + [the breaking change page]: /documentation/breaking-changes/css-vars +{% endcompatibility %} - [CSS custom properties][], also known as CSS variables, have an unusual - declaration syntax: they allow almost any text at all in their declaration - values. What's more, those values are accessible to JavaScript, so any value - might potentially be relevant to the user. This includes values that would - normally be parsed as SassScript. +[CSS custom properties][], also known as CSS variables, have an unusual +declaration syntax: they allow almost any text at all in their declaration +values. What's more, those values are accessible to JavaScript, so any value +might potentially be relevant to the user. This includes values that would +normally be parsed as SassScript. - [CSS Custom Properties]: https://developer.mozilla.org/en-US/docs/Web/CSS/--* +[CSS Custom Properties]: https://developer.mozilla.org/en-US/docs/Web/CSS/--* - Because of this, Sass parses custom property declarations differently than - other property declarations. All tokens, including those that look like - SassScript, are passed through to CSS as-is. The only exception is - [interpolation][], which is the only way to inject dynamic values into a - custom property. +Because of this, Sass parses custom property declarations differently than other +property declarations. All tokens, including those that look like SassScript, +are passed through to CSS as-is. The only exception is [interpolation][], which +is the only way to inject dynamic values into a custom property. - [interpolation]: /documentation/interpolation -{% endmarkdown %} +[interpolation]: /documentation/interpolation {% codeExample 'custom-properties' %} $primary: #81899b; @@ -197,16 +186,14 @@ introduction: > --consumed-by-js: $primary {% endcodeExample %} -{% headsUp false %} - {% markdown %} - 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 [`meta.inspect()` - function][] to preserve the quotes. +{% headsUp %} + 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 [`meta.inspect()` + function][] to preserve the quotes. - [interpolation]: /documentation/interpolation - [`meta.inspect()` function]: /documentation/modules/meta#inspect - {% endmarkdown %} + [interpolation]: /documentation/interpolation + [`meta.inspect()` function]: /documentation/modules/meta#inspect {% codeExample 'custom-properties-strings-meta' %} @use "sass:meta"; diff --git a/source/documentation/style-rules/index.liquid b/source/documentation/style-rules/index.md similarity index 51% rename from source/documentation/style-rules/index.liquid rename to source/documentation/style-rules/index.md index 54b8522..6ffecc0 100644 --- a/source/documentation/style-rules/index.liquid +++ b/source/documentation/style-rules/index.md @@ -23,14 +23,11 @@ introduction: > border: 1px solid #e1e4e8 {% endcodeExample %} -{% markdown %} - ## Nesting +## Nesting - But Sass wants to make your life easier. Rather than repeating the same - selectors over and over again, you can write one style rules inside another. - Sass will automatically combine the outer rule's selector with the inner - rule's. -{% endmarkdown %} +But Sass wants to make your life easier. Rather than repeating the same +selectors over and over again, you can write one style rules inside another. +Sass will automatically combine the outer rule's selector with the inner rule's. {% render 'code_snippets/example-nesting' %} @@ -41,14 +38,11 @@ introduction: > render it. Keep those selectors shallow! {% endheadsUp %} -{% markdown %} - ### Selector Lists +### Selector Lists - Nested rules are clever about handling selector lists (that is, - comma-separated selectors). Each complex selector (the ones between the - commas) is nested separately, and then they're combined back into a selector - list. -{% endmarkdown %} +Nested rules are clever about handling selector lists (that is, comma-separated +selectors). Each complex selector (the ones between the commas) is nested +separately, and then they're combined back into a selector list. {% codeExample 'selector-lists' %} .alert, .warning { @@ -66,15 +60,13 @@ introduction: > padding-bottom: 0 {% endcodeExample %} -{% markdown %} - ### Selector Combinators +### Selector Combinators - You can nest selectors that use [combinators][] as well. You can put the - combinator at the end of the outer selector, at the beginning of the inner - selector, or even all on its own in between the two. +You can nest selectors that use [combinators][] as well. You can put the +combinator at the end of the outer selector, at the beginning of the inner +selector, or even all on its own in between the two. - [combinators]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors#Combinators#Combinators -{% endmarkdown %} +[combinators]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors#Combinators#Combinators {% codeExample 'selector-combinators' %} ul > { @@ -115,27 +107,24 @@ introduction: > opacity: 0.8 {% endcodeExample %} -{% markdown %} - ### Advanced Nesting +### Advanced Nesting - If you want to do more with your nested style rules than just combine them in - order with the descendant combinator (that is, a plain space) separating them, - Sass has your back. See the [parent selector documentation][] for more - details. +If you want to do more with your nested style rules than just combine them in +order with the descendant combinator (that is, a plain space) separating them, +Sass has your back. See the [parent selector documentation][] for more details. - [parent selector documentation]: /documentation/style-rules/parent-selector +[parent selector documentation]: /documentation/style-rules/parent-selector - ## Interpolation +## Interpolation - You can use [interpolation][] to inject values from [expressions][] like - variables and function calls into your selectors. This is particularly useful - when you're writing [mixins][], since it allows you to create selectors from - parameters your users pass in. +You can use [interpolation][] to inject values from [expressions][] like +variables and function calls into your selectors. This is particularly useful +when you're writing [mixins][], since it allows you to create selectors from +parameters your users pass in. - [interpolation]: /documentation/interpolation - [expressions]: /documentation/syntax/structure#expressions - [mixins]: /documentation/at-rules/mixin -{% endmarkdown %} +[interpolation]: /documentation/interpolation +[expressions]: /documentation/syntax/structure#expressions +[mixins]: /documentation/at-rules/mixin {% codeExample 'interpolation' %} @mixin define-emoji($name, $glyph) { @@ -167,13 +156,11 @@ introduction: > worrying that it won't parse. {% endfunFact %} -{% markdown %} - You can combine interpolation with the parent selector `&`, the [`@at-root` - rule][], and [selector functions][] to wield some serious power when - dynamically generating selectors. For more information, see the [parent - selector documentation][]. +You can combine interpolation with the parent selector `&`, the [`@at-root` +rule][], and [selector functions][] to wield some serious power when dynamically +generating selectors. For more information, see the [parent selector +documentation][]. - [`@at-root` rule]: /documentation/at-rules/at-root - [selector functions]: /documentation/modules/selector - [parent selector documentation]: /documentation/style-rules/parent-selector -{% endmarkdown %} +[`@at-root` rule]: /documentation/at-rules/at-root +[selector functions]: /documentation/modules/selector +[parent selector documentation]: /documentation/style-rules/parent-selector diff --git a/source/documentation/style-rules/parent-selector.liquid b/source/documentation/style-rules/parent-selector.md similarity index 65% rename from source/documentation/style-rules/parent-selector.liquid rename to source/documentation/style-rules/parent-selector.md index 24f38bb..816900e 100644 --- a/source/documentation/style-rules/parent-selector.liquid +++ b/source/documentation/style-rules/parent-selector.md @@ -9,11 +9,9 @@ introduction: > or adding a selector *before* the parent. --- -{% markdown %} - When a parent selector is used in an inner selector, it's replaced with the - corresponding outer selector. This happens instead of the normal nesting - behavior. -{% endmarkdown %} +When a parent selector is used in an inner selector, it's replaced with the +corresponding outer selector. This happens instead of the normal nesting +behavior. {% codeExample 'parent-selector' %} .alert { @@ -66,17 +64,15 @@ introduction: > [this GitHub issue]: https://github.com/sass/sass/issues/1425 {% endheadsUp %} -{% markdown %} - ## Adding Suffixes +## Adding Suffixes - You can also use the parent selector to add extra suffixes to the outer - selector. This is particularly useful when using a methodology like [BEM][] - that uses highly structured class names. As long as the outer selector ends - with an alphanumeric name (like class, ID, and element selectors), you can use - the parent selector to append additional text. +You can also use the parent selector to add extra suffixes to the outer +selector. This is particularly useful when using a methodology like [BEM][] that +uses highly structured class names. As long as the outer selector ends with an +alphanumeric name (like class, ID, and element selectors), you can use the +parent selector to append additional text. - [BEM]: http://getbem.com/ -{% endmarkdown %} +[BEM]: http://getbem.com/ {% codeExample 'parent-selector-suffixes' %} .accordion { @@ -119,17 +115,15 @@ introduction: > display: block {% endcodeExample %} -{% markdown %} - ## In SassScript +## In SassScript - The parent selector can also be used within SassScript. It's a special - expression that returns the current parent selector in the same format used by - [selector functions][]: a comma-separated list (the selector list) that - contains space-separated lists (the complex selectors) that contain unquoted - strings (the compound selectors). +The parent selector can also be used within SassScript. It's a special +expression that returns the current parent selector in the same format used by +[selector functions][]: a comma-separated list (the selector list) that contains +space-separated lists (the complex selectors) that contain unquoted strings (the +compound selectors). - [selector functions]: /documentation/modules/selector#selector-values -{% endmarkdown %} +[selector functions]: /documentation/modules/selector#selector-values {% codeExample 'parent-selector-sassscript' %} .main aside:hover, @@ -146,27 +140,23 @@ introduction: > // (unquote(".sidebar") unquote("p"))) {% endcodeExample %} -{% markdown %} - 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 mixin is being called in a style rule or not. +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 +mixin is being called in a style rule or not. - [falsey]: /documentation/at-rules/control/if#truthiness-and-falsiness -{% endmarkdown %} +[falsey]: /documentation/at-rules/control/if#truthiness-and-falsiness {% render 'code_snippets/example-if-parent-selector' %} -{% markdown %} - ### Advanced Nesting +### Advanced Nesting - You can use `&` as a normal SassScript expression, which means you can pass it - to functions or include it in interpolation—even in other selectors! Using it - in combination with [selector functions][] and the [`@at-root` rule][] allows - you to nest selectors in very powerful ways. +You can use `&` as a normal SassScript expression, which means you can pass it +to functions or include it in interpolation—even in other selectors! Using it in +combination with [selector functions][] and the [`@at-root` rule][] allows you +to nest selectors in very powerful ways. - [selector functions]: /documentation/modules/selector#selector-values - [`@at-root` rule]: /documentation/at-rules/at-root -{% endmarkdown %} +[selector functions]: /documentation/modules/selector#selector-values +[`@at-root` rule]: /documentation/at-rules/at-root {% render 'code_snippets/example-advanced-nesting' %} diff --git a/source/documentation/style-rules/placeholder-selectors.liquid b/source/documentation/style-rules/placeholder-selectors.md similarity index 64% rename from source/documentation/style-rules/placeholder-selectors.liquid rename to source/documentation/style-rules/placeholder-selectors.md index 2e6471f..27d1688 100644 --- a/source/documentation/style-rules/placeholder-selectors.liquid +++ b/source/documentation/style-rules/placeholder-selectors.md @@ -10,14 +10,12 @@ introduction: > {% render 'code_snippets/example-placeholder' %} -{% markdown %} - What's the use of a selector that isn't emitted? It can still be [extended][]! - Unlike class selectors, placeholders don't clutter up the CSS if they aren't - extended and they don't mandate that users of a library use specific class - names for their HTML. +What's the use of a selector that isn't emitted? It can still be [extended][]! +Unlike class selectors, placeholders don't clutter up the CSS if they aren't +extended and they don't mandate that users of a library use specific class names +for their HTML. - [extended]: /documentation/at-rules/extend -{% endmarkdown %} +[extended]: /documentation/at-rules/extend {% codeExample 'extended-selector' %} %toolbelt { @@ -58,9 +56,7 @@ introduction: > color: #cddc39 {% endcodeExample %} -{% markdown %} - Placeholder selectors are useful when writing a Sass library where each style - rule may or may not be used. As a rule of thumb, if you're writing a - stylesheet just for your own app, it's often better to just extend a class - selector if one is available. -{% endmarkdown %} +Placeholder selectors are useful when writing a Sass library where each style +rule may or may not be used. As a rule of thumb, if you're writing a stylesheet +just for your own app, it's often better to just extend a class selector if one +is available. diff --git a/source/documentation/syntax/comments.liquid b/source/documentation/syntax/comments.liquid deleted file mode 100644 index c33165f..0000000 --- a/source/documentation/syntax/comments.liquid +++ /dev/null @@ -1,141 +0,0 @@ ---- -title: Comments -introduction: > - The way Sass comments work differs substantially between SCSS and the indented - syntax. Both syntaxes support two types of comments: comments defined using - `/* */` that are (usually) compiled to CSS, and comments defined using `//` - that are not. ---- - -{% markdown %} - ## In SCSS - - Comments in SCSS work similarly to comments in other languages like - JavaScript. **Single-line comments** start with `//`, and go until the end of - the line. Nothing in a single-line comment is emitted as CSS; as far as Sass - is concerned, they may as well not exist. They're also called **silent - comments**, because they don't produce any CSS. - - **Multi-line comments** start with `/*` and end at the next `*/`. If a - multi-line comment is written somewhere that a [statement][] is allowed, it's - compiled to a CSS comment. They're also called **loud comment**, by contrast - with silent comments. A multi-line comment that's compiled to CSS may contain - [interpolation][], which will be evaluated before the comment is compiled. - - By default, multi-line comments will be stripped from the compiled CSS in - [compressed mode][]. If a comment begins with `/*!`, though, it will always be - included in the CSS output. - - [statement]: /documentation/syntax/structure#statements - [interpolation]: /documentation/interpolation - [compressed mode]: /documentation/cli/dart-sass/#style -{% endmarkdown %} - -{% codeExample 'scss-comment', true, 'scss' %} - // This comment won't be included in the CSS. - - /* But this comment will, except in compressed mode. */ - - /* It can also contain interpolation: - * 1 + 1 = #{1 + 1} */ - - /*! This comment will be included even in compressed mode. */ - - p /* Multi-line comments can be written anywhere - * whitespace is allowed. */ .sans { - font: Helvetica, // So can single-line comments. - sans-serif; - } -{% endcodeExample %} - -{% markdown %} - ## In Sass - - Comments in the indented syntax work a little differently: they're - indentation-based, just like the rest of the syntax. Like SCSS, silent - comments written with `//` are never emitted as CSS, but unlike SCSS - everything indented beneath the opening `//` is also commented out. - - Indented syntax comments that start with `/*` work with indentation the same - way, except that they are compiled to CSS. Because the extent of the comment - is based on indentation, the closing `*/` is optional. Also like SCSS, `/*` - comments can contain [interpolation][] and can start with `/*!` to avoid being - stripped in compressed mode. - - Comments can also be used within [expressions][] in the indented syntax. In - this case, they have exactly the same syntax as they do in SCSS. - - [interpolation]: /documentation/interpolation - [expressions]: /documentation/syntax/structure#expressions -{% endmarkdown %} - -{% codeExample 'sass-comment', true, 'sass' %} - // This comment won't be included in the CSS. - This is also commented out. - - /* But this comment will, except in compressed mode. - - /* It can also contain interpolation: - 1 + 1 = #{1 + 1} - - /*! This comment will be included even in compressed mode. - - p .sans - font: Helvetica, /* Inline comments must be closed. */ sans-serif -{% endcodeExample %} - -{% markdown %} - ## Documentation Comments - - When writing style libraries using Sass, you can use comments to document the - [mixins][], [functions][], [variables][], and [placeholder selectors][] that - your library provides, as well as the library itself. These comments are read - by the [SassDoc][] tool, which uses them to generate beautiful documentation. - Check out [the Susy grid engine][susy]'s documentation to see it in action! - - [mixins]: /documentation/at-rules/mixin - [functions]: /documentation/at-rules/function - [variables]: /documentation/variables - [placeholder selectors]: /documentation/style-rules/placeholder-selectors - [SassDoc]: http://sassdoc.com - [susy]: http://oddbird.net/susy/docs/index.html - - Documentation comments are silent comments, written with three slashes (`///`) - directly above the thing you're documenting. SassDoc parses text in the - comments as [Markdown][], and supports many useful [annotations][] to describe - it in detail. - - [Markdown]: https://www.markdownguide.org/getting-started - [annotations]: http://sassdoc.com/annotations/ -{% endmarkdown %} - -{% codeExample 'documentation-comment' %} - /// Computes an exponent. - /// - /// @param {number} $base - /// The number to multiply by itself. - /// @param {integer (unitless)} $exponent - /// The number of `$base`s to multiply together. - /// @return {number} `$base` to the power of `$exponent`. - @function pow($base, $exponent) { - $result: 1; - @for $_ from 1 through $exponent { - $result: $result * $base; - } - @return $result; - } - === - /// Computes an exponent. - /// - /// @param {number} $base - /// The number to multiply by itself. - /// @param {integer (unitless)} $exponent - /// The number of `$base`s to multiply together. - /// @return {number} `$base` to the power of `$exponent`. - @function pow($base, $exponent) - $result: 1 - @for $_ from 1 through $exponent - $result: $result * $base - - @return $result -{% endcodeExample %} diff --git a/source/documentation/syntax/comments.md b/source/documentation/syntax/comments.md new file mode 100644 index 0000000..01c931f --- /dev/null +++ b/source/documentation/syntax/comments.md @@ -0,0 +1,135 @@ +--- +title: Comments +introduction: > + The way Sass comments work differs substantially between SCSS and the indented + syntax. Both syntaxes support two types of comments: comments defined using + `/* */` that are (usually) compiled to CSS, and comments defined using `//` + that are not. +--- + +## In SCSS + +Comments in SCSS work similarly to comments in other languages like JavaScript. +**Single-line comments** start with `//`, and go until the end of the line. +Nothing in a single-line comment is emitted as CSS; as far as Sass is concerned, +they may as well not exist. They're also called **silent comments**, because +they don't produce any CSS. + +**Multi-line comments** start with `/*` and end at the next `*/`. If a +multi-line comment is written somewhere that a [statement][] is allowed, it's +compiled to a CSS comment. They're also called **loud comment**, by contrast +with silent comments. A multi-line comment that's compiled to CSS may contain +[interpolation][], which will be evaluated before the comment is compiled. + +By default, multi-line comments will be stripped from the compiled CSS in +[compressed mode][]. If a comment begins with `/*!`, though, it will always be +included in the CSS output. + +[statement]: /documentation/syntax/structure#statements +[interpolation]: /documentation/interpolation +[compressed mode]: /documentation/cli/dart-sass/#style + +{% codeExample 'scss-comment', true, 'scss' %} + // This comment won't be included in the CSS. + + /* But this comment will, except in compressed mode. */ + + /* It can also contain interpolation: + * 1 + 1 = #{1 + 1} */ + + /*! This comment will be included even in compressed mode. */ + + p /* Multi-line comments can be written anywhere + * whitespace is allowed. */ .sans { + font: Helvetica, // So can single-line comments. + sans-serif; + } +{% endcodeExample %} + +## In Sass + +Comments in the indented syntax work a little differently: they're +indentation-based, just like the rest of the syntax. Like SCSS, silent comments +written with `//` are never emitted as CSS, but unlike SCSS everything indented +beneath the opening `//` is also commented out. + +Indented syntax comments that start with `/*` work with indentation the same +way, except that they are compiled to CSS. Because the extent of the comment is +based on indentation, the closing `*/` is optional. Also like SCSS, `/*` +comments can contain [interpolation][] and can start with `/*!` to avoid being +stripped in compressed mode. + +Comments can also be used within [expressions][] in the indented syntax. In this +case, they have exactly the same syntax as they do in SCSS. + +[interpolation]: /documentation/interpolation +[expressions]: /documentation/syntax/structure#expressions + +{% codeExample 'sass-comment', true, 'sass' %} + // This comment won't be included in the CSS. + This is also commented out. + + /* But this comment will, except in compressed mode. + + /* It can also contain interpolation: + 1 + 1 = #{1 + 1} + + /*! This comment will be included even in compressed mode. + + p .sans + font: Helvetica, /* Inline comments must be closed. */ sans-serif +{% endcodeExample %} + +## Documentation Comments + +When writing style libraries using Sass, you can use comments to document the +[mixins][], [functions][], [variables][], and [placeholder selectors][] that +your library provides, as well as the library itself. These comments are read by +the [SassDoc][] tool, which uses them to generate beautiful documentation. Check +out [the Susy grid engine][susy]'s documentation to see it in action! + +[mixins]: /documentation/at-rules/mixin +[functions]: /documentation/at-rules/function +[variables]: /documentation/variables +[placeholder selectors]: /documentation/style-rules/placeholder-selectors +[SassDoc]: http://sassdoc.com +[susy]: http://oddbird.net/susy/docs/index.html + +Documentation comments are silent comments, written with three slashes (`///`) +directly above the thing you're documenting. SassDoc parses text in the comments +as [Markdown][], and supports many useful [annotations][] to describe it in +detail. + +[Markdown]: https://www.markdownguide.org/getting-started +[annotations]: http://sassdoc.com/annotations/ + +{% codeExample 'documentation-comment' %} + /// Computes an exponent. + /// + /// @param {number} $base + /// The number to multiply by itself. + /// @param {integer (unitless)} $exponent + /// The number of `$base`s to multiply together. + /// @return {number} `$base` to the power of `$exponent`. + @function pow($base, $exponent) { + $result: 1; + @for $_ from 1 through $exponent { + $result: $result * $base; + } + @return $result; + } + === + /// Computes an exponent. + /// + /// @param {number} $base + /// The number to multiply by itself. + /// @param {integer (unitless)} $exponent + /// The number of `$base`s to multiply together. + /// @return {number} `$base` to the power of `$exponent`. + @function pow($base, $exponent) + $result: 1 + @for $_ from 1 through $exponent + $result: $result * $base + + @return $result +{% endcodeExample %} diff --git a/source/documentation/syntax/special-functions.liquid b/source/documentation/syntax/special-functions.liquid deleted file mode 100644 index e473607..0000000 --- a/source/documentation/syntax/special-functions.liquid +++ /dev/null @@ -1,148 +0,0 @@ ---- -title: Special Functions -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](/documentation/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](/documentation/syntax/structure#expressions). All special function - calls return [unquoted strings](/documentation/values/strings#unquoted). ---- - -{% markdown %} - ## `url()` - - The [`url()` function][] is commonly used in CSS, but its syntax is different - than other functions: it can take either a quoted *or* unquoted URL. Because - an unquoted URL isn't a valid SassScript expression, Sass needs special logic - to parse it. - - [`url()` function]: https://developer.mozilla.org/en-US/docs/Web/CSS/url - - If the `url()`'s argument is a valid unquoted URL, Sass parses it as-is, - although [interpolation][] may also be used to inject SassScript values. If - it's not a valid unquoted URL—for example, if it contains [variables][] or - [function calls][]—it's parsed as a normal [plain CSS function call][]. - - [interpolation]: /documentation/interpolation - [variables]: /documentation/variables - [function calls]: /documentation/at-rules/function - [plain CSS function call]: /documentation/at-rules/function/#plain-css-functions -{% endmarkdown %} - -{% codeExample 'url' %} - $roboto-font-path: "../fonts/roboto"; - - @font-face { - // This is parsed as a normal function call that takes a quoted string. - src: url("#{$roboto-font-path}/Roboto-Thin.woff2") format("woff2"); - - font-family: "Roboto"; - font-weight: 100; - } - - @font-face { - // This is parsed as a normal function call that takes an arithmetic - // expression. - src: url($roboto-font-path + "/Roboto-Light.woff2") format("woff2"); - - font-family: "Roboto"; - font-weight: 300; - } - - @font-face { - // This is parsed as an interpolated special function. - src: url(#{$roboto-font-path}/Roboto-Regular.woff2) format("woff2"); - - font-family: "Roboto"; - font-weight: 400; - } - === - $roboto-font-path: "../fonts/roboto" - - @font-face - // This is parsed as a normal function call that takes a quoted string. - src: url("#{$roboto-font-path}/Roboto-Thin.woff2") format("woff2") - - font-family: "Roboto" - font-weight: 100 - - - @font-face - // This is parsed as a normal function call that takes an arithmetic - // expression. - src: url($roboto-font-path + "/Roboto-Light.woff2") format("woff2") - - font-family: "Roboto" - font-weight: 300 - - - @font-face - // This is parsed as an interpolated special function. - src: url(#{$roboto-font-path}/Roboto-Regular.woff2) format("woff2") - - font-family: "Roboto" - font-weight: 400 -{% endcodeExample %} - -{% markdown %} - ## `element()`, `progid:...()`, and `expression()` - - {% compatibility 'dart: "<1.40.0"', 'libsass: false', 'ruby: false', 'feature: "calc()"' %} - LibSass, Ruby Sass, and versions of Dart Sass prior to 1.40.0 parse `calc()` - as special syntactic function like `element()`. - - Dart Sass versions 1.40.0 and later parse `calc()` as a [calculation]. - - [calculation]: /documentation/values/calculations - {% endcompatibility %} - - {% compatibility 'dart: ">=1.31.0 <1.40.0"', 'libsass: false', 'ruby: false', 'feature: "clamp()"' %} - LibSass, Ruby Sass, and versions of Dart Sass prior to 1.31.0 parse - `clamp()` as a [plain CSS function] rather than supporting special syntax - within it. - - [plain CSS function]: /documentation/at-rules/function/#plain-css-functions - - Dart Sass versions between 1.31.0 and 1.40.0 parse `clamp()` as special - syntactic function like `element()`. - - Dart Sass versions 1.40.0 and later parse `clamp()` as a [calculation]. - - [calculation]: /documentation/values/calculations - {% endcompatibility %} - - The [`element()`] function is defined in the CSS spec, and because its IDs - could be parsed as colors, they need special parsing. - - [`element()`]: https://developer.mozilla.org/en-US/docs/Web/CSS/element - - [`expression()`][] and functions beginning with [`progid:`][] are legacy - Internet Explorer features that use non-standard syntax. Although they're no - longer supported by recent browsers, Sass continues to parse them for - backwards compatibility. - - [`expression()`]: https://blogs.msdn.microsoft.com/ie/2008/10/16/ending-expressions/ - [`progid:`]: https://blogs.msdn.microsoft.com/ie/2009/02/19/the-css-corner-using-filters-in-ie8/ - - Sass allows *any text* in these function calls, including nested parentheses. - Nothing is interpreted as a SassScript expression, with the exception that - [interpolation][] can be used to inject dynamic values. - - [interpolation]: /documentation/interpolation -{% endmarkdown %} - -{% codeExample 'element' %} - $logo-element: logo-bg; - - .logo { - background: element(##{$logo-element}); - } - === - $logo-element: logo-bg - - .logo - background: element(##{$logo-element}) -{% endcodeExample %} diff --git a/source/documentation/syntax/special-functions.md b/source/documentation/syntax/special-functions.md new file mode 100644 index 0000000..2b594ab --- /dev/null +++ b/source/documentation/syntax/special-functions.md @@ -0,0 +1,145 @@ +--- +title: Special Functions +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](/documentation/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](/documentation/syntax/structure#expressions). All special function + calls return [unquoted strings](/documentation/values/strings#unquoted). +--- + +## `url()` + +The [`url()` function][] is commonly used in CSS, but its syntax is different +than other functions: it can take either a quoted *or* unquoted URL. Because an +unquoted URL isn't a valid SassScript expression, Sass needs special logic to +parse it. + +[`url()` function]: https://developer.mozilla.org/en-US/docs/Web/CSS/url + +If the `url()`'s argument is a valid unquoted URL, Sass parses it as-is, +although [interpolation][] may also be used to inject SassScript values. If it's +not a valid unquoted URL—for example, if it contains [variables][] or [function +calls][]—it's parsed as a normal [plain CSS function call][]. + +[interpolation]: /documentation/interpolation +[variables]: /documentation/variables +[function calls]: /documentation/at-rules/function +[plain CSS function call]: /documentation/at-rules/function/#plain-css-functions + +{% codeExample 'url' %} + $roboto-font-path: "../fonts/roboto"; + + @font-face { + // This is parsed as a normal function call that takes a quoted string. + src: url("#{$roboto-font-path}/Roboto-Thin.woff2") format("woff2"); + + font-family: "Roboto"; + font-weight: 100; + } + + @font-face { + // This is parsed as a normal function call that takes an arithmetic + // expression. + src: url($roboto-font-path + "/Roboto-Light.woff2") format("woff2"); + + font-family: "Roboto"; + font-weight: 300; + } + + @font-face { + // This is parsed as an interpolated special function. + src: url(#{$roboto-font-path}/Roboto-Regular.woff2) format("woff2"); + + font-family: "Roboto"; + font-weight: 400; + } + === + $roboto-font-path: "../fonts/roboto" + + @font-face + // This is parsed as a normal function call that takes a quoted string. + src: url("#{$roboto-font-path}/Roboto-Thin.woff2") format("woff2") + + font-family: "Roboto" + font-weight: 100 + + + @font-face + // This is parsed as a normal function call that takes an arithmetic + // expression. + src: url($roboto-font-path + "/Roboto-Light.woff2") format("woff2") + + font-family: "Roboto" + font-weight: 300 + + + @font-face + // This is parsed as an interpolated special function. + src: url(#{$roboto-font-path}/Roboto-Regular.woff2) format("woff2") + + font-family: "Roboto" + font-weight: 400 +{% endcodeExample %} + +## `element()`, `progid:...()`, and `expression()` + +{% compatibility 'dart: "<1.40.0"', 'libsass: false', 'ruby: false', 'feature: "calc()"' %} + LibSass, Ruby Sass, and versions of Dart Sass prior to 1.40.0 parse `calc()` + as special syntactic function like `element()`. + + Dart Sass versions 1.40.0 and later parse `calc()` as a [calculation]. + + [calculation]: /documentation/values/calculations +{% endcompatibility %} + +{% compatibility 'dart: ">=1.31.0 <1.40.0"', 'libsass: false', 'ruby: false', 'feature: "clamp()"' %} + LibSass, Ruby Sass, and versions of Dart Sass prior to 1.31.0 parse `clamp()` + as a [plain CSS function] rather than supporting special syntax within it. + + [plain CSS function]: /documentation/at-rules/function/#plain-css-functions + + Dart Sass versions between 1.31.0 and 1.40.0 parse `clamp()` as special + syntactic function like `element()`. + + Dart Sass versions 1.40.0 and later parse `clamp()` as a [calculation]. + + [calculation]: /documentation/values/calculations +{% endcompatibility %} + +The [`element()`] function is defined in the CSS spec, and because its IDs could +be parsed as colors, they need special parsing. + +[`element()`]: https://developer.mozilla.org/en-US/docs/Web/CSS/element + +[`expression()`][] and functions beginning with [`progid:`][] are legacy +Internet Explorer features that use non-standard syntax. Although they're no +longer supported by recent browsers, Sass continues to parse them for backwards +compatibility. + +[`expression()`]: + https://blogs.msdn.microsoft.com/ie/2008/10/16/ending-expressions/ +[`progid:`]: + https://blogs.msdn.microsoft.com/ie/2009/02/19/the-css-corner-using-filters-in-ie8/ + +Sass allows *any text* in these function calls, including nested parentheses. +Nothing is interpreted as a SassScript expression, with the exception that +[interpolation][] can be used to inject dynamic values. + +[interpolation]: /documentation/interpolation + +{% codeExample 'element' %} + $logo-element: logo-bg; + + .logo { + background: element(##{$logo-element}); + } + === + $logo-element: logo-bg + + .logo + background: element(##{$logo-element}) +{% endcodeExample %} diff --git a/source/documentation/values/booleans.liquid b/source/documentation/values/booleans.md similarity index 66% rename from source/documentation/values/booleans.liquid rename to source/documentation/values/booleans.md index 0d43651..7a35368 100644 --- a/source/documentation/values/booleans.liquid +++ b/source/documentation/values/booleans.md @@ -25,14 +25,12 @@ introduction: > @debug math.comparable(100px, 3in) // true {% endcodeExample %} -{% markdown %} - You can work with booleans using [boolean operators][]. The `and` operator - returns `true` if *both* sides are `true`, and the `or` operator returns - `true` if *either* side is `true`. The `not` operator returns the opposite of - a single boolean value. +You can work with booleans using [boolean operators][]. The `and` operator +returns `true` if *both* sides are `true`, and the `or` operator returns `true` +if *either* side is `true`. The `not` operator returns the opposite of a single +boolean value. - [boolean operators]: /documentation/operators/boolean -{% endmarkdown %} +[boolean operators]: /documentation/operators/boolean {% codeExample 'boolean-operators', false %} @debug true and true; // true @@ -54,23 +52,19 @@ introduction: > @debug not false // true {% endcodeExample %} -{% markdown %} - ## Using Booleans +## Using Booleans - You can use booleans to choose whether or not to do various things in Sass. - The [`@if` rule][] evaluates a block of styles if its argument is `true`: +You can use booleans to choose whether or not to do various things in Sass. The +[`@if` rule][] evaluates a block of styles if its argument is `true`: - [`@if` rule]: /documentation/at-rules/control/if -{% endmarkdown %} +[`@if` rule]: /documentation/at-rules/control/if {% render 'code_snippets/example-if' %} -{% markdown %} - The [`if()` function][] returns one value if its argument is `true` and - another if its argument is `false`: +The [`if()` function][] returns one value if its argument is `true` and another +if its argument is `false`: - [`if()` function]: /documentation/modules#if -{% endmarkdown %} +[`if()` function]: /documentation/modules#if {% codeExample 'if-function', false %} @debug if(true, 10px, 30px); // 10px diff --git a/source/documentation/values/calculations.liquid b/source/documentation/values/calculations.liquid deleted file mode 100644 index 00d705a..0000000 --- a/source/documentation/values/calculations.liquid +++ /dev/null @@ -1,253 +0,0 @@ ---- -title: Calculations -introduction: > - Calculations are how Sass represents the `calc()` function, as well as similar - functions like `clamp()`, `min()`, and `max()`. Sass will simplify these as - much as possible, even if they're combined with one another. ---- - -{% compatibility 'dart: "1.40.0"', 'libsass: false', 'ruby: false' %} - LibSass, Ruby Sass, and versions of Dart Sass prior to 1.40.0 parse `calc()` - as a [special function] like `element()`. - - [special function]: /documentation/syntax/special-functions#element-progid-and-expression - - LibSass, Ruby Sass, and versions of Dart Sass prior to 1.31.0 parse `clamp()` - as a [plain CSS function] rather than supporting special syntax within it. - Versions of Dart Sass between 1.31.0 and 1.40.0 parse `clamp()` as a [special - function] like `element()`. - - [plain CSS function]: /documentation/at-rules/function/#plain-css-functions -{% endcompatibility %} - -{% codeExample 'calculations', false %} - @debug calc(400px + 10%); // calc(400px + 10%) - @debug calc(400px / 2); // 200px - @debug min(100px, calc(1rem + 10%)); // min(100px, 1rem + 10%) - === - @debug calc(400px + 10%) // calc(400px + 10%) - @debug calc(400px / 2) // 200px - @debug min(100px, calc(1rem + 10%) ; // min(100px, 1rem + 10%) -{% endcodeExample %} - -{% markdown %} - Calculations use a special syntax that's different from normal SassScript. - It's the same syntax as the CSS `calc()`, but with the additional ability to - use [Sass variables] and call [Sass functions]. This means that `/` is always - a division operator within a calculation! - - [Sass variables]: /documentation/variables - [Sass functions]: /documentation/modules - - {% funFact %} - The arguments to a Sass function call use the normal Sass syntax, rather - than the special calculation syntax! - {% endfunFact %} - - You can also use [interpolation] in a calculation. However, if you do, nothing - in the parentheses that surround that interpolation will be simplified or - type-checked, so it's easy to end up with extra verbose or even invalid CSS. - Rather than writing `calc(10px + #{$var})`, just write `calc(10px + $var)`! - - [interpolation]: /documentation/interpolation - - ## Simplification - - Sass will simplify adjacent operations in calculations if they use units that - can be combined at compile-time, such as `1in + 10px` or `5s * 2`. If - possible, it'll even simplify the whole calculation to a single number—for - example, `clamp(0px, 30px, 20px)` will return `20px`. - - {% headsUp %} - This means that a calculation expression won't necessarily always return a - calculation! If you're writing a Sass library, you can always use the - [`meta.type-of()`] function to determine what type you're dealing with. - - [`meta.type-of()`]: /documentation/modules/meta#type-of - {% endheadsUp %} - - Calculations will also be simplified within other calculations. In particular, - if a `calc()` end up inside any other calculation, the function call will be - removed and it'll be replaced by a plain old operation. -{% endmarkdown %} - -{% codeExample 'simplification' %} - $width: calc(400px + 10%); - - .sidebar { - width: $width; - padding-left: calc($width / 4); - } - === - $width: calc(400px + 10%) - - .sidebar - width: $width - padding-left: calc($width / 4) -{% endcodeExample %} - -{% markdown %} - ## Operations - - You can't use calculations with normal SassScript operations like `+` and `*`. - If you want to write some math functions that allow calculations just write - them within their own `calc()` expressions—if they're passed a bunch of - numbers with compatible units, they'll return plain numbers as well, and if - they're passed calculations they'll return calculations. - - This restriction is in place to make sure that if calculations *aren't* - wanted, they throw an error as soon as possible. Calculations can't be used - everywhere plain numbers can: they can't be injected into CSS identifiers - (such as `.item-#{$n}`), for example, and they can't be passed to Sass's - built-in [math functions]. Reserving SassScript operations for plain numbers - makes it clear exactly where calculations are allowed and where they aren't. - - [math functions]: /documentation/modules/math -{% endmarkdown %} - -{% codeExample 'calc-operations', false %} - $width: calc(100% + 10px); - @debug $width * 2; // Error! - @debug calc($width * 2); // calc((100% + 10px) * 2); - === - $width: calc(100% + 10px); - @debug $width * 2; // Error! - @debug calc($width * 2); // calc((100% + 10px) * 2); -{% endcodeExample %} - -{% markdown %} - ## Constants - - {% compatibility 'dart: "1.60.0"','libsass: false', 'ruby: false' %}{% endcompatibility %} - - Calculations can also contain constants, which are written as CSS identifiers. - For forwards-compatibility with future CSS specs, *all* identifiers are - allowed, and by default they're just treated as unquoted strings that are - passed-through as-is. -{% endmarkdown %} - -{% codeExample 'calc-constants', false %} - @debug calc(h + 30deg); // calc(h + 30deg); - === - @debug calc(h + 30deg) // calc(h + 30deg); -{% endcodeExample %} - -{% markdown %} - Sass automatically resolves a few special constant names that are specified in - CSS to unitless numbers: - - * `pi` is a shorthand for the [mathematical constant *π*]. - - [mathematical constant *π*]: https://en.wikipedia.org/wiki/Pi - - * `e` is a shorthand for the [mathematical constant *e*]. - - [mathematical constant *e*]: https://en.wikipedia.org/wiki/E_(mathematical_constant) - - * `infinity`, `-infinity`, and `NaN` represent the corresponding - floating-point values. -{% endmarkdown %} - -{% codeExample 'unitless-numbers', false %} - @use 'sass:math'; - - @debug calc(pi); // 3.1415926536 - @debug calc(e); // 2.7182818285 - @debug calc(infinity) > math.$max-number; // true - @debug calc(-infinity) < math.$min-number; // true - === - @use 'sass:math' - - @debug calc(pi) // 3.1415926536 - @debug calc(e) // 2.7182818285 - @debug calc(infinity) > math.$max-number // true - @debug calc(-infinity) < math.$min-number // true -{% endcodeExample %} - -{% markdown %} - ## `min()` and `max()` - - {% compatibility 'dart: ">=1.11.0 <1.42.0"', 'libsass: false', 'ruby: false', 'feature: "Special function syntax"' %} - LibSass, Ruby Sass, and versions of Dart Sass prior to 1.11.0 *always* parse - `min()` and `max()` as Sass functions. To create a plain CSS `min()` or - `max()` call for those implementations, you can write something like - `unquote("min(#{$padding}, env(safe-area-inset-left))")` instead. - - Versions of Dart Sass between 1.11.0 and 1.40.0, and between 1.40.1 and - 1.42.0 parse `min()` and `max()` functions as [special functions] if they're - valid plain CSS, but parse them as Sass functions if they contain Sass - features other than interpolation, like variables or function calls. - - Dart Sass 1.41.0 parses `min()` and `max()` functions as calculations, but - doesn't allow unitless numbers to be combined with numbers with units. This - was backwards-incompatible with the global `min()` and `max()` functions, so - that behavior was reverted. - - [special functions]: /documentation/syntax/special-functions - {% endcompatibility %} - - CSS added support for [`min()` and `max()` functions] in Values and Units - Level 4, from where they were quickly adopted by Safari [to support the - iPhoneX]. But Sass supported its own [`min()`] and [`max()`] functions long - before this, and it needed to be backwards-compatible with all those existing - stylesheets. This led to the need for extra-special syntactic 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()`]: /documentation/modules/math#min - [`max()`]: /documentation/modules/math#max - - If a `min()` or `max()` function call is a valid calculation expression, it - will be parsed as a calculation. But as soon as any part of the call contains - a SassScript feature that isn't supported in a calculation, like the [modulo - operator], it's parsed as a call to Sass's core `min()` or `max()` function - instead. - - Since calculations are simplified to numbers when possible anyway, the only - substantive difference is that the Sass functions only support units that can - be combined at build time, so `min(12px % 10, 10%)` will throw an error. - - [modulo operator]: /documentation/operators/numeric -{% endmarkdown %} - -{% headsUp %} - Other calculations don't allow unitless numbers to be added to, subtracted - from, or compared to numbers with units. `min()` and `max()` are different, - though: for backwards-compatibility with the global Sass `min()` and `max()` - functions which allow unit/unitless mixing for historical reasons, these units - can be mixed as long as they're contained directly within a `min()` or `max()` - calculation. -{% endheadsUp %} - -{% codeExample 'min-max' %} - $padding: 12px; - - .post { - // Since these max() calls are valid calculation expressions, they're - // parsed as calculations. - padding-left: max($padding, env(safe-area-inset-left)); - padding-right: max($padding, env(safe-area-inset-right)); - } - - .sidebar { - // Since these use the SassScript-only modulo operator, they're parsed as - // SassScript function calls. - padding-left: max($padding % 10, 20px); - padding-right: max($padding % 10, 20px); - } - === - $padding: 12px - - .post - // Since these max() calls are valid calculation expressions, they're - // parsed as calculations. - padding-left: max($padding, env(safe-area-inset-left)) - padding-right: max($padding, env(safe-area-inset-right)) - - - .sidebar - // Since these use the SassScript-only modulo operator, they're parsed as - // SassScript function calls. - padding-left: max($padding % 10, 20px) - padding-right: max($padding % 10, 20px) -{% endcodeExample %} diff --git a/source/documentation/values/calculations.md b/source/documentation/values/calculations.md new file mode 100644 index 0000000..af477d8 --- /dev/null +++ b/source/documentation/values/calculations.md @@ -0,0 +1,243 @@ +--- +title: Calculations +introduction: > + Calculations are how Sass represents the `calc()` function, as well as similar + functions like `clamp()`, `min()`, and `max()`. Sass will simplify these as + much as possible, even if they're combined with one another. +--- + +{% compatibility 'dart: "1.40.0"', 'libsass: false', 'ruby: false' %} + LibSass, Ruby Sass, and versions of Dart Sass prior to 1.40.0 parse `calc()` + as a [special function] like `element()`. + + [special function]: /documentation/syntax/special-functions#element-progid-and-expression + + LibSass, Ruby Sass, and versions of Dart Sass prior to 1.31.0 parse `clamp()` + as a [plain CSS function] rather than supporting special syntax within it. + Versions of Dart Sass between 1.31.0 and 1.40.0 parse `clamp()` as a [special + function] like `element()`. + + [plain CSS function]: /documentation/at-rules/function/#plain-css-functions +{% endcompatibility %} + +{% codeExample 'calculations', false %} + @debug calc(400px + 10%); // calc(400px + 10%) + @debug calc(400px / 2); // 200px + @debug min(100px, calc(1rem + 10%)); // min(100px, 1rem + 10%) + === + @debug calc(400px + 10%) // calc(400px + 10%) + @debug calc(400px / 2) // 200px + @debug min(100px, calc(1rem + 10%) ; // min(100px, 1rem + 10%) +{% endcodeExample %} + +Calculations use a special syntax that's different from normal SassScript. It's +the same syntax as the CSS `calc()`, but with the additional ability to use +[Sass variables] and call [Sass functions]. This means that `/` is always a +division operator within a calculation! + +[Sass variables]: /documentation/variables +[Sass functions]: /documentation/modules + +{% funFact %} + The arguments to a Sass function call use the normal Sass syntax, rather than + the special calculation syntax! +{% endfunFact %} + +You can also use [interpolation] in a calculation. However, if you do, nothing +in the parentheses that surround that interpolation will be simplified or +type-checked, so it's easy to end up with extra verbose or even invalid CSS. +Rather than writing `calc(10px + #{$var})`, just write `calc(10px + $var)`! + +[interpolation]: /documentation/interpolation + +## Simplification + +Sass will simplify adjacent operations in calculations if they use units that +can be combined at compile-time, such as `1in + 10px` or `5s * 2`. If possible, +it'll even simplify the whole calculation to a single number—for example, +`clamp(0px, 30px, 20px)` will return `20px`. + +{% headsUp %} + This means that a calculation expression won't necessarily always return a + calculation! If you're writing a Sass library, you can always use the + [`meta.type-of()`] function to determine what type you're dealing with. + + [`meta.type-of()`]: /documentation/modules/meta#type-of +{% endheadsUp %} + +Calculations will also be simplified within other calculations. In particular, +if a `calc()` end up inside any other calculation, the function call will be +removed and it'll be replaced by a plain old operation. + +{% codeExample 'simplification' %} + $width: calc(400px + 10%); + + .sidebar { + width: $width; + padding-left: calc($width / 4); + } + === + $width: calc(400px + 10%) + + .sidebar + width: $width + padding-left: calc($width / 4) +{% endcodeExample %} + +## Operations + +You can't use calculations with normal SassScript operations like `+` and `*`. +If you want to write some math functions that allow calculations just write them +within their own `calc()` expressions—if they're passed a bunch of numbers with +compatible units, they'll return plain numbers as well, and if they're passed +calculations they'll return calculations. + +This restriction is in place to make sure that if calculations *aren't* wanted, +they throw an error as soon as possible. Calculations can't be used everywhere +plain numbers can: they can't be injected into CSS identifiers (such as +`.item-#{$n}`), for example, and they can't be passed to Sass's built-in [math +functions]. Reserving SassScript operations for plain numbers makes it clear +exactly where calculations are allowed and where they aren't. + +[math functions]: /documentation/modules/math + +{% codeExample 'calc-operations', false %} + $width: calc(100% + 10px); + @debug $width * 2; // Error! + @debug calc($width * 2); // calc((100% + 10px) * 2); + === + $width: calc(100% + 10px); + @debug $width * 2; // Error! + @debug calc($width * 2); // calc((100% + 10px) * 2); +{% endcodeExample %} + +## Constants + +{% compatibility 'dart: "1.60.0"','libsass: false', 'ruby: false' %}{% endcompatibility %} + +Calculations can also contain constants, which are written as CSS identifiers. +For forwards-compatibility with future CSS specs, *all* identifiers are allowed, +and by default they're just treated as unquoted strings that are passed-through +as-is. + +{% codeExample 'calc-constants', false %} + @debug calc(h + 30deg); // calc(h + 30deg); + === + @debug calc(h + 30deg) // calc(h + 30deg); +{% endcodeExample %} + +Sass automatically resolves a few special constant names that are specified in +CSS to unitless numbers: + +* `pi` is a shorthand for the [mathematical constant *π*]. + + [mathematical constant *π*]: https://en.wikipedia.org/wiki/Pi + +* `e` is a shorthand for the [mathematical constant *e*]. + + [mathematical constant *e*]: https://en.wikipedia.org/wiki/E_(mathematical_constant) + +* `infinity`, `-infinity`, and `NaN` represent the corresponding floating-point + values. + +{% codeExample 'unitless-numbers', false %} + @use 'sass:math'; + + @debug calc(pi); // 3.1415926536 + @debug calc(e); // 2.7182818285 + @debug calc(infinity) > math.$max-number; // true + @debug calc(-infinity) < math.$min-number; // true + === + @use 'sass:math' + + @debug calc(pi) // 3.1415926536 + @debug calc(e) // 2.7182818285 + @debug calc(infinity) > math.$max-number // true + @debug calc(-infinity) < math.$min-number // true +{% endcodeExample %} + +## `min()` and `max()` + +{% compatibility 'dart: ">=1.11.0 <1.42.0"', 'libsass: false', 'ruby: false', 'feature: "Special function syntax"' %} + LibSass, Ruby Sass, and versions of Dart Sass prior to 1.11.0 *always* parse + `min()` and `max()` as Sass functions. To create a plain CSS `min()` or + `max()` call for those implementations, you can write something like + `unquote("min(#{$padding}, env(safe-area-inset-left))")` instead. + + Versions of Dart Sass between 1.11.0 and 1.40.0, and between 1.40.1 and 1.42.0 + parse `min()` and `max()` functions as [special functions] if they're valid + plain CSS, but parse them as Sass functions if they contain Sass features + other than interpolation, like variables or function calls. + + Dart Sass 1.41.0 parses `min()` and `max()` functions as calculations, but + doesn't allow unitless numbers to be combined with numbers with units. This + was backwards-incompatible with the global `min()` and `max()` functions, so + that behavior was reverted. + + [special functions]: /documentation/syntax/special-functions +{% endcompatibility %} + +CSS added support for [`min()` and `max()` functions] in Values and Units Level +4, from where they were quickly adopted by Safari [to support the iPhoneX]. But +Sass supported its own [`min()`] and [`max()`] functions long before this, and +it needed to be backwards-compatible with all those existing stylesheets. This +led to the need for extra-special syntactic 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()`]: /documentation/modules/math#min +[`max()`]: /documentation/modules/math#max + +If a `min()` or `max()` function call is a valid calculation expression, it will +be parsed as a calculation. But as soon as any part of the call contains a +SassScript feature that isn't supported in a calculation, like the [modulo +operator], it's parsed as a call to Sass's core `min()` or `max()` function +instead. + +Since calculations are simplified to numbers when possible anyway, the only +substantive difference is that the Sass functions only support units that can be +combined at build time, so `min(12px % 10, 10%)` will throw an error. + +[modulo operator]: /documentation/operators/numeric + +{% headsUp %} + Other calculations don't allow unitless numbers to be added to, subtracted + from, or compared to numbers with units. `min()` and `max()` are different, + though: for backwards-compatibility with the global Sass `min()` and `max()` + functions which allow unit/unitless mixing for historical reasons, these units + can be mixed as long as they're contained directly within a `min()` or `max()` + calculation. +{% endheadsUp %} + +{% codeExample 'min-max' %} + $padding: 12px; + + .post { + // Since these max() calls are valid calculation expressions, they're + // parsed as calculations. + padding-left: max($padding, env(safe-area-inset-left)); + padding-right: max($padding, env(safe-area-inset-right)); + } + + .sidebar { + // Since these use the SassScript-only modulo operator, they're parsed as + // SassScript function calls. + padding-left: max($padding % 10, 20px); + padding-right: max($padding % 10, 20px); + } + === + $padding: 12px + + .post + // Since these max() calls are valid calculation expressions, they're + // parsed as calculations. + padding-left: max($padding, env(safe-area-inset-left)) + padding-right: max($padding, env(safe-area-inset-right)) + + + .sidebar + // Since these use the SassScript-only modulo operator, they're parsed as + // SassScript function calls. + padding-left: max($padding % 10, 20px) + padding-right: max($padding % 10, 20px) +{% endcodeExample %} diff --git a/source/documentation/values/colors.liquid b/source/documentation/values/colors.liquid deleted file mode 100644 index c54ea5f..0000000 --- a/source/documentation/values/colors.liquid +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: Colors ---- - -{% compatibility 'dart: "1.14.0"', 'libsass: "3.6.0"', 'ruby: "3.6.0"', 'feature: "Level 4 Syntax"' %} - LibSass and older versions of Dart or Ruby Sass don't support [hex colors with - an alpha channel][]. - - [hex colors with an alpha channel]: https://drafts.csswg.org/css-color/#hex-notation -{% endcompatibility %} - -{% markdown %} - Sass has built-in support for color values. Just like CSS colors, they - represent points in the [sRGB color space][], although many Sass [color - functions][] operate using [HSL coordinates][] (which are just another way of - expressing sRGB colors). Sass colors can be written as hex codes (`#f2ece4` or - `#b37399aa`), [CSS color names][] (`midnightblue`, `transparent`), or the - functions [`rgb()`][], [`rgba()`][], [`hsl()`][], and [`hsla()`][]. - - [sRGB color space]: https://en.wikipedia.org/wiki/SRGB - [color functions]: /documentation/modules/color - [HSL coordinates]: 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()`]: /documentation/modules#rgb - [`rgba()`]: /documentation/modules#rgba - [`hsl()`]: /documentation/modules#hsl - [`hsla()`]: /documentation/modules#hsla -{% endmarkdown %} - -{% codeExample 'colors', false %} - @debug #f2ece4; // #f2ece4 - @debug #b37399aa; // rgba(179, 115, 153, 67%) - @debug midnightblue; // #191970 - @debug rgb(204, 102, 153); // #c69 - @debug rgba(107, 113, 127, 0.8); // rgba(107, 113, 127, 0.8) - @debug hsl(228, 7%, 86%); // #dadbdf - @debug hsla(20, 20%, 85%, 0.7); // rgb(225, 215, 210, 0.7) - === - @debug #f2ece4 // #f2ece4 - @debug #b37399aa // rgba(179, 115, 153, 67%) - @debug midnightblue // #191970 - @debug rgb(204, 102, 153) // #c69 - @debug rgba(107, 113, 127, 0.8) // rgba(107, 113, 127, 0.8) - @debug hsl(228, 7%, 86%) // #dadbdf - @debug hsla(20, 20%, 85%, 0.7) // rgb(225, 215, 210, 0.7) -{% endcodeExample %} - -{% funFact %} - No matter how a Sass color is originally written, it can be used with both - HSL-based and RGB-based functions! -{% endfunFact %} - -{% markdown %} - CSS supports many different formats that can all represent the same color: its - name, its hex code, and [functional notation][]. Which format Sass chooses to - compile a color to depends on the color itself, how it was written in the - original stylesheet, and the current output mode. Because it can vary so much, - stylesheet authors shouldn't rely on any particular output format for colors - they write. - - [functional notation]: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value - - 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]: /documentation/modules/color#mix - [scaling their hue, saturation, or lightness]: /documentation/modules/color#scale -{% endmarkdown %} - -{% codeExample 'color-formats', false %} - $venus: #998099; - - @debug scale-color($venus, $lightness: +15%); // #a893a8 - @debug mix($venus, midnightblue); // #594d85 - === - $venus: #998099 - - @debug scale-color($venus, $lightness: +15%) // #a893a8 - @debug mix($venus, midnightblue) // #594d85 -{% endcodeExample %} diff --git a/source/documentation/values/colors.md b/source/documentation/values/colors.md new file mode 100644 index 0000000..0309d10 --- /dev/null +++ b/source/documentation/values/colors.md @@ -0,0 +1,77 @@ +--- +title: Colors +--- + +{% compatibility 'dart: "1.14.0"', 'libsass: "3.6.0"', 'ruby: "3.6.0"', 'feature: "Level 4 Syntax"' %} + LibSass and older versions of Dart or Ruby Sass don't support [hex colors with + an alpha channel][]. + + [hex colors with an alpha channel]: https://drafts.csswg.org/css-color/#hex-notation +{% endcompatibility %} + +Sass has built-in support for color values. Just like CSS colors, they represent +points in the [sRGB color space][], although many Sass [color functions][] +operate using [HSL coordinates][] (which are just another way of expressing sRGB +colors). Sass colors can be written as hex codes (`#f2ece4` or `#b37399aa`), +[CSS color names][] (`midnightblue`, `transparent`), or the functions +[`rgb()`][], [`rgba()`][], [`hsl()`][], and [`hsla()`][]. + +[sRGB color space]: https://en.wikipedia.org/wiki/SRGB +[color functions]: /documentation/modules/color +[HSL coordinates]: 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()`]: /documentation/modules#rgb +[`rgba()`]: /documentation/modules#rgba +[`hsl()`]: /documentation/modules#hsl +[`hsla()`]: /documentation/modules#hsla + +{% codeExample 'colors', false %} + @debug #f2ece4; // #f2ece4 + @debug #b37399aa; // rgba(179, 115, 153, 67%) + @debug midnightblue; // #191970 + @debug rgb(204, 102, 153); // #c69 + @debug rgba(107, 113, 127, 0.8); // rgba(107, 113, 127, 0.8) + @debug hsl(228, 7%, 86%); // #dadbdf + @debug hsla(20, 20%, 85%, 0.7); // rgb(225, 215, 210, 0.7) + === + @debug #f2ece4 // #f2ece4 + @debug #b37399aa // rgba(179, 115, 153, 67%) + @debug midnightblue // #191970 + @debug rgb(204, 102, 153) // #c69 + @debug rgba(107, 113, 127, 0.8) // rgba(107, 113, 127, 0.8) + @debug hsl(228, 7%, 86%) // #dadbdf + @debug hsla(20, 20%, 85%, 0.7) // rgb(225, 215, 210, 0.7) +{% endcodeExample %} + +{% funFact %} + No matter how a Sass color is originally written, it can be used with both + HSL-based and RGB-based functions! +{% endfunFact %} + +CSS supports many different formats that can all represent the same color: its +name, its hex code, and [functional notation][]. Which format Sass chooses to +compile a color to depends on the color itself, how it was written in the +original stylesheet, and the current output mode. Because it can vary so much, +stylesheet authors shouldn't rely on any particular output format for colors +they write. + +[functional notation]: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value + +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]: /documentation/modules/color#mix +[scaling their hue, saturation, or lightness]: /documentation/modules/color#scale + +{% codeExample 'color-formats', false %} + $venus: #998099; + + @debug scale-color($venus, $lightness: +15%); // #a893a8 + @debug mix($venus, midnightblue); // #594d85 + === + $venus: #998099 + + @debug scale-color($venus, $lightness: +15%) // #a893a8 + @debug mix($venus, midnightblue) // #594d85 +{% endcodeExample %} diff --git a/source/documentation/values/functions.liquid b/source/documentation/values/functions.liquid deleted file mode 100644 index 03e4aa1..0000000 --- a/source/documentation/values/functions.liquid +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: Functions ---- - -{% render 'doc_snippets/call-impl-status' %} - -{% markdown %} - [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 [`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]: /documentation/at-rules/function - [`meta.get-function()` function]: /documentation/modules/meta#get-function - [`meta.call()` function]: /documentation/modules/meta#call -{% endmarkdown %} - -{% render 'code_snippets/example-first-class-function' %} diff --git a/source/documentation/values/functions.md b/source/documentation/values/functions.md new file mode 100644 index 0000000..6ff187f --- /dev/null +++ b/source/documentation/values/functions.md @@ -0,0 +1,17 @@ +--- +title: Functions +--- + +{% render 'doc_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 [`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]: /documentation/at-rules/function +[`meta.get-function()` function]: /documentation/modules/meta#get-function +[`meta.call()` function]: /documentation/modules/meta#call + +{% render 'code_snippets/example-first-class-function' %} diff --git a/source/documentation/values/lists.liquid b/source/documentation/values/lists.liquid deleted file mode 100644 index 7011f81..0000000 --- a/source/documentation/values/lists.liquid +++ /dev/null @@ -1,222 +0,0 @@ ---- -title: Lists -table_of_contents: true ---- - -{% compatibility 'dart: true', 'libsass: "3.5.0"', 'ruby: "3.5.0"', 'feature: "Square Brackets"' %} - Older implementations of LibSass and Ruby Sass didn't support lists with - square brackets. -{% endcompatibility %} - -{% markdown %} - Lists contain a sequence of other values. In Sass, elements in lists can be - separated by commas (`Helvetica, Arial, sans-serif`), spaces (`10px 15px 0 - 0`), or [slashes] as long as it's consistent within the list. Unlike most - other languages, lists in Sass don't require special brackets; any - [expressions] separated with spaces or commas count as a list. However, you're - allowed to write lists with square brackets (`[line1 line2]`), which is useful - when using [`grid-template-columns`]. - - [slashes]: #slash-separated-lists - [expressions]: /documentation/syntax/structure#expressions - [`grid-template-columns`]: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns - - Sass lists can contain one or even zero elements. A single-element list can be - written either `(,)` or `[]`, and a zero-element list - 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]: /documentation/modules/list - - {% headsUp %} - Empty lists without brackets aren't valid CSS, so Sass won't let you use one - in a property value. - {% endheadsUp %} - - ## Slash-Separated Lists - - Lists in Sass can be separated by slashes, to represent values like the `font: - 12px/30px` shorthand for setting `font-size` and `line-height` or the `hsl(80 - 100% 50% / 0.5)` syntax for creating a color with a given opacity value. - However, **slash-separated lists can't currently be written literally.** Sass - historically used the `/` character to indicate division, so while existing - stylesheets transition to using [`math.div()`] slash-separated lists can only - be written using [`list.slash()`]. - - [`math.div()`]: /documentation/modules/math#div - [`list.slash()`]: /documentation/modules/list#slash - - For more details, see [Breaking Change: Slash as Division]. - - [Breaking Change: Slash as Division]: /documentation/breaking-changes/slash-div - - ## Using Lists - - 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]: /documentation/modules/list - - ### Indexes - - Many of these functions take or return numbers, called *indexes*, that refer - to the elements in a list. The index 1 indicates the first element of the - list. Note that this is different than many programming languages where - indexes start at 0! Sass also makes it easy to refer to the end of a list. The - index -1 refers 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 - [`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. - - [`list.nth($list, $n)` function]: /documentation/modules/list#nth -{% endmarkdown %} - -{% render 'code_snippets/example-list-nth' %} - -{% markdown %} - ### Do Something for Every Element - - This doesn't actually use a function, but it's still one of the most common - ways to use lists. The [`@each` rule][] evaluates a block of styles for each - element in a list, and assigns that element to a variable. - - [`@each` rule]: /documentation/at-rules/control/each -{% endmarkdown %} - -{% render 'code_snippets/example-each-list' %} - -{% markdown %} - ### Add to a List - - 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. - - [`list.append($list, $val)` function]: /documentation/modules/list#append - [immutable]: #immutability -{% endmarkdown %} - -{% codeExample 'lists', false %} - @debug append(10px 12px 16px, 25px); // 10px 12px 16px 25px - @debug append([col1-line1], col1-line2); // [col1-line1, col1-line2] - === - @debug append(10px 12px 16px, 25px) // 10px 12px 16px 25px - @debug append([col1-line1], col1-line2) // [col1-line1, col1-line2] -{% endcodeExample %} - -{% markdown %} - ### 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 [`list.index($list, $value)` function][]. This takes a list and a - value to locate in that list, and returns the index of that value. - - [`list.index($list, $value)` function]: /documentation/modules/list#index -{% endmarkdown %} - -{% render 'code_snippets/example-list-index' %} - -{% markdown %} - 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`]: /documentation/values/null - [falsey]: /documentation/at-rules/control/if#truthiness-and-falsiness - [`@if`]: /documentation/at-rules/control/if - [`if()`]: /documentation/modules#if -{% endmarkdown %} - -{% codeExample 'list-index', false %} - @use "sass:list"; - - $valid-sides: top, bottom, left, right; - - @mixin attach($side) { - @if not list.index($valid-sides, $side) { - @error "#{$side} is not a valid side. Expected one of #{$valid-sides}."; - } - - // ... - } - === - @use "sass:list" - - $valid-sides: top, bottom, left, right - - @mixin attach($side) - @if not list.index($valid-sides, $side) - @error "#{$side} is not a valid side. Expected one of #{$valid-sides}." - - - // ... -{% endcodeExample %} - -{% markdown %} - ## Immutability - - Lists in Sass are *immutable*, which means that the contents of a list value - never changes. Sass's list functions all return new lists rather than - modifying the originals. Immutability helps avoid lots of sneaky bugs that can - creep in when the same list is shared across different parts of the - stylesheet. - - 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. -{% endmarkdown %} - -{% codeExample 'immutability', false %} - @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: 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: list.append($prefixes, map.get($prefixes-by-browser, $browser)) - - @return $prefixes - - - @debug prefixes-for-browsers("firefox" "ie") // moz ms -{% endcodeExample %} - -{% markdown %} - ## Argument Lists - - 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 [`meta.keywords()` function][]. - - [arbitrary arguments]: /documentation/at-rules/mixin#taking-arbitrary-arguments - [`meta.keywords()` function]: /documentation/modules/meta#keywords -{% endmarkdown %} - -{% render 'code_snippets/example-mixin-arbitrary-keyword-arguments' %} diff --git a/source/documentation/values/lists.md b/source/documentation/values/lists.md new file mode 100644 index 0000000..20de004 --- /dev/null +++ b/source/documentation/values/lists.md @@ -0,0 +1,206 @@ +--- +title: Lists +table_of_contents: true +--- + +{% compatibility 'dart: true', 'libsass: "3.5.0"', 'ruby: "3.5.0"', 'feature: "Square Brackets"' %} + Older implementations of LibSass and Ruby Sass didn't support lists with + square brackets. +{% endcompatibility %} + +Lists contain a sequence of other values. In Sass, elements in lists can be +separated by commas (`Helvetica, Arial, sans-serif`), spaces (`10px 15px 0 0`), +or [slashes] as long as it's consistent within the list. Unlike most other +languages, lists in Sass don't require special brackets; any [expressions] +separated with spaces or commas count as a list. However, you're allowed to +write lists with square brackets (`[line1 line2]`), which is useful when using +[`grid-template-columns`]. + +[slashes]: #slash-separated-lists +[expressions]: /documentation/syntax/structure#expressions +[`grid-template-columns`]: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns + +Sass lists can contain one or even zero elements. A single-element list can be +written either `(,)` or `[]`, and a zero-element list +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]: /documentation/modules/list + +{% headsUp %} + Empty lists without brackets aren't valid CSS, so Sass won't let you use one + in a property value. +{% endheadsUp %} + +## Slash-Separated Lists + +Lists in Sass can be separated by slashes, to represent values like the `font: +12px/30px` shorthand for setting `font-size` and `line-height` or the `hsl(80 +100% 50% / 0.5)` syntax for creating a color with a given opacity value. +However, **slash-separated lists can't currently be written literally.** Sass +historically used the `/` character to indicate division, so while existing +stylesheets transition to using [`math.div()`] slash-separated lists can only be +written using [`list.slash()`]. + +[`math.div()`]: /documentation/modules/math#div +[`list.slash()`]: /documentation/modules/list#slash + +For more details, see [Breaking Change: Slash as Division]. + +[Breaking Change: Slash as Division]: /documentation/breaking-changes/slash-div + +## Using Lists + +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]: /documentation/modules/list + +### Indexes + +Many of these functions take or return numbers, called *indexes*, that refer to +the elements in a list. The index 1 indicates the first element of the list. +Note that this is different than many programming languages where indexes start +at 0! Sass also makes it easy to refer to the end of a list. The index -1 refers +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 +[`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. + +[`list.nth($list, $n)` function]: /documentation/modules/list#nth + +{% render 'code_snippets/example-list-nth' %} + +### Do Something for Every Element + +This doesn't actually use a function, but it's still one of the most common ways +to use lists. The [`@each` rule][] evaluates a block of styles for each element +in a list, and assigns that element to a variable. + +[`@each` rule]: /documentation/at-rules/control/each + +{% render 'code_snippets/example-each-list' %} + +### Add to a List + +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. + +[`list.append($list, $val)` function]: /documentation/modules/list#append +[immutable]: #immutability + +{% codeExample 'lists', false %} + @debug append(10px 12px 16px, 25px); // 10px 12px 16px 25px + @debug append([col1-line1], col1-line2); // [col1-line1, col1-line2] + === + @debug append(10px 12px 16px, 25px) // 10px 12px 16px 25px + @debug append([col1-line1], col1-line2) // [col1-line1, col1-line2] +{% endcodeExample %} + +### 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 [`list.index($list, $value)` function][]. This takes a list and a +value to locate in that list, and returns the index of that value. + +[`list.index($list, $value)` function]: /documentation/modules/list#index + +{% render 'code_snippets/example-list-index' %} + +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`]: /documentation/values/null +[falsey]: /documentation/at-rules/control/if#truthiness-and-falsiness +[`@if`]: /documentation/at-rules/control/if +[`if()`]: /documentation/modules#if + +{% codeExample 'list-index', false %} + @use "sass:list"; + + $valid-sides: top, bottom, left, right; + + @mixin attach($side) { + @if not list.index($valid-sides, $side) { + @error "#{$side} is not a valid side. Expected one of #{$valid-sides}."; + } + + // ... + } + === + @use "sass:list" + + $valid-sides: top, bottom, left, right + + @mixin attach($side) + @if not list.index($valid-sides, $side) + @error "#{$side} is not a valid side. Expected one of #{$valid-sides}." + + + // ... +{% endcodeExample %} + +## Immutability + +Lists in Sass are *immutable*, which means that the contents of a list value +never changes. Sass's list functions all return new lists rather than modifying +the originals. Immutability helps avoid lots of sneaky bugs that can creep in +when the same list is shared across different parts of the stylesheet. + +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. + +{% codeExample 'immutability', false %} + @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: 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: list.append($prefixes, map.get($prefixes-by-browser, $browser)) + + @return $prefixes + + + @debug prefixes-for-browsers("firefox" "ie") // moz ms +{% endcodeExample %} + +## Argument Lists + +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 [`meta.keywords()` function][]. + +[arbitrary arguments]: /documentation/at-rules/mixin#taking-arbitrary-arguments +[`meta.keywords()` function]: /documentation/modules/meta#keywords + +{% render 'code_snippets/example-mixin-arbitrary-keyword-arguments' %} diff --git a/source/documentation/values/maps.liquid b/source/documentation/values/maps.liquid deleted file mode 100644 index 2a0c0ae..0000000 --- a/source/documentation/values/maps.liquid +++ /dev/null @@ -1,191 +0,0 @@ ---- -title: Maps -table_of_contents: true ---- - -{% markdown %} - Maps in Sass hold pairs of keys and values, and make it easy to look up a - value by its corresponding key. They're written `(: , - : )`. The - [expression](/documentation/syntax/structure#expressions) before the `:` is - the key, and the expression after is the value associated with that key. The - keys must be unique, but the values may be duplicated. Unlike - [lists](/documentation/values/lists), maps *must* be written with parentheses - around them. A map with no pairs is written `()`. - - {% funFact %} - Astute readers may note that an empty map, `()`, is written the same as an - empty list. That's because it counts as both a map and a list. In fact, - *all* maps count as lists! 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)`. - {% endfunFact %} - - Maps allow any Sass values to be used as their keys. The [`==` operator][] is - used to determine whether two keys are the same. - - [`==` operator]: /documentation/operators/equality - - {% headsUp %} - Most of the time, it's a good idea to use [quoted strings][] rather than - [unquoted strings][] for map keys. This is because some values, such as - color names, may *look* like unquoted strings but actually be other types. - To avoid confusing problems down the line, just use quotes! - - [quoted strings]: /documentation/values/strings#quoted - [unquoted strings]: /documentation/values/strings#unquoted - {% endheadsUp %} - - ## Using Maps - - 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. - - [functions]: /documentation/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][]! - 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]: /documentation/modules/map#get - [`null`]: /documentation/values/null -{% endmarkdown %} - -{% render 'code_snippets/example-map-get' %} - -{% markdown %} - ### Do Something for Every Pair - - This doesn't actually use a function, but it's still one of the most common - ways to use maps. The [`@each` rule][] evaluates a block of styles for each - key/value pair in a map. The key and the value are assigned to variables so - they can easily be accessed in the block. - - [`@each` rule]: /documentation/at-rules/control/each -{% endmarkdown %} - -{% render 'code_snippets/example-each-map' %} - -{% markdown %} - ### 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.set($map, $key, $value)` function][] does this: it - returns a copy of `$map` with the value at `$key` set to `$value`. - - [`map.set($map, $key, $value)` function]: /documentation/modules/map#set -{% endmarkdown %} - -{% codeExample 'maps', false %} - @use "sass:map"; - - $font-weights: ("regular": 400, "medium": 500, "bold": 700); - - @debug map.set($font-weights, "extra-bold", 900); - // ("regular": 400, "medium": 500, "bold": 700, "extra-bold": 900) - @debug map.set($font-weights, "bold", 900); - // ("regular": 400, "medium": 500, "bold": 900) - === - @use "sass:map" - - $font-weights: ("regular": 400, "medium": 500, "bold": 700) - - @debug map.set($font-weights, "extra-bold": 900) - // ("regular": 400, "medium": 500, "bold": 700, "extra-bold": 900) - @debug map.set($font-weights, "bold", 900) - // ("regular": 400, "medium": 500, "bold": 900) -{% endcodeExample %} - -{% markdown %} - Instead of setting values one-by-one, you can also merge two existing maps - using [`map.merge($map1, $map2)`][]. - - [`map.merge($map1, $map2)`]: /documentation/modules/map#merge -{% endmarkdown %} - -{% codeExample 'map-merge', false %} - @use "sass:map"; - - $light-weights: ("lightest": 100, "light": 300); - $heavy-weights: ("medium": 500, "bold": 700); - - @debug map.merge($light-weights, $heavy-weights); - // ("lightest": 100, "light": 300, "medium": 500, "bold": 700) - === - @use "sass:map" - - $light-weights: ("lightest": 100, "light": 300) - $heavy-weights: ("medium": 500, "bold": 700) - - @debug map.merge($light-weights, $heavy-weights) - // ("lightest": 100, "light": 300, "medium": 500, "bold": 700) -{% endcodeExample %} - -{% markdown %} - If both maps have the same keys, the second map's values are used in the map - that gets returned. -{% endmarkdown %} - -{% codeExample 'map-same-keys', false %} - @use "sass:map"; - - $weights: ("light": 300, "medium": 500); - - @debug map.merge($weights, ("medium": 700)); - // ("light": 300, "medium": 700) - === - @use "sass:map"; - - $weights: ("light": 300, "medium": 500) - - @debug map.merge($weights, ("medium": 700)) - // ("light": 300, "medium": 700) -{% endcodeExample %} - -{% markdown %} - Note that because Sass maps are [immutable][], `map.set()` and `map.merge()` - do not modify the original list. - - [immutable]: #immutability - - ## Immutability - - Maps in Sass are *immutable*, which means that the contents of a map value - never changes. Sass's map functions all return new maps rather than modifying - the originals. Immutability helps avoid lots of sneaky bugs that can creep in - when the same map is shared across different parts of the stylesheet. - - You can still update your state over time by assigning new maps to the same - variable, though. This is often used in functions and mixins to track - configuration in a map. -{% endmarkdown %} - -{% codeExample 'immutability', false %} - @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)) !global; - } - - @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)) !global - - - @include add-browser-prefix("opera", o) - @debug $prefixes-by-browser - // ("firefox": moz, "safari": webkit, "ie": ms, "opera": o) -{% endcodeExample %} diff --git a/source/documentation/values/maps.md b/source/documentation/values/maps.md new file mode 100644 index 0000000..fecb8ae --- /dev/null +++ b/source/documentation/values/maps.md @@ -0,0 +1,179 @@ +--- +title: Maps +table_of_contents: true +--- + +Maps in Sass hold pairs of keys and values, and make it easy to look up a value +by its corresponding key. They're written `(: , +: )`. The +[expression](/documentation/syntax/structure#expressions) before the `:` is the +key, and the expression after is the value associated with that key. The keys +must be unique, but the values may be duplicated. Unlike +[lists](/documentation/values/lists), maps *must* be written with parentheses +around them. A map with no pairs is written `()`. + +{% funFact %} + Astute readers may note that an empty map, `()`, is written the same as an + empty list. That's because it counts as both a map and a list. In fact, *all* + maps count as lists! 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)`. +{% endfunFact %} + +Maps allow any Sass values to be used as their keys. The [`==` operator][] is +used to determine whether two keys are the same. + +[`==` operator]: /documentation/operators/equality + +{% headsUp %} + Most of the time, it's a good idea to use [quoted strings][] rather than + [unquoted strings][] for map keys. This is because some values, such as color + names, may *look* like unquoted strings but actually be other types. To avoid + confusing problems down the line, just use quotes! + + [quoted strings]: /documentation/values/strings#quoted + [unquoted strings]: /documentation/values/strings#unquoted +{% endheadsUp %} + +## Using Maps + +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. + +[functions]: /documentation/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][]! +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]: /documentation/modules/map#get +[`null`]: /documentation/values/null + +{% render 'code_snippets/example-map-get' %} + +### Do Something for Every Pair + +This doesn't actually use a function, but it's still one of the most common ways +to use maps. The [`@each` rule][] evaluates a block of styles for each key/value +pair in a map. The key and the value are assigned to variables so they can +easily be accessed in the block. + +[`@each` rule]: /documentation/at-rules/control/each + +{% render 'code_snippets/example-each-map' %} + +### 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.set($map, $key, $value)` function][] does this: it +returns a copy of `$map` with the value at `$key` set to `$value`. + +[`map.set($map, $key, $value)` function]: /documentation/modules/map#set + +{% codeExample 'maps', false %} + @use "sass:map"; + + $font-weights: ("regular": 400, "medium": 500, "bold": 700); + + @debug map.set($font-weights, "extra-bold", 900); + // ("regular": 400, "medium": 500, "bold": 700, "extra-bold": 900) + @debug map.set($font-weights, "bold", 900); + // ("regular": 400, "medium": 500, "bold": 900) + === + @use "sass:map" + + $font-weights: ("regular": 400, "medium": 500, "bold": 700) + + @debug map.set($font-weights, "extra-bold": 900) + // ("regular": 400, "medium": 500, "bold": 700, "extra-bold": 900) + @debug map.set($font-weights, "bold", 900) + // ("regular": 400, "medium": 500, "bold": 900) +{% endcodeExample %} + +Instead of setting values one-by-one, you can also merge two existing maps using +[`map.merge($map1, $map2)`][]. + +[`map.merge($map1, $map2)`]: /documentation/modules/map#merge + +{% codeExample 'map-merge', false %} + @use "sass:map"; + + $light-weights: ("lightest": 100, "light": 300); + $heavy-weights: ("medium": 500, "bold": 700); + + @debug map.merge($light-weights, $heavy-weights); + // ("lightest": 100, "light": 300, "medium": 500, "bold": 700) + === + @use "sass:map" + + $light-weights: ("lightest": 100, "light": 300) + $heavy-weights: ("medium": 500, "bold": 700) + + @debug map.merge($light-weights, $heavy-weights) + // ("lightest": 100, "light": 300, "medium": 500, "bold": 700) +{% endcodeExample %} + +If both maps have the same keys, the second map's values are used in the map +that gets returned. + +{% codeExample 'map-same-keys', false %} + @use "sass:map"; + + $weights: ("light": 300, "medium": 500); + + @debug map.merge($weights, ("medium": 700)); + // ("light": 300, "medium": 700) + === + @use "sass:map"; + + $weights: ("light": 300, "medium": 500) + + @debug map.merge($weights, ("medium": 700)) + // ("light": 300, "medium": 700) +{% endcodeExample %} + +Note that because Sass maps are [immutable][], `map.set()` and `map.merge()` do +not modify the original list. + +[immutable]: #immutability + +## Immutability + +Maps in Sass are *immutable*, which means that the contents of a map value never +changes. Sass's map functions all return new maps rather than modifying the +originals. Immutability helps avoid lots of sneaky bugs that can creep in when +the same map is shared across different parts of the stylesheet. + +You can still update your state over time by assigning new maps to the same +variable, though. This is often used in functions and mixins to track +configuration in a map. + +{% codeExample 'immutability', false %} + @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)) !global; + } + + @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)) !global + + + @include add-browser-prefix("opera", o) + @debug $prefixes-by-browser + // ("firefox": moz, "safari": webkit, "ie": ms, "opera": o) +{% endcodeExample %} diff --git a/source/documentation/values/null.liquid b/source/documentation/values/null.md similarity index 66% rename from source/documentation/values/null.liquid rename to source/documentation/values/null.md index e4bb68d..be3f652 100644 --- a/source/documentation/values/null.liquid +++ b/source/documentation/values/null.md @@ -22,12 +22,9 @@ introduction: > @debug & // null {% endcodeExample %} -{% markdown %} - If a [list][] contains a `null`, that `null` is omitted from the generated - CSS. +If a [list][] contains a `null`, that `null` is omitted from the generated CSS. - [list]: /documentation/values/lists -{% endmarkdown %} +[list]: /documentation/values/lists {% codeExample 'null-lists' %} $fonts: ("serif": "Helvetica Neue", "monospace": "Consolas"); @@ -42,9 +39,7 @@ introduction: > font: 18px bold map-get($fonts, "sans") {% endcodeExample %} -{% markdown %} - If a property value is `null`, that property is omitted entirely. -{% endmarkdown %} +If a property value is `null`, that property is omitted entirely. {% codeExample 'null-value-omitted' %} $fonts: ("serif": "Helvetica Neue", "monospace": "Consolas"); @@ -66,15 +61,13 @@ introduction: > family: map-get($fonts, "sans") {% endcodeExample %} -{% markdown %} - `null` is also [*falsey*][], which means it counts as `false` for any rules or - [operators][] that take booleans. This makes it easy to use values that can be - `null` as conditions for [`@if`][] and [`if()`][]. +`null` is also [*falsey*][], which means it counts as `false` for any rules or +[operators][] that take booleans. This makes it easy to use values that can be +`null` as conditions for [`@if`][] and [`if()`][]. - [*falsey*]: /documentation/at-rules/control/if#truthiness-and-falsiness - [operators]: /documentation/operators/boolean - [`@if`]: /documentation/at-rules/control/if - [`if()`]: /documentation/modules#if -{% endmarkdown %} +[*falsey*]: /documentation/at-rules/control/if#truthiness-and-falsiness +[operators]: /documentation/operators/boolean +[`@if`]: /documentation/at-rules/control/if +[`if()`]: /documentation/modules#if {% render 'code_snippets/example-if-parent-selector' %} diff --git a/source/documentation/values/numbers.liquid b/source/documentation/values/numbers.md similarity index 50% rename from source/documentation/values/numbers.liquid rename to source/documentation/values/numbers.md index 8808f6b..bd1b4d5 100644 --- a/source/documentation/values/numbers.liquid +++ b/source/documentation/values/numbers.md @@ -19,14 +19,12 @@ introduction: > @debug 5px * 2px // 10px*px (read "square pixels") {% endcodeExample %} -{% markdown %} - Sass numbers support the same formats as CSS numbers, including [scientific - notation][], which is written with an `e` between the number and its power - of 10. Because support for scientific notation in browsers has historically - been spotty, Sass always compiles it to fully expanded numbers. +Sass numbers support the same formats as CSS numbers, including [scientific +notation][], which is written with an `e` between the number and its power of +10. Because support for scientific notation in browsers has historically been +spotty, Sass always compiles it to fully expanded numbers. - [scientific notation]: https://en.wikipedia.org/wiki/Scientific_notation -{% endmarkdown %} +[scientific notation]: https://en.wikipedia.org/wiki/Scientific_notation {% codeExample 'scientific-notation', false %} @debug 5.2e3; // 5200 @@ -44,34 +42,32 @@ introduction: > {% render 'doc_snippets/number-units' %} -{% markdown %} - ## Precision +## Precision - {% compatibility 'dart: true', 'libsass: false', 'ruby: "3.5.0"', 'feature: "10 Digit Default"' %} - LibSass and older versions of Ruby Sass default to 5 digits of numeric - precision, but can be configured to use a different number. It's recommended - that users configure them for 10 digits for greater accuracy and - forwards-compatibility. - {% endcompatibility %} +{% compatibility 'dart: true', 'libsass: false', 'ruby: "3.5.0"', 'feature: "10 Digit Default"' %} + LibSass and older versions of Ruby Sass default to 5 digits of numeric + precision, but can be configured to use a different number. It's recommended + that users configure them for 10 digits for greater accuracy and + forwards-compatibility. +{% endcompatibility %} - Sass numbers are represented internally as 64-bit floating point values. They - support up to 10 digits of precision after the decimal point when serialized - to CSS and for the purposes of equality. This means a few different things: +Sass numbers are represented internally as 64-bit floating point values. They +support up to 10 digits of precision after the decimal point when serialized to +CSS and for the purposes of equality. This means a few different things: - * Only the first ten digits of a number after the decimal point will be - included in the generated CSS. +* Only the first ten digits of a number after the decimal point will be included + in the generated CSS. - * Operations like [`==`][] and [`>=`][] will consider two numbers equivalent - if they're the same up to the tenth digit after the decimal point. +* Operations like [`==`][] and [`>=`][] will consider two numbers equivalent if + 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 - [`list.nth()`][] that require integer arguments. +* 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 [`list.nth()`][] that + require integer arguments. - [`==`]: /documentation/operators/equality - [`>=`]: /documentation/operators/relational - [`list.nth()`]: /documentation/modules/list#nth -{% endmarkdown %} +[`==`]: /documentation/operators/equality +[`>=`]: /documentation/operators/relational +[`list.nth()`]: /documentation/modules/list#nth {% codeExample 'precision', false %} @debug 0.012345678912345; // 0.0123456789 diff --git a/source/documentation/values/strings.liquid b/source/documentation/values/strings.md similarity index 53% rename from source/documentation/values/strings.liquid rename to source/documentation/values/strings.md index 6e1abab..a1eaa91 100644 --- a/source/documentation/values/strings.liquid +++ b/source/documentation/values/strings.md @@ -10,15 +10,13 @@ introduction: > these cover the different kinds of text that appear in CSS. --- -{% funFact false %} - {% markdown %} - 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][]. +{% funFact %} + 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][]. - [`string.unquote()` function]: /documentation/modules/string#unquote - [`string.quote()` function]: /documentation/modules/string#quote - {% endmarkdown %} + [`string.unquote()` function]: /documentation/modules/string#unquote + [`string.quote()` function]: /documentation/modules/string#quote {% codeExample 'fun-fact-strings', false %} @use "sass:string"; @@ -33,25 +31,22 @@ introduction: > {% endcodeExample %} {% endfunFact %} -{% markdown %} - ## Escapes +## Escapes - All Sass strings support the standard CSS [escape codes][]: +All Sass strings support the standard CSS [escape codes][]: - [escape codes]: https://developer.mozilla.org/en-US/docs/Web/CSS/string#Syntax +[escape codes]: https://developer.mozilla.org/en-US/docs/Web/CSS/string#Syntax - * Any character other than a letter from A to F or a number from 0 to 9 (even - a newline!) can be included as part of a string by writing `\` in front of - it. +* Any character other than a letter from A to F or a number from 0 to 9 (even a + newline!) can be included as part of a string by writing `\` in front of it. - * Any character can be included as part of a string by writing `\` followed by - its [Unicode code point number][] written in [hexadecimal][]. You can - optionally include a space after the code point number to indicate where the - Unicode number ends. +* Any character can be included as part of a string by writing `\` followed by + its [Unicode code point number][] written in [hexadecimal][]. You can + optionally include a space after the code point number to indicate where the + Unicode number ends. - [Unicode code point number]: https://en.wikipedia.org/wiki/List_of_Unicode_characters - [hexadecimal]: https://en.wikipedia.org/wiki/Hexadecimal -{% endmarkdown %} + [Unicode code point number]: https://en.wikipedia.org/wiki/List_of_Unicode_characters + [hexadecimal]: https://en.wikipedia.org/wiki/Hexadecimal {% codeExample 'escapes', false %} @debug "\""; // '"' @@ -72,29 +67,27 @@ introduction: > escape produces exactly the same string as writing the character itself. {% endfunFact %} -{% markdown %} - ## Quoted +## Quoted - Quoted strings are written between either single or double quotes, as in - `"Helvetica Neue"`. They can contain [interpolation][], as well as any - unescaped character except for: +Quoted strings are written between either single or double quotes, as in +`"Helvetica Neue"`. They can contain [interpolation][], as well as any unescaped +character except for: - [interpolation]: /documentation/interpolation +[interpolation]: /documentation/interpolation - * `\`, which can be escaped as `\\`; - * `'` or `"`, whichever was used to define that string, which can be escaped - as `\'` or `\"`; - * newlines, which can be escaped as `\a ` (including a trailing space). +* `\`, which can be escaped as `\\`; +* `'` or `"`, whichever was used to define that string, which can be escaped as + `\'` or `\"`; +* newlines, which can be escaped as `\a ` (including a trailing space). - Quoted strings are guaranteed to be compiled to CSS strings that have the same - contents as the original Sass strings. The exact format may vary based on the - implementation or configuration—a string containing a double quote may be - compiled to `"\""` or `'"'`, and a non-[ASCII][] character may or may not be - escaped. But that should be parsed the same in any standards-compliant CSS - implementation, including all browsers. +Quoted strings are guaranteed to be compiled to CSS strings that have the same +contents as the original Sass strings. The exact format may vary based on the +implementation or configuration—a string containing a double quote may be +compiled to `"\""` or `'"'`, and a non-[ASCII][] character may or may not be +escaped. But that should be parsed the same in any standards-compliant CSS +implementation, including all browsers. - [ASCII]: https://en.wikipedia.org/wiki/ASCII -{% endmarkdown %} +[ASCII]: https://en.wikipedia.org/wiki/ASCII {% codeExample 'quoted', false %} @debug "Helvetica Neue"; // "Helvetica Neue" @@ -123,15 +116,13 @@ introduction: > [its quotes are removed]: /documentation/interpolation#quoted-strings {% endfunFact %} -{% markdown %} - ## Unquoted +## Unquoted - Unquoted strings are written as CSS [identifiers][], following the syntax - diagram below. They may include [interpolation][] anywhere. +Unquoted strings are written as CSS [identifiers][], following the syntax +diagram below. They may include [interpolation][] anywhere. - [identifiers]: https://drafts.csswg.org/css-syntax-3/#ident-token-diagram - [interpolation]: /documentation/interpolation -{% endmarkdown %} +[identifiers]: https://drafts.csswg.org/css-syntax-3/#ident-token-diagram +[interpolation]: /documentation/interpolation
@@ -173,31 +164,28 @@ introduction: > strings. {% endheadsUp %} -{% markdown %} - ### Escapes in Unquoted Strings +### Escapes in Unquoted Strings - {% compatibility 'dart: "1.11.0"', 'libsass: false', 'ruby: false', 'feature: "Normalization"' %} - LibSass, Ruby Sass, and older versions of Dart Sass don't normalize escapes - in identifiers. Instead, the text in the unquoted string is the exact text - the user wrote. For example, `\1F46D` and `👭` are not considered - equivalent. - {% endcompatibility %} +{% compatibility 'dart: "1.11.0"', 'libsass: false', 'ruby: false', 'feature: "Normalization"' %} + LibSass, Ruby Sass, and older versions of Dart Sass don't normalize escapes in + identifiers. Instead, the text in the unquoted string is the exact text the + user wrote. For example, `\1F46D` and `👭` are not considered equivalent. +{% endcompatibility %} - When an unquoted string is parsed, the literal text of escapes are parsed as - part of the string. For example, `\a ` is parsed as the characters `\`, `a`, - and space. In order to ensure that unquoted strings that have the same - meanings in CSS are parsed the same way, though, these escapes are - *normalized*. For each code point, whether it's escaped or unescaped: +When an unquoted string is parsed, the literal text of escapes are parsed as +part of the string. For example, `\a ` is parsed as the characters `\`, `a`, and +space. In order to ensure that unquoted strings that have the same meanings in +CSS are parsed the same way, though, these escapes are *normalized*. For each +code point, whether it's escaped or unescaped: - * If it's a valid identifier character, it's included unescaped in the - unquoted string. For example, `\1F46D` returns the unquoted string `👭`. +* If it's a valid identifier character, it's included unescaped in the unquoted + string. For example, `\1F46D` returns the unquoted string `👭`. - * If it's a printable character other than a newline or a tab, it's included - after a `\`. For example, `\21 ` returns the unquoted string `\!`. +* If it's a printable character other than a newline or a tab, it's included + after a `\`. For example, `\21 ` returns the unquoted string `\!`. - * Otherwise, the lowercase Unicode escape is included with a trailing space. - For example, `\7Fx` returns the unquoted string `\7f x`. -{% endmarkdown %} +* Otherwise, the lowercase Unicode escape is included with a trailing space. For + example, `\7Fx` returns the unquoted string `\7f x`. {% codeExample 'normalization', false %} @use "sass:string"; @@ -215,18 +203,16 @@ introduction: > @debug string.length(\7Fx) // 5 {% endcodeExample %} -{% markdown %} - ## String Indexes +## String Indexes - Sass has a number of [string functions][] that take or return numbers, called - *indexes*, that refer to the characters in a string. The index 1 indicates the - first character of the string. Note that this is different than many - programming 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. +Sass has a number of [string functions][] that take or return numbers, called +*indexes*, that refer to the characters in a string. The index 1 indicates the +first character of the string. Note that this is different than many programming +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]: /documentation/modules/string -{% endmarkdown %} +[string functions]: /documentation/modules/string {% codeExample 'string-indexes', false %} @use "sass:string";