3
头图

Recently, there is a very exciting news that CSS will natively support nesting - Agenda+ to publish FPWD of Nesting , indicating that the CSS nesting specification is about to enter the FWPD phase of the specification.

The current corresponding specification is - CSS Nesting Module .

With the large-scale compatibility of CSS Variables, CSS is about to support nesting, and some core functions of preprocessors have been natively supported by CSS. Does this mean that preprocessors such as SASS/LESS are useless? ? About to be eliminated?

Several stages of specification

First, let’s briefly introduce the stages that a standard will go through from its proposal to its implementation:

  1. Editor's Draft (ED)
  2. Working Draft (WD)
  3. Transition-Last Call Working Draft (LCWD)
  4. Candidate Recommendation (CR)
  5. Transition-Proposed Recommendations (PR)
  6. Recommendation (REC)

As mentioned above, it is about to enter FPWD, but it is in the second phase of the specification WD stage. FPWD represents the First Public Working Draft (FPWD). There will be several working drafts following the FPWD, which will deal with feedback from the wider community within the CSSWG and outside the group. Improve the standard design.

In other words, at present, even if the subsequent process goes smoothly, it will be a long time before the browser implements the specification on a large scale until it can be implemented.

In addition, I think SASS\LESS and other preprocessors have some interesting functions (functions), which are still lacking even after native CSS supports custom attributes and nesting. I will briefly list my views.

for() loop function

Currently, native CSS still does not support loop functions.

But in fact, in the preprocessor, loop is still a more commonly used function. Consider the following layout:

ul Here are more li , the height of each li incremental 20px , one by one, of course, can write, but with circulation fact can greatly reduce the workload:

<ul>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
</ul>

Without the preprocessor, our CSS might look like this:

ul {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
}
li {
    width: 50px;
    background: #000;
}
li:nth-child(1) {
    height: 20px;
}
li:nth-child(2) {
    height: 40px;
}
// ... 3~9
li:nth-child(10) {
    height: 200px;
}

If you use the SASS preprocessor, it can be simplified to:

