Nesting Agenda+ to Publish FPWD of Nesting Agenda+ to Publish FPWD of Nesting Agenda+ to publish FPWD of Nesting

Nesting Module = — CSS Nesting Module

With CSS Variable compatibility on a large scale, CSS is now going to support nesting, and some core functions of the preprocessor are already supported natively by CSS. Does this mean that preprocessors like SASS/LESS are no longer available? About to be eliminated?

Several stages of specification

First of all, let’s briefly introduce some stages that a specification will go through from its proposal to implementation:

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

As mentioned above, we are about to enter the FPWD, but we are only in the second phase of the specification, the WD phase. FPWD stands for First Public Working Draft (FPWD). The FPWD will be followed by several working drafts that will deal with feedback from the wider community, both within CSSWG and outside the group. Perfect the design of the specification.

That said, at this point, even if the rest of the process goes well, it’s going to be a long time before browsers can implement the specification on a large scale.

In addition, I think there are some interesting features of preprocessors such as SASS\LESS that are missing even with native CSS support for custom properties and nesting. Here are my thoughts.

For () loop function

Currently, native CSS does not support looping functions.

But loops are a common feature in preprocessors. Consider the following layout:

Ul has more than one li under it, and each li’s height is increased by 20px.

<ul>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
</ul>
Copy the code

Without a 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;
}
Copy the code

If the SASS preprocessor is used, it can be simplified as:

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); }}Copy the code

Beyond that, of course, looping is a very, very common feature in a lot of complex CSS animation effects.

For example, with particle animations, we might normally have to manipulate 50, 100 particles, which is 50, 100 divs, or more. Without loops, it would be very inefficient to write one by one.

Using the preprocessor loop function to achieve some effects

Here is a brief list of some animations I’ve implemented using the CSS preprocessor loop feature.

Like the above flame effect using pure CSS, where the flame burns dynamically. It’s actually a lot of tiny particles moving together with a filter.

A fragment of SASS’s looping function 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; }}Copy the code

Well, that’s 200 cycles, which is a huge amount of work to do. The full code for the above effects you can poke here:

CodePen Demo — CSS Candles

If () conditional statement

The next one is the if() condition.

There is a class of conditional statements that are very similar to those in CSS: media query @media and feature check @supports. Some of the conditional statements that are currently supported in CSS are:

@support conditional statement

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

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

Position :sticky if the client supports position:sticky, position:fixed otherwise.

For an in-depth look at CSS feature detection, you can check out my post: An In-depth look at CSS feature detection @ Supports and Modernizr

@media conditional statement

Another common conditional statement is the media query, which you are familiar with.

If the current device meets a certain condition, then so be it.

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

Well, also, the above two conditional statements can be nested within each other:

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

After all, these are not exactly the if() statements we’d expect.

A long time ago, the community had a sound (css-values-if () function), proposing that the CSS specification implement if() conditional statements like this:

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

If (var(–calc) < 12px, 12px, var(–calc)) is similar to a ternary statement, which makes sense.

However, we can see why the above conditional statement has not been supported in scss-scss-scs-if () function.

The reason is that CSS is trying to avoid creating arbitrary dependencies in properties. In CSS, there are implicit dependencies between properties, such as em unit length, which is affected by the font-size of the parent element. If authors can add arbitrary dependencies (via the if() condition), this can cause problems.

The original 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).

So, the direct if() statement in CSS has never been implemented.

SASS and other preprocessorsif()statements

Finally, let’s take a look at the use of if() in preprocessors. Since preprocessors like SASS ultimately compile into CSS files, if() is not often used. Font: if(var(–calc) < 12px, 12px, var(–calc));

In SASS, I think the most common if() is probably 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);
}
Copy the code

The above code is a package of CSS to achieve the triangle, through the passed in parameters, different directions, colors, sizes of the triangle. That is, if() in the preprocessor, more to complete the encapsulation of some functions, convenient reuse.

In fact, the above code will compile to:

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

Random() Random function

OK, here’s the random function, which I personally use most often in preprocessors like SASS. Currently native CSS does not support any form of randomness.

