current position:Home>Modern CSS solution: CSS mathematical functions

Modern CSS solution: CSS mathematical functions

2022-05-15 05:03:14chokcoco

stay CSS in , In fact, there are various functions . It can be divided into :

this paper , We will introduce in detail CSS Mathematical functions (Math functions) in , Has been massively supported by browsers 4 individual :

  • calc()
  • min()
  • max()
  • clamp()

Why is it supported by browsers on a large scale ? Because apart from this 4 A mathematical function that has been supported on a large scale , In fact, the standard CSS Values and Units Module Level 4 We have defined some related functions such as trigonometric function sin()cos()tan() etc. , Exponential function correlation pow()sqrt() Wait, mathematical functions , It's just that they're all in the laboratory now , No browser supports them yet , Need some time .

Calc()

calc() this CSS Function allows you to declare CSS Some calculations are performed when the property is valued .

The syntax is similar to

{
    width: calc(100% - 80px);
}

Some points to pay attention to :

  • + and - Operators must have white space characters on both sides . such as ,calc(50% -8px) Will be resolved into an invalid expression , Must be written as calc(8px + -50%)
  • * and / You don't need white space around these two operators , But if you think about unity , It's still recommended to add white space
  • use 0 Divisor makes HTML The parser throws an exception
  • Table columns in tables involving automatic layout and fixed layout 、 List group 、 Table row 、 Mathematical expression for the width and height percentages of table row groups and table cells ,auto Can be regarded as specified .
  • calc() Functions support nesting , But the way to support it is : Put the nested calc() All functions are treated as ordinary brackets .( therefore , Just use parentheses directly in the function .)
  • calc() Support and CSS Variables are mixed

Look at one of the most common examples , The page structure is as follows :

<div class="g-container">
    <div class="g-content">Content</div>
    <div class="g-footer">Footer</div>
</div>

Page g-footer High for 80px, We hope that no matter how long the page is ,g-content Some of them can take up the remaining space , It's like this. :

This layout uses flex Flexible layout can be easily realized , Of course , You can also use calc() Realization :

.g-container {
    height: 100vh;
}
.g-content {
    height: calc(100vh - 80px);
}
.g-footer {
    height: 80px;
}

Here is a list of Calc() Advanced techniques for .

Calc The difference between addition and subtraction and multiplication and division in

Be careful ,calc() The difference between addition and subtraction and multiplication and division in :

{
    font-size: calc(1rem + 10px);
    width: calc(100px + 10%);
}

You can see , The operands on both sides of the addition and subtraction method need units , And multiplication and division , Need a unitless number , It only represents a magnification :

{
    width: calc(100% / 7);
    animation-delay: calc(1s * 3);
}

Calc Nesting of

calc() Functions can be nested , It's like this. :

{
  width: calc(100vw - calc(100% - 64px));
}

here , Inside calc() The function can be degenerated into a bracket (), So the above code is equivalent to :

{
  width: calc(100vw - (100% - 64px));
}

That is, nested calc(),calc Several function characters can be omitted .

Calc Mixed operation of different units in

calc() Support mixed operation of different units , For length , As long as it belongs to length related units, mixed operation can be carried out , Contains the :

  • px
  • %
  • em
  • rem
  • in
  • mm
  • cm
  • pt
  • pc
  • ex
  • ch
  • vh
  • vw
  • vmin
  • vmax

Here's an interesting point , Computing must be performance consuming , Early years , There is such a passage CSS Code , You can directly Chrome Browser crashes Crash:

<div></div>

CSS The style is as follows :