ul {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
}
li {
    width: 50px;
    background: #000;
}
@for $i from 1 through 10 {
    li:nth-child(#{$i}) {
        height: calc(#{$i} * 20px);
    }
}

Of course, in addition, in a lot of complex CSS animation effects, looping is a very, very commonly used function.

For example, for some particle animations, we usually need to manipulate 50-100 particles, that is, 50-100 div styles, or even more. If there is no loop, the efficiency of writing one by one will be greatly reduced.

Show some effects achieved by using the preprocessor loop function

Below I briefly list some of the animation effects that I have implemented and applied the loop function of the CSS preprocessor.

Like the above flame effect achieved using pure CSS, the dynamic burning effect of the flame. In fact, it is achieved through the movement of a large number of fine particles with filters.

A fragment of the loop function of SASS is used:

@for $i from 1 to 200 {
    .g-ball:nth-child(#{$i}) {
        $width: #{random(50)}px;
        
        width: $width;
        height: $width;
        left: calc(#{(random(70))}px - 55px);
    }
    
    .g-ball:nth-child(#{$i}) {
        animation: movetop 1s linear -#{random(3000)/1000}s infinite;
    }
}

Huh, the above loop is repeated 200 times. If you really want to write one by one, the workload is still very huge. For the complete code of the above effect, you can click here:

CodePen Demo -- CSS Candles

if() conditional statement

The next one is the if() conditional statement.

In fact, there is a very similar conditional statement in CSS, that is, the media query @media and the feature detection @supports statement. At present, some of the similar conditional selection methods supported in CSS are as follows:

@support conditional statement

CSS @supports implements feature detection through CSS syntax, and writes the CSS statement if the feature detection passes the desired implementation in the internal CSS block.

div {
    position:fixed;
}
 
@supports (position:sticky) {
    div {
        position:sticky;
    }
}

The above CSS statement means that if the client supports position:sticky , then position:sticky is used, otherwise, it is position:fixed .

For an in-depth explanation of CSS feature detection, you can read this article of depth discussion of CSS feature detection @supports and Modernizr

@media conditional statement

Another common conditional statement is media query, which everyone is familiar with.

If the current equipment satisfies one of the conditions, how and how.

article {
  padding: 4rem;
}
@media screen and (min-width: 900px) {
  article {
    padding: 1rem 3rem;
  }
}

Well, and the above two conditional statements can be nested with each other:

@supports (display: flex) {
  @media screen and (min-width: 900px) {
    article {
      display: flex;
    }
  }
}

However, the above two statements if()

A long time ago, there was a voice in the community ( css-values-if() function if() should be implemented in the CSS specification, similar to this:

.foo {
  --calc: calc(10 * (1vw + 1vh) / 2);
  font-size: if(var(--calc) < 12px, 12px, var(--calc));
}

You can see that this statement if(var(--calc) < 12px, 12px, var(--calc)) similar to a ternary statement, which is relatively easy to understand.

However, the reason why the above conditional statement has not been supported can be seen scss-values-if() function

The reason is that CSS has been trying to avoid arbitrary dependencies among attributes. In CSS, there are some implicit dependency between the property itself, such as em unit length by the parent element font-size impact, if the author can add any dependencies (via if () conditional statement), it will cause some problems.

The original text is: this, unfortunately, means we're adding arbitrary dependencies between properties, something we've avoided doing so far because it's, in general, unresolvable.
Custom properties can arbitrarily refer to each other, but they're limited in what they can do, and have a somewhat reasonable "just become invalid" behavior when we notice a cycle. Cycles are more difficult to determine for arbitrary CSS, and can happen much more easily, because there are a number of existing, implicit between-property dependencies. For example, anything that takes a length relies on font-size (due to em), and so you can't have a value in font-size that refers to a property that takes a length (so no adjusting font-size to scale with width!). We add new dependencies of this sort over time (such as adding the lh unit, which induces a dependency on line-height); if authors could add arbitrary dependencies, we'd be unable to add new implicit ones for fear of breaking existing content (by forming cycles that were previous valid and non-cyclic).

Therefore, the direct if() statement in CSS has not been implemented.

if() statement in preprocessors such as SASS

Finally, let's take a look at if() in the preprocessor. Since preprocessors such as SASS will eventually be compiled into CSS files, if() is actually not very commonly used. Because if() SASS can't realize the function similar to font-size: if(var(--calc) < 12px, 12px, var(--calc)) mentioned above.

In SASS, I think the most commonly used if() may be this scenario:

@mixin triangle($size, $color, $direction) {
  height: 0;
  width: 0;

  border-color: transparent;
  border-style: solid;
  border-width: $size;

  @if $direction == up {
    border-bottom-color: $color;
  } @else if $direction == right {
    border-left-color: $color;
  } @else if $direction == down {
    border-top-color: $color;
  } @else if $direction == left {
    border-right-color: $color;
  } @else {
    @error "Unknown direction #{$direction}.";
  }
}

.next {
  @include triangle(5px, black, right);
}

The above code is an encapsulation of the CSS implementation of triangles. Through the passed parameters, triangles of different directions, colors, and sizes are realized. That is, if() in the preprocessor, which more completes the encapsulation of some functions and facilitates reuse.

The actual above code will be compiled into:

.next {
  height: 0;
  width: 0;
  border-color: transparent;
  border-style: solid;
  border-width: 5px;
  border-left-color: black;
}

Random() random function

OK, the next one is a random function, which is my most commonly used function in SASS and other preprocessors. Currently, native CSS does not support arbitrary forms of randomness.

In CSS animation effects, we don’t want many factors to be static. What we hope is that we set a basic rule for the value of some properties and get them in a range, so that every refresh can produce a different Effect.

The most common ones are different colors, different lengths, different numbers, etc.

For example, the following effect achieved using CSS: Summer sunset picture .

Through random, we can get different height/width, different positions of div blocks each time we refresh, and use random features to draw different renderings:

DEMO - Summer sunset picture

Currently, native CSS does not support arbitrary forms of randomness. Using the preprocessor, you can only write random functions before compilation. Some of the more commonly used random functions in SASS are written:

$r: random(100);

random() is a function supported by SASS. The above $r can get a random integer from 0 to 100.

Using random() , you can encapsulate various random functions, such as random colors:

@function randomNum($max, $min: 0, $u: 1) {
    @return ($min + random($max)) * $u;
}

@function randomColor() {
    @return rgb(randomNum(255), randomNum(255), randomNum(255));
}

div {
    background: randomColor();
}

Some thoughts on the implementation of random() in native CSS

The following are some thoughts from the community on the implementation of the random() function in native CSS. If you are interested, you can rush:

[[css-values] random() function](https://github.com/w3c/csswg-drafts/issues/2826)

Simply move some of the more interesting points.

Assuming that CSS random() implements the 06111ddb12e1e5 function, for example, the following is written:

<p class="foo">123</p>
<p class="foo">456</p>
<p class="foo">789</p>
.foo:hover { 
    color: rgb(random(0, 255), 0, 0); 
}

Assuming that ramdom() is a random function implemented by native CSS, there are some things that need to be solved or recognized by everyone:

  1. random(0, 255) the value of 06111ddb12e27e determined, every time CSS is parsed, or every time it is triggered by an application?
  2. For the above DEMO, are the .foo of color three 06111ddb12e2c0 the same?
  3. For repeated hover , cancel the hover state, random(0, 255) the value of 06111ddb12e308 change?

The above problem can be attributed to if CSS natively supports randomness, the persistence and update of random values are problems that must be solved. In short, it seems that the possibility of CSS native support for randomness is still very high in the future.

Tool functions: color functions, mathematical functions

Finally, let's take a look at some interesting tool functions. Currently, native CSS does not support some more complex color functions and mathematical functions. But the preprocessor comes with these functions.

In my previous article on shadows- CSS shadowing techniques and details that you don't know, I introduced a way to use multiple shadows to achieve three-dimensional shadows. For example, we want to achieve the following effect:

The color change of the shadow is based on the color function of SASS:

  • fade-out Change the transparency of the color to make the color more transparent
  • desaturate Change the saturation value of the color to make the color less saturated
@function makelongrightshadow($color) {
    $val: 0px 0px $color;

    @for $i from 1 through 50 {
        $color: fade-out(desaturate($color, 1%), .02);
        $val: #{$val}, #{$i}px #{$i}px #{$color};
    }

    @return $val;
}

p{
   text-shadow: makelongrightshadow(hsla(14, 100%, 30%, 1));
}

Of course, in addition to the above two color functions, SASS also provides a lot of similar color-related functions, you can look here: Sass basics-color function .

In addition to colors, mathematical functions are often used in CSS effects.

In this article- using trigonometric functions in CSS to draw curve graphics and display animation , I specifically talked about how to use SASS and other preprocessors to achieve trigonometric function to achieve curve lines and achieve some interesting effects. Like this:

Of course, SASS does not currently support trigonometric functions, but we can use SASS function to implement a set of trigonometric function codes:

@function fact($number) {
    $value: 1;
    @if $number>0 {
        @for $i from 1 through $number {
            $value: $value * $i;
        }
    }
    @return $value;
}

@function pow($number, $exp) {
    $value: 1;
    @if $exp>0 {
        @for $i from 1 through $exp {
            $value: $value * $number;
        }
    }
    @else if $exp < 0 {
        @for $i from 1 through -$exp {
            $value: $value / $number;
        }
    }
    @return $value;
}

@function rad($angle) {
    $unit: unit($angle);
    $unitless: $angle / ($angle * 0 + 1);
    @if $unit==deg {
        $unitless: $unitless / 180 * pi();
    }
    @return $unitless;
}

@function pi() {
    @return 3.14159265359;
}

@function sin($angle) {
    $sin: 0;
    $angle: rad($angle);
    // Iterate a bunch of times.
    @for $i from 0 through 20 {
        $sin: $sin + pow(-1, $i) * pow($angle, (2 * $i + 1)) / fact(2 * $i + 1);
    }
    @return $sin;
}

@function cos($angle) {
    $cos: 0;
    $angle: rad($angle);
    // Iterate a bunch of times.
    @for $i from 0 through 20 {
        $cos: $cos + pow(-1, $i) * pow($angle, 2 * $i) / fact(2 * $i);
    }
    @return $cos;
}

@function tan($angle) {
    @return sin($angle) / cos($angle);
}

As far as the current native CSS is concerned, a lot of efforts have been made in terms of mathematical functions, such as:

  • Basic calculation function calc()
  • Comparison function max() , min() , clamp()

When the compatibility has been gradually rolled out, you can start to use it on a large scale, and similar to

  • Exponential function pow() , sqrt() , hypot() , log() , exp()
  • Trigonometric functions sin() , con() , tan()
  • Step function round() , mod() , rem() etc.

It is also in the specification 16111ddb12e797 CSS Values and Units Module Level 4 . I believe it will gradually land in the near future.

For some discussions on mathematical functions in the community, you can also check here if you are interested: Mathematical Expressions

in conclusion

Well, to sum up, for now, I think SASS/LESS and other preprocessors are still useful in many aspects. Before some of the above functions are fully implemented in native CSS, preprocessors can be used to a certain extent. To make up for the shortcomings of CSS.

Moreover, in addition to the above-mentioned functions and functions that I personally think are more important and interesting, some other core functions of the preprocessor, such as extend, mixins, etc., can also effectively improve the efficiency of development.

So, for some time to come, I think the preprocessor can still coexist friendly with CSS~

at last

Okay, this concludes this article, I hope it helps you :)

If you want to get the most interesting CSS information, don't miss my account - 16111ddb12e876 iCSS front-end interesting 16111ddb12e878 😄

For more exciting CSS effects, please pay attention to my CSS inspiration

More wonderful CSS technical articles are summarized in my Github - iCSS , which will be updated continuously. Welcome to click a star to subscribe to the collection.

If you have any questions or suggestions, you can exchange more, original articles, limited writing style, and lack of knowledge. If there are any irregularities in the article, please let me know.


chokcoco
12.3k 声望18.5k 粉丝