Can a Recursive Variable Be Expressed in CSS

Can a recursive variable be expressed in css?

You can use two CSS variables to simulate the recursive behavior and avoid cycle dependency.

Here is an example:

body {  --x: 10;}.y {  --y: calc(var(--x) + 1);}.x{  --x: calc(var(--y) + 1);}.result {  border-right:calc(1px * var(--y)) solid red;  border-left:calc(1px * var(--x)) solid green;  height:50px;}
<body>  <div class="y">    <div class="x">      <div class="y">        <div class="x">          <div class="y">            <div class="x">              <div class="y result">
</div> </div> </div> </div> </div> </div> </div></body>

Can a CSS variable be used in the recalculation of its own value?

A quick check on the MDN docs unfortunately did not shine light on this. So unless you're willing to dive into the spec, here's a quick test:

:root {  --x: 4em;}
.class2 { --x: calc(0.5 * var(--x)); font-size: var(--x);}
<div class="class2">  Test - doesn't work as intended</div>

how to use recursive definition in less?

According to Witcher42 you can use Variable Names.

@index: 2;
@theme1-color: #2d8cf0, #19be6b, #515a6e, #363e4f, rgba(255, 255, 255, 0.7);
@theme2-color: #2d8cf0, #89bf04, #89bf04, #89bf04, #89bf04;

@primary-color: "theme@{index}-color";

a {
color: extract(@@primary-color, 1);
}

Generate headings size with a recursive function in SASS

After some research, I figured out I wasn't digging in the right direction. I extracted the factor the value of x from the equation and concentrated myself on the factor.

@function calculateFontSize($n) {
@if $n == 1 {
@return $headingSizeRatio;
}
@else {
@return $headingSizeRatio * calculateFontSize($n - 1);
}
}

@for $i from 1 through 6 {
h#{7 - $i} {
font-size: $base-font-size * calculateFontSize($i);
}
}

It solved my issue. :)

Recursive LESS: expected expression

You have your = and > the wrong way round

Less Mixin Guards Documentation

"The full list of comparison operators usable in guards are: > >= = =< <. Additionally, the keyword true is the only truthy value, making these two mixins equivalent:"

.loop(@index, @n) when (@index <= @n)

should be

.loop(@index, @n) when (@index =< @n)

how to create a repeating rainbow of nested divs is CSS

If you can alternate the nesting using different elements you can try something like below using CSS variables. We need different elements to be able to increment a variable on each level combining two variables. (related: Can a recursive variable be expressed in css?)

I considered 4 colors but you can easily scale to any number:

:root {  --p:0;  --x:0;}
.first,.first span,.first div{ padding:10px; border:5px solid transparent; background: linear-gradient(white,white) padding-box, /* Color only the padding box*/ /* N = 4*/ repeating-linear-gradient( red 0 calc(100%/4), blue calc(1*100%/4) calc(2*100%/4), green calc(2*100%/4) calc(3*100%/4), purple calc(3*100%/4) calc(4*100%/4)) 0 calc(var(--p)*100%/3)/ /* 0 var(--p)*100%/(N-1) */ 100% 400% /* Width:100% height:N*100% */ border-box; /* Color the border area */}.first span { --p:calc(var(--x) + 1); display:block;}.first div { --x:calc(var(--p) + 1); background-position:0 calc(var(--x)*100%/3); /* 0 var(--x)*100%(N-1) */}
<div class="first">  <span>    <div>     <span>      <div>      <span>       <div>        <span>          <div>          </div>        </span>       </div>     </span>    </div>   </span>  </div> </span></div>

Select recursive :last-child. Possible?

No, unfortunately that's just about the only way to do it without modifying the HTML.

There has been at least one request for recursive versions of the :first-child and :last-child pseudo-classes, but it doesn't seem to have gained much favor. Notice it suggests nesting and repeating the pseudo-classes in the same way as in your question:

Currently, AFAIK, we can only match children up to some exact nesting level known in advance (3 in the example below):

.container > :first-child,
.container > :first-child > :first-child,
.container > :first-child > :first-child > :first-child {}

We cannot use just :first-child context selector since it would also select first children of blocks that are not first children themselves.

So we need a sort of recursive selector that matches not just first of last child, but recursively matches all first-most and last-most elements regardless of their nesting level.

How should I reset a less variable using its own value

The above code would result in the following error being thrown on compilation:

NameError: Recursive variable definition for @navbar-default-bg

Recursive variable definitions won't work in Less because of the way Less does lazy loading of the variables. This would mean that the last definition for that variable (within the same scope) will be the one that is used. In your example it would result in an error because the variable cannot reference itself (to get its originally declared value).

Quoting Less Website:

When defining a variable twice, the last definition of the variable is used, searching from the current scope upwards. This is similar to css itself where the last property inside a definition is used to determine the value.


The best way to create a rgba color value from a given rgb color is to use the built-in fade function (like shown below). But note that, the value cannot be assigned back to the same variable.

@navbar-default-bg: rgb(255, 0, 0);

#sample{
color: fade(@navbar-default-bg, 90%);
}

The above Less code when compiled would produce the following CSS output:

#sample {
color: rgba(255, 0, 0, 0.9);
}

Of-course, you could do something like mentioned in this answer to sort of achieve a reset effect but my personal opinion is that it is way too much complexity and effort for something that can probably be achieved in a different way.

Here is a sample implementation of the method mentioned in that answer adapted to suit this question. (Code is added below just in-case the link becomes inactive.)

.init() {
.inc-impl(rgb(255, 0, 0), 0.1); // set initial value
}
.init();
.inc-impl(@new, @i) {
.redefine() {
@color: @new;
@alpha: @i;
}
}
.someSelector(@name) {
.redefine(); // this sets the value of counter for this call only
.inc-impl(rgba(red(@color), green(@color), blue(@color), @alpha), (@alpha + 0.1)); // this sets the value of counter for the next call
@className: ~"@{name}";
.@{className}
{
color: @color;
}
}
.someSelector("nameOfClass");
.someSelector("nameOfClass1");
.someSelector("nameOfClass2");


Related Topics



Leave a reply



Submit