Implementing randomness in CSS using trigonometry

In previous articles I discussed the topic of implementation

Pseudo-randomness in CSS using integer division

and used

simple numbers to create an automatic counter that can generate different values ​​for each object

. Thanks to this, we can calculate pseudo-random values ​​for each element separately.

Despite the reliability of this solution, it also has disadvantages:

  • Division with remainder function is not continuous
  • The method is too complicated: it requires three variables and a definition @property for each random value we want to generate
  • Requires application @propertywhich is not very widely supported yet

Luckily, you can do better! In this article I will propose a more optimal solution based on trigonometry.

A better solution

Since my last research on this topic, there have been some exciting new features in CSS. One of the most fascinating ones is the trigonometric functions. They make it possible to solve many previously impossible problems. They are also the first continuous bounded functions natively supported in CSS, making them an excellent tool for creating pseudo-random generators.

Randomness and pseudo-randomness

Obviously, the solution presented in the article generates only pseudo-random values. All values ​​are calculated using predefined constants. As they say in my

previous article

you can add an additional variable

--seed

and change it outside the system (for example, set it when JavaScript is loaded) so that the result is less deterministic, but CSS does not have any non-deterministic methods. However, this solution should be sufficient to produce acceptable values ​​for animations, positions, and so on. If you wanted to use it to solve your cryptographic functions, you may have chosen the wrong technology in the first place.

Characteristics of the sine function

The sine and cosine functions are interesting for many reasons. They can be very useful in all operations that involve circles and rotations. However, in our case, we can use their properties for other purposes.

Limited function

One of the great properties of sine and cosine is that the resulting values ​​are always limited to an interval between -1 and 1. This means that no matter the magnitude of the value it conveys, the result will always be a value within that interval. After which we can perform a simple normalization to the interval

[0,1]

. Once the values ​​are normalized, we can use them to set any other value using a simple linear mapping.

--x: calc(0.5 + 0.5 * sin(var(--n) * 342.06184 + 23.434));

/* Затем мы можем использовать это следующим образом */
background: rgb(calc(50 + var(--x) * 100), 0, 0);
/* Красный будет находиться в интервале 50-150 */

The code shown above uses my counter

var(--n)

described in my previous article, where I use prime numbers to provide an efficient way to automatically create a counter variable in CSS.

Counting in CSS: Unlock magic of CSS variables

The value is then multiplied and shifted by arbitrary values ​​to create a pseudo-random large number (the values ​​are not particularly important, you can change them to get different results). After this we use the sine function to map it to the interval [-1, 1]. Next, as shown in the animation below, we can display it in the interval [0, 1], applying a simple algebraic transformation. Retrieving a value from an interval [0, 1]we can apply linear mapping to map it to any desired value.

Continuity

Another characteristic of the sine function is continuity. You can study the full formal definition of continuity

Here

, but to understand the principle, imagine that any small changes in the input data of a sine or cosine function result in small changes in the output data. This allows you to ensure that values ​​change gradually as you animate objects, although the system will behave randomly.

Examples

Here are some examples that demonstrate the potential of using trigonometric functions to generate pseudo-random values.

Circle grid

The first example shows the properties of sine in action. The values ​​generated are random, but we can still maintain order and a sense of continuity when animating colors and sizes.

Codepen

The main part of the code is the calculation of the variables x, y, z and w, which describe red, green, blue and width, respectively.

div::before {
  --x: calc(0.5 + 0.5 * sin(4.284 * var(--n)));
  --y: calc(0.5 + 0.5 * sin(7.284 * var(--n)));
  --z: calc(0.5 + 0.5 * sin(4 * var(--n) + 2 * var(--t)));
  --w: calc(0.5 + 0.5 * sin((0.2 * cos(var(--t)/100) + 0.8) * 49.123 * var(--n) + var(--t)));
  
  background: rgb(
    calc(50 +  100 * var(--x)),
    calc(200 + 30 * var(--y)),
    calc(120 + 100 * var(--z))
  );
  width: calc(50% + var(--w)*50%);
}

The last two variables along with our counter

--n

use time variable

--t

which is obtained by performing an animation that gradually changes the variable:

@property --t {
  syntax: '<number>'; /* <- задаётся как тип number, чтобы этот переход работал */
  initial-value: 0;
  inherits: true;
}
:root {
  --t: 0;
}

@keyframes timeOn {
  50% {--t: 30}
}

html {
  animation: 30s timeOn infinite linear;
}

This is the only part of the code where it is used

@property

. To make this work in all browsers, we can simply update this variable in JavaScript without losing the ability to calculate everything else in regular CSS.

Stains

Randomness can also be used with SVG elements, which when combined with SVG filters makes it a powerful tool. The demo below was inspired by

awesome article from CSS-Tricks called The Gooey Effect

.

Codepen

The position of each individual spot is determined using a simple formula. The only difference is that we use cx, cy, r and fill to style them because they are SVG elements.

.blobs > circle {
  --x: calc(sin(var(--t) + var(--n) * 74.543 + 432.43312));
  --y: calc(cos(var(--t) + var(--n) * 2.34 + 1.432));
  --v: calc(0.5 + 0.5 * sin(var(--n) * var(--n) * 4.343 + 2.673));
  
  cx: calc(10vw + var(--x) * 80vw);
  cy: calc(10vh + var(--y) * 80vh);
  r: calc(var(--v) * 5vw + 1vw);
}

To achieve the sticky effect we use the following SVG filter:

<filter id="goo">
    <feGaussianBlur in="SourceGraphic" result="blur" stdDeviation="15" />
    <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 22 -11" result="goo" />
    <feBlend in2="goo" in="SourceGraphic" result="mix" />
</filter>

Memphis style pattern

The latest demo is an updated version

example

, which I used in a previous attempt at achieving randomness in CSS when I used the division operator with a remainder. In my new solution, calculations are much easier to understand and change.

Memphis Pattern using Trigonometry randomness

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *