# Build Complex CSS Transitions using Custom Properties and cubic-bezier()

This time, `@property` Features. Currently only supported in Chrome-based browsers, but you can still try it out to show how to do it and use it to create complex animations as well.

It is highly recommended that you read the previous article to refer to some of the concepts discussed in detail here. Also note that the demos in this article are most often viewed in Chromium-based browsers. `@property` Support is still limited.

Click the button (multiple times) to see the “magic” curve you get. It may seem trivial at first glance, as you can achieve such an effect with a few complex keyframes. But the secret is that there are no keyframes there! The animation is performed using only transitions.

That’s amazing? And this is just the beginning, so let’s dig into it!

### main idea

The trick in the previous example relies on the following code.

``````@property --d1 {
syntax: '<number>';
inherits: false;
initial-value: 0;
}
@property --d2 {
syntax: '<number>';
inherits: false;
initial-value: 0;
}

.box {
top: calc((var(--d1) + var(--d2)) * 1%);
transition:
--d1 1s cubic-bezier(0.7, 1200, 0.3, -1200),
--d2 1s cubic-bezier(0.5, 1200, 0.5, -1200);
}
.box:hover {
--d1: 0.2;
--d1: -0.2;
}``````

It defines two custom properties. `--d1` And `--d2`..Then declare `top` Properties `.box` An element that uses the sum of both of these properties.Nothing is overly complicated yet — just `calc()` Applies to two variables.

The two properties are defined as `<number>` Then multiply those values ​​by 1% and convert them to percentages.These can be defined as `<percentage>` Immediately to avoid multiplication. However, I chose numbers instead to give them more flexibility to perform more complex operations later.

Note that we apply different transitions to each variable.More precisely, different `timing-function` In the same period.Actually not Sine curve For both variables, this is a deep dive in the previous article.

From there, the property value changes if: `.box` Is hovered and the animation is triggered. But why do you get the results you saw in the demo?

It’s all about math. Add two functions to create a third function.for `--d1`, There is a function (let’s call it F1).for `--d2` , There is another one (let’s call it F2). In other words `top` It is F1 + F2.

An example to better explain:

The first two transitions show each variable individually. The third is the sum of them. At each step of the animation, suppose you want to get the values ​​of both variables and sum them up to get each point along the final curve.

Let’s try another example:

This time, I combined two parabolas … well, I don’t know the name, but it’s another complicated curve.

This trick is not limited to parabolas and sinusoids. It works with all kinds of timing functions, even if the result is not always a complex curve.

this time:

• `--d1` Go from `0` To `30` When `ease-in` Timing function
• `--d2` Go from `0` To `-20` When `ease-out` Timing function