div {
  --initial-level-0: calc(1vh + 1% + 1px + 1em + 1vw + 1cm);

  --level-1: calc(var(--initial-level-0) + var(--initial-level-0));
  --level-2: calc(var(--level-1) + var(--level-1));
  --level-3: calc(var(--level-2) + var(--level-2));
  --level-4: calc(var(--level-3) + var(--level-3));
  --level-5: calc(var(--level-4) + var(--level-4));
  --level-6: calc(var(--level-5) + var(--level-5));
  --level-7: calc(var(--level-6) + var(--level-6));
  --level-8: calc(var(--level-7) + var(--level-7));
  --level-9: calc(var(--level-8) + var(--level-8));
  --level-10: calc(var(--level-9) + var(--level-9));
  --level-11: calc(var(--level-10) + var(--level-10));
  --level-12: calc(var(--level-11) + var(--level-11));
  --level-13: calc(var(--level-12) + var(--level-12));
  --level-14: calc(var(--level-13) + var(--level-13));
  --level-15: calc(var(--level-14) + var(--level-14));
  --level-16: calc(var(--level-15) + var(--level-15));
  --level-17: calc(var(--level-16) + var(--level-16));
  --level-18: calc(var(--level-17) + var(--level-17));
  --level-19: calc(var(--level-18) + var(--level-18));
  --level-20: calc(var(--level-19) + var(--level-19));
  --level-21: calc(var(--level-20) + var(--level-20));
  --level-22: calc(var(--level-21) + var(--level-21));
  --level-23: calc(var(--level-22) + var(--level-22));
  --level-24: calc(var(--level-23) + var(--level-23));
  --level-25: calc(var(--level-24) + var(--level-24));
  --level-26: calc(var(--level-25) + var(--level-25));
  --level-27: calc(var(--level-26) + var(--level-26));
  --level-28: calc(var(--level-27) + var(--level-27));
  --level-29: calc(var(--level-28) + var(--level-28));
  --level-30: calc(var(--level-29) + var(--level-29));

  --level-final: calc(var(--level-30) + 1px);

    border-width: var(--level-final);                                 
    border-style: solid;
}

You can see , from --level-1 To --level-30, The amount of computation increases exponentially every time , Finally arrive --level-final Variable , There will be 2^30 = 1073741824 individual --initial-level-0 The content of the expression .

also , Every --initial-level-0 The content of the expression -- calc(1vh + 1% + 1px + 1em + 1vw + 1cm), When the browser parses , It's complicated enough .

Mix it up , This leads to the of the browser BOOM(Chrome 70 Previous version ), In order to see the effect , We assign the above style to an element, which is hover When , The results are as follows :

css-crash

Of course , This BUG It has been repaired , We can also use this small DEMO come to know , One is calc It can perform mixed operations of different units , Another is to pay attention to the specific use, if the amount of calculation is huge , It may lead to large performance consumption .

Of course , Don't Mix length units with non length units , It's like this. :

{
    animation-delay: calc(1s + 1px);
}

Calc collocation CSS Custom variables use

calc() A very important feature of functions is the ability to match CSS Customize and CSS @property Variables are used together .

The easiest one DEMO:

:root {
    --width: 10px;
}
div {
    width: calc(var(--width));
}

Of course , It looks like , I can't see the function of this writing at all , It doesn't seem to make any sense . In the actual application scenario , Will be better than the above DEMO It's a little more complicated .

Suppose we want to realize such a loading Animation effect , At first, there was only 3 A ball :

The possible way to write it is like this , We give 3 Add the same rotation animation to all balls , Then control their animation-delay

<div class="g-container">
    <div class="g-item"></div>
    <div class="g-item"></div>
    <div class="g-item"></div>
</div>
.item:nth-child(1) {
    animation: rotate 3s infinite linear;
}
.item:nth-child(2) {
    animation: rotate 3s infinite -1s linear;
}
.item:nth-child(3) {
    animation: rotate 3s infinite -2s linear;
}

If one day , This animation needs to be expanded into 5 If it's a ball , It's like this. :

We have to , Have to add HTML, Modify again CSS. And with the help of Calc and CSS Variable , This scene can be simplified a little .

Assuming that only the 3 A ball :

<div class="g-container">
    <div class="g-item" style="--delay: 0"></div>
    <div class="g-item" style="--delay: 1"></div>
    <div class="g-item" style="--delay: 2"></div>
</div>

We go through HTML Of Style label , Pass in --delay Variable , stay CSS Use them directly in :

.g-item {
    animation: rotate 3s infinite linear;
    animation-delay: calc(var(--delay) * -1s);
}
@keyframes rotate {
    to {
        transform: rotate(360deg);
    }
}

And when the animation changes to 5 Ball time , We don't need to modify CSS, Directly modifying HTML that will do , It's like this. :

<div class="g-container">
    <div class="g-item" style="--delay: 0"></div>
    <div class="g-item" style="--delay: 0.6"></div>
    <div class="g-item" style="--delay: 1.2"></div>
    <div class="g-item" style="--delay: 1.8"></div>
    <div class="g-item" style="--delay: 2.4"></div>
</div>

The core CSS Still this sentence , No modification required :

{
    animation-delay: calc(var(--delay) * -1s);
}

complete DEMO, You can poke here :CodePen Demo -- Calc & CSS Variable Demo

calc The default value when matching with custom variables

Or the above Loading Animation effect , If my HTML In the label , One label forgot to fill --delay The value of the , What will happen then ?

It's like this. :

