Pass Less variable in to attribute selector - html

I have a task to write 100 styles for every of 10 columns in Less.
Code looks like this at the moment:
.loopingCellWidth (#index) when (#index > 0){
&[data-1-column-width="#{index}"] {
.exercise-table-row {
.exercise-table-row-part {
&:nth-child(1) {
width: percentage(#index * 0.01) !important;
}
}
}
}
&[data-2-column-width="#{index}"] {
.exercise-table-row {
.exercise-table-row-part {
&:nth-child(2) {
width: percentage(#index * 0.01) !important;
}
}
}
}
// ..... up to 10
.loopingCellWidth(#index - 1);
}
.loopingCellWidth(100);
I would like to create a variable #numberOfColumn and place it in the attribute selector, like this:
&[data-#{#numberOfColumn}-column-width="#{index}"] {
But this solution doesn't work.
Any ideas how it should be done? Of course if it's even possible.

Related

How do I set properties according to custom HTML attributes in CSS?

I'm working on Fractions.
My checkpoint is :
frac {
display: inline-block;
position: relative;
vertical-align: middle;
letter-spacing: 0.001em;
text-align: center;
}
frac {
display: block;
padding: 0.01em;
}
frac {
border-top: thin solid black;
}
It is working but I want to two things :
I want to set default values, i.e. 0 to num and 1 to den.
I want to do use this type of code to make things simple : <frac num="0" den="1"> Note :It should not have a closing tag.The num and den attributes should have their default values if not mentioned.
Btw, I only know CSS.
There is no <frac> element in HTML.
To create your own <frac-el num="3" den="4"></frac-el>, you can create a small web component, which must adhere to custom element naming rules (name must contain a -). It also will need a closing tag.
That being said, here we go:
class FractionElement extends HTMLElement {
numerator = document.createElement('sup');
denominator = document.createElement('sub');
style = document.createElement('style');
constructor(n = 0, d = 1) {
super().attachShadow({mode:'open'});
this.num = n;
this.den = d;
this.style.textContent = `
:host { display: inline-flex; flex-direction: column; text-align: center; }
sup { border-bottom: 1px solid #666; }
`;
this.shadowRoot.append(this.numerator, this.denominator, this.style);
}
get num() { return this.numerator.textContent; }
set num(val) { this.numerator.textContent = val; }
get den() { return this.denominator.textContent; }
set den(val) { this.denominator.textContent = val; }
static get observedAttributes() {
return ['num', 'den'];
}
attributeChangedCallback(attr, oldVal, newVal) {
if (oldVal === newVal) return; // nothing to do, no change
switch (attr) {
case 'num': this.num = newVal ?? 0; break;
case 'den': this.den = newVal ?? 1; break;
}
}
}
customElements.define('frac-el', FractionElement);
<frac-el num="3" den="4"></frac-el>
<frac-el num="11" den="27691"></frac-el>
<frac-el></frac-el>
<frac-el num="3x + 7" den="y"></frac-el>

Access to root variable within a #mixin

I would like to use the value of one root variable (which is defined by javascript) within a mixin as a condition of a #if. I think the example below is more clear than my explanation actually... Thanks for the help.
:root {
--bu:A;
}
#mixin varCheck() {
$var: var(--bu);
#if ($var == A) {
header {
background-color: blue !important;
}
}
#if ($var == B) {
header {
background-color: black !important;
}
}
}
#include varCheck();

How have dynamic class names in LESS CSS and use them as values in function

I want generate flexible color classes for another class like this without writing all of them on LESS as variables:
.link.color-green{
color:green;
}
.link.color-red{
color:red;
}
.link.color-cccccc{
color:#cccccc;
}
.link.color-FFF8DC{
color:#FFF8DC;
}
maybe something like this? but compiler say error:
NameError: variable #colorNameOrHexaCode is undefined
.link{
.color-#{colorNameOrHexaCode} {
color: rgb(#colorNameOrHexaCode);
};
}
I'm not sure how make loop or function for this, sorry.
You have to create a list of colors first before creating a loop:
.make-classes(#prefix, #list) {
.iter(length(#list));
.iter(#i) when (#i > 0) {
.iter(#i - 1);
#pair: extract(#list, #i);
#key: extract(#pair, 1);
#value: extract(#pair, 2);
.#{prefix}.color-#{key} {
color: #value;
}
}
}
#colors:
~'blue' #7FB3D4,
~'gray' #767676,
~'green' #8CC079,
~'red' #b35d5d;
.make-classes(link, #colors);
Output:
.link.color-blue {
color: #7fb3d4;
}
.link.color-gray {
color: #767676;
}
.link.color-green {
color: #8cc079;
}
.link.color-red {
color: #b35d5d;
}

Can i nest the disabled attribute using LESS?

I have the following code to target buttons that are in a disable state:
.btn-default[disabled] {
background-color: lighten(#btn-default-bg, 30%)
}
Is it possible to use nested rules to target the disabled attribute? something similar to &:Hover
You can indeed, like this:
.btn-default {
&[disabled] {
background-color: lighten(#btn-default-bg, 30%)
}
}
http://jsbin.com/aKuLire/1/edit
You can even do further nesting:
input {
&[type="submit"] {
&[disabled] {
background: #blue;
}
}
}

How can I build a flexible ratings widget in LESS instead of straight CSS?

I found this flexible, one-image rating widget built with SASS by AirBnB. I'd like to create something similar with LESS. I know I could just write out the CSS, but I'd like to do it dynamically with LESS. My main problem seems to be dynamically adding the counter _1 ... _10 to the class (.filled_1 ... filled_10). Is this possible in LESS?
Here's the working SASS code:
$starWidth: 44px;
$starOffset: 0 -43px;
$numStars: 5;
$steps: 2;
$total: $numStars * $steps;
#mixin filled($n: 0) {
width: ($starWidth / $steps) * $n;
}
.stars {
background: url(/images/sprite.png) repeat-x top left;
height: 43px;
&.empty {
background-position: $starOffset;
width: $numStars * $starWidth;
}
#for $i from 0 through ($total) {
&.filled_#{$i} { #include filled($i) }
}
}
This turns out code like this in CSS:
.stars {
background: url(/images/sprite.png) repeat-x top left;
height: 43px; }
.stars.empty {
background-position: 0 -43px;
width: 220px; }
.stars.filled_0 {
width: 0px; }
.stars.filled_1 {
width: 22px; }
.stars.filled_2 {
width: 44px; }
.stars.filled_3 {
width: 66px; }
.stars.filled_4 {
width: 88px; }
.stars.filled_5 {
width: 110px; }
.stars.filled_5 {
width: 132px; }
.stars.filled_7 {
width: 154px; }
.stars.filled_8 {
width: 176px; }
.stars.filled_9 {
width: 198px; }
.stars.filled_10 {
width: 220px; }
How can I do the same loop and include in LESS instead of CSS?
The final HTML will look like this: (where 9 will show 4.5 stars)
<div class="stars empty">
<div class="stars filled_9">4.5</div>
</div>
As simple as link to a resource: http://blog.thehippo.de/2012/04/programming/do-a-loop-with-less-css
And here is code sample from the resource:
LESS code:
#iterations: 30;
// helper class, will never show up in resulting css
// will be called as long the index is above 0
.loopingClass (#index) when (#index > 0) {
// create the actual css selector, example will result in
// .myclass_30, .myclass_28, .... , .myclass_1
(~".myclass_#{index}") {
// your resulting css
my-property: -#index px;
}
// next iteration
.loopingClass(#index - 1);
}
// end the loop when index is 0
.loopingClass (0) {}
// "call" the loopingClass the first time with highest value
.loopingClass (#iterations);
Resulting CSS:
.myclass_30 {
my-property: -30 px;
}
.myclass_29 {
my-property: -29 px;
}
.......
.......
.......
.myclass_1 {
my-property: .1 px;
}
Stackoverflow user GnrlBzik shared a looping strategy for LESS, but the result looked more complex than I had hoped. Here is a working solution that still looks elegant for those that will have a static amount of stars.
#starWidth: 44px;
#starOffset: 0 -43px;
#numStars: 5;
.starCount(#starSpan: 1) {
width: (#starWidth / 2) * #starSpan;
}
.stars {
background: url('/images/sprites/stars.png') repeat-x top left;
height: 43px;
display:block;
&.empty {
background-position: #starOffset;
width: (#starWidth * #numStars);
}
&.filled_0 { .starCount(0); }
&.filled_1 { .starCount(1); }
&.filled_2 { .starCount(2); }
&.filled_3 { .starCount(3); }
&.filled_4 { .starCount(4); }
&.filled_5 { .starCount(5); }
&.filled_6 { .starCount(6); }
&.filled_7 { .starCount(7); }
&.filled_8 { .starCount(8); }
&.filled_9 { .starCount(9); }
&.filled_10 { .starCount(10); }
}