Can you do a javascript for loop inside of LESS css?
I will recommend to checkout Twitter Bootsrap. They are building their grid system that way. They loop, with recursion, in a less mixin, instead of typing every class they need.
The interesting part is in mixins.less file, in the less directory, below "// The Grid" comment (line 516). The interesting portion is:
#grid {
.core (@gridColumnWidth, @gridGutterWidth) {
.spanX (@index) when (@index > 0) {
(~".span@{index}") { .span(@index); }
.spanX(@index - 1);
}
.spanX (0) {}
...
.span (@columns) {
width: (@gridColumnWidth * @columns) + (@gridGutterWidth * (@columns - 1));
}
...
Which is called in grid.less file in less directory this way:
#grid > .core(@gridColumnWidth, @gridGutterWidth);
Which produce (among other things):
.span12 {
width: 940px;
}
.span11 {
width: 860px;
}
.span10 {
width: 780px;
}
...
in bootstrap.css line 170.
For @gridColumnWidth, @gridGutterWidth and the rest of variables check variables.less file (line 184)
Be sure to have the last version of lessc node compiler installed.
can I write a loop for css
You can't do loops with pure CSS, however, if you're using something like SASS or LESS then you can do both like:
SASS:
@for $i from 1 through 4
.#{$class-slug}-#{$i}
width: 60px + $i
LESS:
Can you do a javascript for loop inside of LESS css?
However, assuming you just want to apply the same style to each nested div
, you can just do
.containerLength > div{
float: left;
}
or perhaps create a class named .float-left
and apply it to each element you want floated right.
styling several Div inside a javascript loop
This isn't something I would use divs for since they provide no semantic meaning and you are creating tabular data.
I would instead use a table which is designed for just this purpose.
Additionally styling the element directly is generally considered poor practise. It's more often than not best to CSS to do this so you do not repeat yourself and are able to easily change styles.
I've written an example that demonstrates using both recommendations.
// Create a table and bodyvar table = document.createElement("table"); var body = document.createElement("tbody");
// Loop through the rows and columns to add itemsvar count = 1;for (var i = 1; i < 4; i++) {
// Create a new row var row = document.createElement("tr"); for (var j = 1; j < 4; j++) { var cell = document.createElement("td"); cell.id = count++; // Set the id cell.innerHTML = cell.id; // Set innerHTML to show number for example row.appendChild(cell); // Add the cell to the row } body.appendChild(row); // Add the row to the body}
// Add the body to the table and the table to the documenttable.appendChild(body);document.body.appendChild(table);
table { border: 1px solid blue; /* Add the border to the whole table */ border-left-width: 0; /* But no border on the left hand side */ border-collapse: separate; /* Ensure borders are visible */ border-spacing: 0; /* But with no spaces */}
table td { border-left: 1px solid blue; /* Add internal borders to cells */ border-top: 1px solid blue;}
tbody tr:first-child td { border-top: none; /* Make sure we don't have a double border on top */}
CSS LESS - add variable in loop
You could move the colors into an array then fetch by index, e.g:
@colors: 'color-item-1' #f00, 'color-item-2' #0f0, 'color-item-3' #00f;
.generate-item(3);
.generate-item(@n, @i: 1) when (@i =< @n) {
.item@{i} {
color: extract(extract(@colors, @i),2);
}
.generate-item(@n, (@i + 1));
}
How come this JQuery loop doesn't change CSS with elements less than 4
The issue is because your code looks at all .product
elements in the DOM, not specifically those within each ul
in the each()
loop.
To correct this you can use $(this)
to reference the current ul
, then retrieve its child li
elements:
jQuery($ => {
$('ul.products').each(function() {
let $li = $(this).children('.product');
if ($li.length < 4) {
$li.css("background-color", "yellow");
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<ul class="products">
<li class="product">Test</li>
<li class="product">Test</li>
<li class="product">Test</li>
<li class="product">Test</li>
<li class="product">Test</li>
</ul>
<ul class="products">
<li class="product">Test</li>
<li class="product">Test</li>
<li class="product">Test</li>
</ul>
LESS Mixin for loop
Looking at the docs I'd say it would look like:
.foo(4);
.foo(@n, @i: 1) when (@i =< @n) {
&:nth-child(@{i}) {
.animation-delay(100ms + (@i * 20));
}
.foo(@n, (@i + 1));
}
Tested with LESS2CSS using animation-delay
property instead of your function:
.foo(4);
.foo(@n, @i: 1) when (@i =< @n) {
&:nth-child(@{i}) {
animation-delay: (100ms + (@i * 20));
}
.foo(@n, (@i + 1));
}
Generates:
:nth-child(1) {
animation-delay: 120ms;
}
:nth-child(2) {
animation-delay: 140ms;
}
:nth-child(3) {
animation-delay: 160ms;
}
:nth-child(4) {
animation-delay: 180ms;
}
LESS CSS nested loops for header elements
This mixin will work in LESS 1.6+. The em
at the end of the font-size calculation was kicking up an error and is not necessary as em
units are already being used in the calculation.
.headers-generator(@n; @i : 1) when (@i =< @n)
{
h@{i} {
font-size: (2em - (@i - 1) * 0.2);
}
.headers-generator(@n; (@i + 1));
}
.headers-generator(6);
Less css: Maximum call stack size with loop in loop
The problem in your case is because the e()
(or ~()
) function's output is always a string and you cannot use it to perform mathematical operations or comparisons etc. You can verify this by adding the below line in your @media
query (and commenting out the mixin calls).
columnIsNumber: isnumber(@column);
/* with your current method this will always return false */
To overcome this issue, you should avoid using the e()
function for any variable which you would like to perform a mathematical operation on. For instance, you can change your mixin to be like below (refer inline comments for changes made):
@prefixes: 'sm', 'md', 'lg';
@breakpoints: '0', '100rem', '140rem';
@columns: 2, 6, 12; /* note the exclusion of quotes */
.generate-offset(@n, @tag, @i: 1) when (@i < @n) {
.offset--@{tag}-@{i} {
margin-left: (@i * 100% / @n);
}
.generate-offset(@n, @tag, (@i + 1));
}
// Grid loops
.loop(@index, @count) when (@index > 0){
// extract variables
@current: (@count - @index);
@breakpoint: e(extract(@breakpoints, @current));
@column: extract(@columns, @current); /* avoid using e() */
@prefix: e(extract(@prefixes, @current));
@media (min-width: @breakpoint) {
.generate-columns(@column, @prefix);
/*columnIsNumber: isnumber(@column);*/
.generate-offset(@column, @prefix);
}
.loop ((@index - 1), @count);
}
// run
@grids: length(@breakpoints);
.loop(@grids, (@grids + 1));
Of-course you could do it with your own code (with quotes in variable declaration and e()
in the mixin) using a bit of JS evaluation. But I wouldn't recommend this approach as it just adds to the complexity in my view.
@media (min-width: @breakpoint) {
.generate-columns(@column, @prefix);
@col: `function(){return @{column}}()`; /* JS evaluation */
/*columnIsNumber: isnumber(@col);*/
.generate-offset(@col, @prefix);
}
or
@media (min-width: @breakpoint) {
.generate-columns(@column, @prefix);
@col: `function(){return parseInt(@{column},10)}()`; /* JS evaluation */
/*columnIsNumber: isnumber(@col);*/
.generate-offset(@col, @prefix);
}
Related Topics
Determine Maximum Possible Div Height
JavaScript - Check If String Is Valid CSS Color
Google Chrome Copy CSS Path in Developer Tools
How to Disable JavaScript/CSS Minification in ASP.NET MVC 4 Beta
Select Element by CSS Style (All with Given Style)
Detect High Contrast Extension Use in Chrome Browser
Detecting Click Event on Padding Only
How to Detect MAC Os Inverted Color Mode in JavaScript/Css
Vanilla JavaScript: Resize Font-Awesome to Fit Container
How to Get All Valid Keywords for CSS Property
How to Customize Ant.Design Styles
Blend Mode:Multiply in Internet Explorer
How to Change the Style of Elements with Same Class Name
Change Svg Text to CSS Word Wrapping
Jquery: How to Get Assigned Font to Element
How to Add Alpha Filter to Any HTML Element and Keep the Other Filters in Ie