Skip to content

Commit 371d0a1

Browse files
committed
[css-values-4] Add min()/max().
1 parent 22687d6 commit 371d0a1

File tree

1 file changed

+117
-45
lines changed

1 file changed

+117
-45
lines changed

css-values/Overview.bs

Lines changed: 117 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,14 +1583,20 @@ Functional Notations</h2>
15831583
-->
15841584

15851585
<h3 id="calc-notation">
1586-
Mathematical Expressions: ''calc()''</h3>
1586+
Mathematical Expressions: ''calc()'', ''min()'', and ''max()''</h3>
15871587

1588-
The <dfn>calc()</dfn> function allows mathematical expressions
1588+
The <dfn>math functions</dfn>,
1589+
<dfn>calc()</dfn>, <dfn>min()</dfn>, and <dfn>max()</dfn>,
1590+
allow mathematical expressions
15891591
with addition (''+''), subtraction (''-''), multiplication (''*''), and division (''/'')
15901592
to be used as component values.
1591-
The ''calc()'' expression represents the result of the mathematical calculation it contains,
1592-
using standard operator precedence rules.
1593-
It can be used wherever
1593+
A ''calc()'' function represents the result of the mathematical calculation it contains,
1594+
using standard operator precedence rules;
1595+
a ''min()'' or ''max()'' function represents
1596+
the smallest (most negative) or largest (most positive), respectively,
1597+
comma-separated calculation it contains.
1598+
1599+
A [=math function=] can be used wherever
15941600
<<length>>,
15951601
<<frequency>>,
15961602
<<angle>>,
@@ -1599,8 +1605,10 @@ Mathematical Expressions: ''calc()''</h3>
15991605
<<number>>, or
16001606
<<integer>>
16011607
values are allowed.
1602-
Components of a ''calc()'' expression can be literal values or
1603-
''attr()'' or ''calc()'' expressions.
1608+
Components of a [=math function=] can be literal values,
1609+
other [=math functions=],
1610+
or other expressions, such as ''attr()'',
1611+
that evaluate to a valid argument type (like <<length>>).
16041612

16051613
<div class="example">
16061614
<pre>
@@ -1664,10 +1672,12 @@ Mathematical Expressions: ''calc()''</h3>
16641672
<h4 id='calc-syntax'>
16651673
Syntax</h4>
16661674

1667-
The syntax of a ''calc()'' function is:
1675+
The syntax of a [=math function=] is:
16681676