In CSS animation, there are a lot of factors that we don’t want to be fixed. What we want is that the values of some properties are generated by setting a base rule, a range, so that each refresh has a different effect.

The most common ones are different colors, different lengths, different quantities, and so on.

Take the following CSS effect: a summer sunset.

We can get div blocks with different heights/widths and positions every time we refresh by randomness, and draw different renderings by randomness:

DEMO – summer sunsets

Currently native CSS does not support any form of randomness. Using the preprocessor, you can only write random functions before compiling.

$r: random(100);
Copy the code

Random () is a function supported by SASS, and the above $r will yield a random integer ranging from 0 to 100.

Using random(), we 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(a); }Copy the code

Some thoughts on the native CSS implementation of Random ()

Here are some of the community’s thoughts on implementing the random() function in native CSS:

[css-values] random() function

Simply move on to some of the more interesting ideas.

Suppose CSS implements the random() function natively, such as this:

<p class="foo">123</p>
<p class="foo">456</p>
<p class="foo">789</p>
Copy the code
.foo:hover { 
    color: rgb(random(0.255), 0.0); 
}
Copy the code

Assuming that ramdom() is a random function implemented in native CSS, there are a few things that need to be addressed or agreed upon:

  1. random(0, 255)When is the value determined, each time the CSS is parsed, or each time the application is triggered?
  2. For the above DEMO, three.foocolorAre the values the same?
  3. For repeatedhoverTo cancelhoverState,random(0, 255)Will the value of change?

The above problem can be attributed to the fact that if CSS natively supports randomness, persistence and updating of random values are issues that must be addressed. Overall, it looks like the future of CSS native support is likely to be random.

Tool function: color function, mathematical function

Finally, let’s look at some interesting utility functions. Currently native CSS does not support some of the more complex color functions and mathematical functions. But the preprocessor comes with these functions.

In my previous article on Shadows — CSS Shading Tips and Details that you didn’t know about, I introduced the use of multiple shadows to achieve a three-dimensional shadow effect. For example, we want to achieve the following effect:

The color of the shadows is changed by SASS’s color function:

  • fade-outChange the color transparency to make the color more transparent
  • desaturateChange the saturation value of the color to make it 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));
}
Copy the code

Of course, in addition to the above two color functions, SASS provides a number of similar color related functions, as shown here: SASS Basics – Color functions.

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

In this article — Using trigonometric functions to draw curves and display animations in CSS, I specifically talk about how to use the trigonometric functions of SASS and other preprocessors to create curves and 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 functions:

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

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

@function rad($angle) {
    $unit: unit($angle);
    $unitless: $angle / ($angle * 0 + 1);
    @if $unit==deg {
        $unitless: $unitless / 180 * pi(a); }@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);
}
Copy the code

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

  • Basic operation functioncalc()
  • The comparison functionmax(),min(),clamp()

As the compatibility has gradually rolled out, it can start to be used on a large scale, and similar to

  • Exponential functionpow(),sqrt(),hypot(),log(),exp()
  • Trigonometric functionssin(),con(),tan()
  • Step functionround(),mod(),rem()

It is also mentioned in CSS Values and Units Module Level 4 and will be implemented in the near future.

For a community discussion of Mathematical functions, you can also see here: Mathematical Expressions

To summarize

All right, so to sum up, for now, I think there are a number of ways in which SASS/LESS and other preprocessors can be used to make up for some of the disadvantages of native CSS until some of the above features are fully implemented.

In addition, in addition to the above mentioned functions and functions that I personally think are 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 expect the preprocessor to coexist nicely with CSS

The last

Ok, this article is over, hope to help you 🙂

Want to Get the most interesting CSS information, do not miss my public number – iCSS front-end interesting 😄

More wonderful CSS effects can pay attention to my CSS inspiration

More exciting CSS technical articles are summarized in my Github – iCSS, continue to update, welcome to click the star subscription favorites.

If there are any questions or suggestions, you can communicate more, original article, writing style is limited, talent is shallow, if there is something wrong in the article, hope to inform.