<div class="g-container">
    <div class="g-item" style="--delay: 0"></div>
    <div class="g-item" style="--delay: 0.6"></div>
    <div class="g-item"></div>
    <div class="g-item" style="--delay: 1.8"></div>
    <div class="g-item" style="--delay: 2.4"></div>
</div>
{
    animation-delay: calc(var(--delay) * -1s);
}

because HTML The tag was not passed in --delay Value , And in CSS The corresponding value cannot be found by looking up in the middle , here ,animation-delay: calc(var(--delay) * -1s) This sentence is actually invalid , amount to animation-delay: 0, The effect is the effect of missing a ball :

therefore , Based on this situation , You can use CSS Custom variable var() Of fallback Mechanism :

{
    // (--delay, 1)  Medium  1  It's a fault-tolerant mechanism 
    animation-delay: calc(var(--delay, 1) * -1s);
}

here , If nothing is read --delay value , It will use the default 1 And -1s Carry out operations .

Calc String splicing

Many people are using CSS When , String splicing will try , It's like this. :

<div style="--url: 'bsBD1I.png'"></div>
:root {
    --urlA: 'url(https://s1.ax1x.com/2022/03/07/';
    --urlB: ')';
}
div {
    width: 400px;
    height: 400px;
    background-image: calc(var(--urlA) + var(--url) + var(--urlB));
}