result?The· `top` value is `0` To `10` (((`30-20`) Custom timing function (total of) `ease-in` And `ease-out`).

In this case, no complex migration has occurred. This is to explain the fact that it is a general idea, not just limited to: `cubic-bezier()`..

I think it’s time for an interactive demo.

Here are some examples I made:

As you can see, you can combine two different timing functions ( `cubic-bezier()` ) Create a third one that is complex enough to achieve a flashy transition. Unlimited combinations (and possibilities)!

In that last example, I wanted to show how adding two opposite functions would give the logical result of a constant function (no transitions). Therefore, a flat line.

Did you think it would stop at just two variables? Certainly not!You can extend the logic as follows `N` variable. there is no limit. Define each with a timing function and add them up.

Example with 3 variables:

In most cases, two variables are enough to create a flashy curve, but it’s useful to know that you can extend the trick to more variables.

### Can variables be submitted, multiplied or divided?

of course! You can extend the same idea to consider more operations. You can add, subtract, multiply, divide, and even perform complex formulas between variables.

Here we are multiplying the values.

You can also use a single variable and multiply it alone to get a quadratic function.

Let’s introduce and add more fun to it `min()`/`max()` To simulate `abs()` function:

Note that the second box will never be higher than the center point of the y-axis. `top` Is always a positive value. (I added `margin-top` Make the center of the box a 0 reference. )

Not all calculations go into it, but you can imagine the possibility of creating timing functions of all kinds. Simply use one variable or combine multiple variables to find the right expression.

The first code can be generalized.

``````@property --d1 { /* we do the same for d2 .. dn */
syntax: '<number>';
inherits: false;
initial-value: i1; /* the initial value can be different for each variable */
}

.box {
--duration: 1s; /* the same duration for all */
property: calc(f(var(--d1),var(--d2), .. ,var(--dn))*[1UNIT]);
transition:
--d1 var(--duration) cubic-bezier( ... ),
--d2 var(--duration) cubic-bezier( ... ),
/* .. */
--dn var(--duration) cubic-bezier( ... );
}
.box:hover {
--d1:f1;
--d2:f2;
/* .. */
--dn:f3;
}``````

This is pseudo code to explain the logic.

1. We are using `@property` Define custom properties for numbers, each with an initial value.
2. Each variable has its own timing function, but the duration is the same.
3. We define `f` A function that is an expression used between variables. This function provides a number to use to multiply the associated units.This is done on all `calc()` Applies to properties.
4. Updates the value of each variable when hovering (or toggled, etc.).

Given this, the property transitions from `f(i1,i2,…,in)` To `f(f1,f2,..,fn)` With custom timing function.

### Chain of timing functions

By combining basic timing functions, it is now possible to create complex timing functions. Let’s try another idea that allows you to use more complex timing functions. Chain timing functions..

The trick is to use to perform the transitions in sequence. `transition-delay` Property. Let’s look back at the interactive demo and apply a delay to one of the variables.

I’m still chaining the timing functions, not adding them together aother How to create more complex timing functions! Mathematically it’s still total, but the transitions don’t run at the same time, so we use constants to sum the functions and simulate the chain.

Imagine the case now `N` A variable that is gradually delayed.Not only can you create complex transitions this way, but you have enough flexibility to build complex transitions. Timeline..

This is an interesting hover effect created using that technique.

There are no keyframes there. Small action scenes are completely created using a single element and CSS transitions.

Here’s a realistic pendulum animation using the same idea:

Or what about a ball that bounces naturally?

Or a ball that rolls along a curve:

You see? I created a complex animation with no keyframes in my code.

### That’s it!

We would appreciate it if you could remove three important points from this article and the previous one.

1. Can be used to get parabolas and sine curves `cubic-bezier()` This allows you to create complex transitions without keyframes.
2. You can create more curves by combining different timing functions with custom properties. `calc()`..
3. You can use to chain curves `transition-delay` Build a complex timeline.

Thanks to these three features, there are no restrictions on creating complex animations.
{"ft_lang_label":"__label__en","ft_lang_prob":0.82855,"math_prob":0.95089376,"size":8046,"snap":"2021-43-2021-49","text_gpt3_token_len":1848,"char_repetition_ratio":0.14299925,"word_repetition_ratio":0.0067264573,"special_character_ratio":0.24074075,"punctuation_ratio":0.1504914,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.9651479,"pos_list":[0,1,2,3,4],"im_url_duplicate_count":[null,null,null,3,null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2021-10-19T03:16:53Z\",\"WARC-Record-ID\":\"<urn:uuid:7e9974d9-3d7d-4068-bf3c-414b4afd728f>\",\"Content-Length\":\"76746\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:822c46a6-439e-4404-83f1-b8e0c3789f25>\",\"WARC-Concurrent-To\":\"<urn:uuid:cd1a5a1a-1962-4d3b-9ea0-d9aed6df14b5>\",\"WARC-IP-Address\":\"104.21.83.91\",\"WARC-Target-URI\":\"https://programmingshots.com/build-complex-css-transitions-using-custom-properties-and-cubic-bezier/\",\"WARC-Payload-Digest\":\"sha1:5UDGTKJNYKVOR47ML55XZGWJZU6COYRL\",\"WARC-Block-Digest\":\"sha1:5AY3OMWKS7FPEHSNL6ZMQKMZDSD5T3GY\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2021/CC-MAIN-2021-43/CC-MAIN-2021-43_segments_1634323585231.62_warc_CC-MAIN-20211019012407-20211019042407-00431.warc.gz\"}"}