16691677
<pre class='prod'>
16701678
<<calc()>> = calc( <<calc-sum>> )
1679+
<<min()>> = min( <<calc-sum>># )
1680+
<<max()>> = max( <<calc-sum>># )
16711681
<dfn>&lt;calc-sum></dfn> = <<calc-product>> [ [ '+' | '-' ] <<calc-product>> ]*
16721682
<dfn>&lt;calc-product></dfn> = <<calc-value>> [ '*' <<calc-value>> | '/' <<calc-number-value>> ]*
16731683
<dfn>&lt;calc-value></dfn> = <<number>> | <<dimension>> | <<percentage>> | ( <<calc-sum>> )
@@ -1676,38 +1686,53 @@ Syntax</h4>
16761686
<dfn>&lt;calc-number-value></dfn> = <<number>> | ( <<calc-number-sum>> )
16771687
</pre>
16781688

1679-
In addition, <a href="https://www.w3.org/TR/css-syntax/#whitespace">white space</a>
1689+
In addition, [=whitespace=]
16801690
is required on both sides of the ''+'' and ''-'' operators.
16811691
(The ''*'' and ''/'' operaters can be used without white space around them.)
16821692

1683-
UAs must support ''calc()'' expressions of at least 20 terms,
1693+
UAs must support [=math function=] expressions of at least 20 terms,
16841694
where each <code>NUMBER</code>, <code>DIMENSION</code>, or <code>PERCENTAGE</code> is a term.
1685-
If a ''calc()'' expression contains more than the supported number of terms,
1695+
If a [=math function=] contains more than the supported number of terms,
16861696
it must be treated as if it were invalid.
16871697

16881698

16891699
<h4 id='calc-type-checking'>
16901700
Type Checking</h4>
16911701

1692-
A math expression has a <dfn>resolved type</dfn>, which is one of
1702+
A [=math function=] has a <dfn>resolved type</dfn>, which is one of
16931703
<<length>>,
16941704
<<frequency>>,
16951705
<<angle>>,
16961706
<<time>>,
16971707
<<percentage>>,
16981708
<<number>>, or
16991709
<<integer>>.
1700-
The <a>resolved type</a> must be valid for where the expression is placed;
1710+
The <a>resolved type</a> must be valid for where the [=math function=] is placed;
17011711
otherwise, the expression is invalid.
1702-
The <a>resolved type</a> of the expression is determined by the types of the values it contains.
1703-
<<number-token>>s are of type <<number>> or <<integer>>.
1704-
A <<dimension-token>>’s type is given by its unit
1705-
(''cm'' is <<length>>, ''deg'' is <<angle>>, etc.).
1706-
An ''attr()'' expression's type is given by its <<type-or-unit>> argument.
1712+
1713+
The <a>resolved type</a> of a [=math function=] is determined by the values and calculations it contains:
1714+
1715+
* <<number-token>>s are of type <<number>> or <<integer>>.
1716+
* A <<dimension-token>>’s type is given by its unit
1717+
(''cm'' is <<length>>, ''deg'' is <<angle>>, etc.).
1718+
* Functions’ types are defined by their specification
1719+
(nested ''calc()'' has its type determined by its own contents,
1720+
''attr()''’s type is determined by its <<type-or-unit>> argument,
1721+
etc).
1722+
* Larger calculations’ types are determined by the types of their arguments
1723+
and the rules for their operation,
1724+
as defined below.
1725+
1726+
A ''calc()'' expression's <a>resolved type</a> is the <a>resolved type</a> of the calculation it contains.
1727+
The <a>resolved type</a> of a ''min()'' or ''max()'' expression
1728+
is the <a>resolved type</a> of any of the calculations it contains.
1729+
If a ''min()'' or ''max()'' expression's arguments have different <a>resolved types</a>,
1730+
the expression is invalid.
17071731

17081732
Note: Because <<number-token>>s are always interpreted as <<number>>s or <<integer>>s,
1709-
"unitless 0" <<length>>s aren't supported in ''calc()''.
1733+
"unitless 0" <<length>>s aren't supported in [=math functions=].
17101734
That is, ''width: calc(0 + 5px);'' is invalid,
1735+
because it's trying to add a <<number>> to a <<length>>,
17111736
even though both ''width: 0;''
17121737
and ''width: 5px;''
17131738
are valid.
@@ -1778,38 +1803,42 @@ Type Checking</h4>
17781803
(as purely-numeric expressions can be evaluated without any additional
17791804
information at parse time).
17801805

1781-
Note: Algebraic simplifications do not affect the validity of the ''calc()'' expression or its resolved type.
1806+
Note: Algebraic simplifications do not affect the validity of a [=math function=] or its resolved type.
17821807
For example, ''calc(5px - 5px + 10s)'' and ''calc(0 * 5px + 10s)'' are both invalid
17831808
due to the attempt to add a length and a time.
17841809

17851810
<h4 id='calc-computed-value'>
17861811
Computed Value</h4>
17871812

1788-
The computed value of a ''calc()'' expression is the expression
1813+
The computed value of a ''calc()'' function is the expression
17891814
with all components computed.
1815+
The computed value of a ''min()'' or ''max()'' function
1816+
is the comma-separated list of expressions,
1817+
with each expression having all its component computed.
17901818

17911819
Where percentages are not resolved at computed-value time,
1792-
they are not resolved in ''calc()'' expressions,
1820+
they are not resolved in [=math functions=],
17931821
e.g. ''calc(100% - 100% + 1em)'' resolves to ''calc(1em + 0%)'',
17941822
not to ''1em''.
17951823
If there are special rules for computing percentages in a value
17961824
(e.g. <a href="https://www.w3.org/TR/CSS21/visudet.html#the-height-property">the <css>height</css> property</a>),
1797-
they apply whenever a ''calc()'' expression contains percentages.
1825+
they apply whenever a [=math function=] contains percentages.
17981826

17991827
<div class=note>
18001828
Note: The serialization rules do not preserve the structure of the computation,
18011829
so implementations can simplify the expressions
18021830
further than what is required here
18031831
when storing the values internally;
1804-
in particular, all ''calc()'' expressions can be reduced
1832+
in particular, all [=math function=] expressions can be reduced
18051833
to a sum of a <<number>>, a <<percentage>>, and some <<dimension>>s,
18061834
eliminating all multiplication or division,
18071835
and combining terms with identical units.
18081836

18091837
At this time, all units can be absolutized
18101838
to a single unit per type at computed-value time,
1811-
so at that point the ''calc()'' expression can be reduced
1812-
to just a <<number>>, a <<percentage>>, and a single absolute <<dimension>> of the appropriate type.
1839+
so at that point the [=math function=] can be reduced
1840+
to just a <<number>>, a <<percentage>>, and a single absolute <<dimension>> of the appropriate type,
1841+
per expression.
18131842
</div>
18141843

18151844
<div class='example'>
@@ -1848,7 +1877,7 @@ Computed Value</h4>
18481877
<h4 id='calc-range'>
18491878
Range Checking</h4>
18501879

1851-
Parse-time range-checking of values is not performed within ''calc()'',
1880+
Parse-time range-checking of values is not performed within [=math functions=],
18521881
and therefore out-of-range values do not cause the declaration to become invalid.
18531882
However, the used value resulting from an expression
18541883
must be clamped to the range allowed in the target context.
@@ -1876,33 +1905,76 @@ Serialization</h4>
18761905

18771906
Issue: This section is still <a href="https://lists.w3.org/Archives/Member/w3c-css-wg/2016AprJun/0239.html">under discussion</a>.
18781907

1879-
To serialize a ''calc()'' value:
1908+
<div algorithm="serialize a calc() value">
1909+
To <dfn>serialize a ''calc()'' value</dfn>
1910+
1911+
1. [=Simplify the expression=] inside of it.
18801912

1881-
1. Simplify the expression by:
1913+
2. If this simplification process results in only a single value
1914+
(one <<number>>, one <<dimension>>, or one <<percentage>>),
1915+
and the value being serialized is a <a>computed value</a> or later,
1916+
serialize it just as that one value,
1917+
without the ''calc()'' wrapper.
1918+
If this value is outside the allowed range for the context,
1919+
it must be clamped to the nearest allowed value.
1920+
1921+
3. Otherwise,
1922+
[=serialize the summation=],
1923+
prefix the result with "calc("
1924+
and suffix it with ")",
1925+
then return it.
1926+
</div>
18821927

1883-
* Replacing nested ''calc()'' values with parentheses containing their contents
1884-
* Resolving all multiplications and divisions
1885-
* Combining identical units
1928+
<div algorithm="serialize a min()/max() value">
1929+
To <dfn lt="serialize a min() value|serialize a max() value">serialize a ''min()'' or ''max()'' value</dfn>:
1930+
1931+
1. For each comma-separated expression inside of it,
1932+
[=simplify the expression=].
1933+
1934+
2. Let |s| initially be "min(" or "max(", as appropriate.
1935+
1936+
3. [=serialize the summation|Serialize each summation=],
1937+
then join them into a single string,
1938+
with ", " between each term.
1939+
Append the result to |s|.
1940+
1941+
4. Append ")" to |s|,
1942+
then return it.
1943+
</div>
1944+
1945+
<div algorithm="simplify an expression">
1946+
To <dfn lt="simplify an expression | simplify the expression" for="math function">simplify an expression</dfn>:
1947+
1948+
1. Replace any ''calc()'' values with parentheses containing their contents.
1949+
2. Resolve all multiplications and divisions.
1950+
3. Combine identical units.
1951+
4. Recurse into ''min()'' or ''max()'' values.
1952+
5. Return the result.
18861953

18871954
Note: The value-computation process can transform disparate units into identical ones.
18881955
For example, ''em'' and ''px'' are obviously different at specified-value time,
18891956
but at computed-value time they're both absolutized to ''px''.
18901957

1891-
The result must be a summation of unique units.
1958+
The result must be a summation of unique units and/or [=math functions=].
18921959
(Terms with a value of zero <strong>must</strong> be preserved in this summation.)
1960+
</div>
18931961

1894-
2. If this simplification process results in only a single value
1895-
(one <<number>>, one <<dimension>>, or one <<percentage>>),
1896-
and the value being serialized is a <a>computed value</a> or later,
1897-
serialize it just as that one value,
1898-
without the ''calc()'' wrapper.
1899-
If this value is outside the allowed range for the context,
1900-
it must be clamped to the nearest allowed value.
1901-
1902-
3. Otherwise, serialize as a ''calc()'' containing the summation,
1903-
with the units ordered <a>ASCII case-insensitive</a> alphabetically,
1904-
the number (if present) coming before all units,
1905-
and the percentage (if present) coming after all units.
1962+
<div algorithm="serialize a summation">
1963+
To <dfn lt="serialize a summation|serialize the summation" for="math function">serialize a summation</dfn>:
1964+
1965+
1. Sort the terms in the following order:
1966+
1967+
1. The number, if present
1968+
2. The dimensions, ordered by their units <a>ASCII case-insensitive</a> alphabetically
1969+
3. The percentage, if present
1970+
4. The ''min()'' and ''max()'' functions,
1971+
in the order they appeared in the original expression.
1972+
1973+
2. Serialize all the terms,
1974+
then join them into a single string,
1975+
with " + " between each term.
1976+
Return the result.
1977+
</div>
19061978

19071979
<div class="example">
19081980
For example, ''calc(20px + 30px)'' would serialize as ''calc(50px)'' as a specified value,

0 commit comments

Comments
 (0)