I want to take advantage of calc(var(--urlA) + var(--url) + var(--urlB)) Spell out the complete in background-image Available in URL url(https://s1.ax1x.com/2022/03/07/bsBD1I.png).

However , This is not allowed ( Impossible ).calc Without the ability of string splicing .

The only possible way to complete string splicing is in the pseudo element of the element content Properties of the . But it's not using calc.

Here's an example , This is a error Of :

:root {
    --stringA: '123';
    --stringB: '456';
    --stringC: '789';
}

div::before {
    content: calc(var(--stringA) + var(--stringB) + var(--stringC));
}

here , Unwanted calc, You can add directly with custom variables .

therefore , correct Writing :

:root {
    --stringA: '123';
    --stringB: '456';
    --stringC: '789';
}
div::before {
    content: var(--stringA) + var(--stringB) + var(--stringC);
}

here , The content can be displayed normally :

Just a little bit more ,calc Without the ability of string splicing , The following usage methods are unrecognized wrong Syntax :

.el::before {
  //  String splicing is not supported 
  content: calc("My " + "counter");
}
.el::before {
  //  String multiplication is not supported 
  content: calc("String Repeat 3 times" * 3);
}

min()、max()、clamp()

min()、max()、clamp() Suitable for speaking together . Their functions are related to each other .

  • max(): Select the maximum... From a comma separated list of expressions ( Positive direction ) As the value of the property
  • min(): Select the smallest value from a comma separated list of expressions as the value of the property
  • clamp(): Limit a value between an upper and lower limit , When this value exceeds the range of minimum and maximum , Choose a value between the minimum value and the maximum value to use

Because in reality , The attributes of many elements are not invariable , But according to the context 、 Change with the environment .

For example, such a layout :

<div class="container"></div>
.container {
    height: 100px;
    background: #000;
}

The effect is as follows ,.container Block, which will increase as the screen increases , Always occupy the whole screen :

For a responsive project , We certainly don't want its width to grow all the time , But when a certain threshold is reached , Width has changed from relative units to absolute units , This applies to min(), Simple transformation of the code :

.container {
    width: min(100%, 500px);
    height: 100px;
    background: #000;
}

The width value of the container will be in width: 100% And width: 500px Choose between , Choose the relatively small one .

When the screen width is insufficient 500px When , That is to say width: 100%, conversely , It is shown as width: 500px

Empathy , In a similar scene , We can also use max() From multiple values , Choose a relatively larger value .

min()、max() Support a list of multiple values

min()、max() Support a list of multiple values , for example width: max(1px, 2px, 3px, 50px).

Of course , For the above expression :

width: max(1px, 2px, 3px, 50px) In fact, it is equal to width: 50px. therefore , about min()、max() For the specific use of , It should contain at most one specific absolute unit . otherwise , Such code like the above , Although the syntax supports , But in any case , The calculated values are determined , It doesn't make sense .

coordination calc

min()、max()、clamp() All can cooperate with calc Use it together .

for example :

div {
    width: max(50vw, calc(300px + 10%));
}

under these circumstances ,calc And the brackets of the corresponding package can be omitted , therefore , The above code can be written as :

div {
    width: max(50vw, 300px + 10%);
}

be based on max、min simulation clamp

Now? , There's a scenario like this , If , We need to limit the maximum , You also need to limit the minimum , What shall I do? ?

A scene like this ,** Font size , The minimum is 12px, As the screen gets bigger , Gradually get bigger , But in order to avoid the phenomenon of old people's machines ( As the screen gets bigger , Unlimited increase ), We also need to limit a maximum 20px.

We can use vw To assign dynamic values to Fonts , Suppose at the mobile end , The width of the equipment CSS The pixel is 320px when , The minimum font width of the page is 12px, The conversion vw That is 320 / 100 = 3.2, That is to say 1vw stay The screen width is 320px When , Manifested as 3.2px,12px About equal to 3.75 vw.

meanwhile , We need to limit the maximum font value to 20px, Corresponding CSS as follows :

p {
    font-size: max(12px, min(3.75vw, 20px));
}

Look at the effect :

adopt max()min() In combination with , And match a relative unit vw, We successfully set the upper and lower limits for Fonts , The dynamic change is realized between the upper and lower limits .

Of course , The paragraph above the core max(12px, min(3.75vw, 20px)) It looks a little windy , therefore ,CSS Launched clamp() Simplify this syntax , The following two expressions are equivalent :

p {
    font-size: max(12px, min(3.75vw, 20px));
    //  Equivalent to 
    font-size: clamp(12px, 3.75vw, 20px);
}

clamp()

clamp() The function limits a value between an upper limit and a lower limit , When this value exceeds the range of minimum and maximum , Choose a value between the minimum value and the maximum value to use . It takes three parameters : minimum value 、 Preferred value 、 Maximum .

What's interesting is that ,clamp(MIN, VAL, MAX) In fact, it means max(MIN, min(VAL, MAX)).

Use vw coordination clamp Achieve responsive layout

Let's continue with the above topic .

In the near past , Adaptation of mobile terminal , Use more rem Adaptation scheme , Some ready-made libraries may be used , Be similar to flexible.js、hotcss.js Such as the library .rem One of the big problems of the scheme is that it needs a period of time JavaScript Respond to viewport changes , Reset the root element font-size, also , Use rem More or less hack The feeling of .

At present , Adapt on the mobile end , More highly of us vw pure CSS programme , And rem Similar scheme , Its essence is the equal scaling of the page . One of its problems is , If you just use vw, As the screen gets bigger or smaller , Content elements will keep getting bigger and smaller , This also leads to a big screen , Many elements look too big !

therefore , We need a way to control the maximum 、 The way of minimum threshold , It's like this. :

here ,clamp It can be very useful , Or our above example , This code font-size: clamp(12px, 3.75vw, 20px), You can limit the font to 12px - 20px Within the scope of .

therefore , For mobile pages , All units of length involved , We can all use vw Set it up . And things like Fonts 、 Inside and outside the margin 、 The width should not be scaled exactly , use clamp() Control the maximum and minimum threshold .

stay Modern Fluid Typography Using CSS Clamp In the article , To use clamp() There is a more in-depth discussion on the flow response layout , Those who are interested can read deeply .

To sum up , For mobile pages , We can use vw coordination clamp() The way ,​ Complete the adaptation of the whole mobile terminal layout . Its advantage is :

  • No extra JavaScript The introduction of code , pure CSS Solution
  • It can well control the boundary threshold , Reasonable zoom display

Reverse responsive change

There's another trick , utilize clamp() Fit negative , We can also reverse the operation , Get a bigger screen , The smaller the font, the more responsive the effect is :

p {
    font-size: clamp(20px, -5vw + 96px, 60px);
}

Look at the effect :

This technique is very interesting , because -5vw + 96px The calculated value of will increase as the screen becomes smaller , A reverse font responsive change is realized .

summary

To sum up , Rational use min()、max()、clamp(), It is the focus of building a modern responsive layout , We can say goodbye to traditional needs JavaScript Some auxiliary schemes , be based on CSS These mathematical functions can complete all the demands .

Some very good articles for advanced reading :

Last

Okay , This concludes the article , I hope this article has been helpful :)

Want to Get To the most interesting CSS information , Don't miss my official account -- iCSS Front end anecdotes

More exciting CSS Technical articles summarized in mine Github -- iCSS , Continuous updating , Welcome to point a star Subscribe to the collection .

Any questions or Suggestions , Communicate more , Original article , Writing co., LTD. , Pretty good , If there is anything wrong with the text , All hope to inform .

copyright notice
author[chokcoco],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2022/132/202205111125086221.html

Random recommended