How to generate classes in LESS? - css

I need to generate all combinations the following classes:
.b-1-1-1-1 {
border:1px solid #000;
}
.b-0-1-1-1 {
border-right: 1px solid #000;
border-bottom: 1px solid #000;
border-left: 1px solid #000;
}
.
.
.
I need to use class names as border style likes, is it possible to make it in LESS automatically?

You could also just loop through binary numbers instead of a nested loop (makes everything a bit shorter) ... something like this perhaps:
.set-top() when (#t > 0) {
border-top: 1px solid #000;
}
.set-left() when (#l > 0) {
border-left: 1px solid #000;
}
.set-right() when (#r > 0) {
border-right: 1px solid #000;
}
.set-bottom() when (#b > 0) {
border-bottom: 1px solid #000;
}
.borders(#t:0, #r:0, #b:0, #l:1){
.b-#{t}-#{r}-#{b}-#{l} {
.set-top;
.set-right;
.set-bottom;
.set-left;
}
}
.loop(#i:16) when (#i < 32) {
.borders(~`(#{i}).toString(2)[1]`,
~`(#{i}).toString(2)[2]`,
~`(#{i}).toString(2)[3]`,
~`(#{i}).toString(2)[4]`);
.loop((#i + 1));
}
.loop();
In addition you can again add a check for which properties are set/same and combine them under a combined border property and set the border width/style/color like ScottS shows in his example.

(Update: I've been asked to rework my example to a complete snippet - so here we go).
Variant 1
Basically it's the same as in Martin Turjak answer but without inline javascript and with some further makeup:
// usage:
.borders(1px dashed wheat);
div {
.borders(3px, dotted, red);
}
// implementation:
.borders(#values...) {
.values(t, 1) {border-top: #values}
.values(r, 1) {border-right: #values}
.values(b, 1) {border-bottom: #values}
.values(l, 1) {border-left: #values}
.values(... ) {}
.trbl-(#t, #r, #b, #l) {
.b-#{t}-#{r}-#{b}-#{l} {
.values(t, #t);
.values(r, #r);
.values(b, #b);
.values(l, #l);
}
}
.-(#i: 15) when (#i > 0) {
.-((#i - 1));
.trbl-(mod(floor((#i / 8)), 2),
mod(floor((#i / 4)), 2),
mod(floor((#i / 2)), 2),
mod(floor((#i / 1)), 2));
}.-;
}
Variant 2
The magic one, no loops, minified CSS output:
// usage:
.borders(1px, dashed, wheat);
// implementation:
.borders(#values...) {
0, 1 {
.b-1-&-&-& {border-top: #values}
.b-&-1-&-& {border-right: #values}
.b-&-&-1-& {border-bottom: #values}
.b-&-&-&-1 {border-left: #values}
}
}

Doable
This code allows flexibility in setting style and color to the border, the unit value of the width, and defaults to max width of 1 unit (which is px by default). Note that setting the border width values to anything more than 1, the output CSS code is going to begin increasing at a dramatic rate (try running them at just 2, i.e. calling .generateBorderClasses(#t: 2, #r: 2, #b: 2, #l: 2);, and see the results);
.generateBorderClasses(#unit: px, #style: solid, #color: #000, #t: 1, #r: 1, #b: 1, #l: 1) {
.b() when (#check) {
border: unit(#t,#unit) #style #color;
}
.b() when (#sum = 0) {}
.b() when (#t > 0) and (#sum > 0) and not (#check) {
border-top: unit(#t, #unit) #style #color;
}
.b() when (#r > 0) and (#sum > 0) and not (#check) {
border-right: unit(#r, #unit) #style #color;
}
.b() when (#b > 0) and (#sum > 0) and not (#check) {
border-bottom: unit(#b, #unit) #style #color;
}
.b() when (#l > 0) and (#sum > 0) and not (#check) {
border-left: unit(#l, #unit) #style #color;
}
.t-loop (#t) when (#t > -1) {
.r-loop (#r) when (#r > -1) {
.b-loop (#b) when (#b > -1) {
.l-loop (#l) when (#l > -1) {
#sum: (#t + #r + #b + #l);
#check: e(`(#{t} == #{r}) && (#{t} == #{b}) && (#{t} == #{l}) ? "true" : "false"`);
.b-#{t}-#{r}-#{b}-#{l} {
.b();
}
.l-loop(#l - 1);
}
.l-loop (-1) {}
.l-loop(#l);
.b-loop(#b - 1);
}
.b-loop (-1) {}
.b-loop(#b);
.r-loop(#r - 1);
}
.r-loop (-1) {}
.r-loop(#r);
.t-loop(#t - 1);
}
.t-loop(-1) {}
.t-loop(#t);
}
.generateBorderClasses();
Still Not Recommended
Personally, I would just have four classes controlling the html (so something like class="bt br bb bl") and then do this:
.bt {
border-top: 1px solid #000;
}
.br {
border-right: 1px solid #000;
}
.bb {
border-bottom: 1px solid #000;
}
.bl {
border-left: 1px solid #000;
}
MUCH less (pun intended) css code and essentially the same control value in the class assigning of the html.

Related

"Quoting" argument variable in LESS mixin

I have the following array of color definitions:
#colors: ~"black" #000, ~"white" #fff, ~"blue" #008FD6, ~"bluehover" #44A1E0, ~"grayborder" #DBDBDB;
And I use the following function to use those colors within CSS declarations.
.colorkey(#key) {
.-(length(#colors));
.-(#i) when (#i > 0) {.-((#i - 1))}
.-(#i) when (#key = extract(extract(#colors, #i), 1)) {
#colorkey: extract(extract(#colors, #i), 2);
}
.--() {#colorkey: #000} .--;
}
Usage:
.my-div {
.colorkey(~"black");
color: #colorkey
}
However I'd prefer to use the mixin like so:
.colorkey(black);
Without the quotes and tilde. Is it possible to modify the colorkey mixin to achieve this?
If your #colors can be defined without putting the color names in ~"...", you just need to make a minor change:
#colors: black #000, white #fff, blue #008FD6, bluehover #44A1E0, grayborder #DBDBDB;
.colorkey(#key:black) {
.-(length(#colors));
.-(#i) when (#key = extract(extract(#colors, #i), 1)) {
#colorkey: extract(extract(#colors, #i), 2);
}
.-(#i) when (#i > 0) {.-(#i - 1)}
}
.my-div {
.colorkey(bluehover);
color: #colorkey
}
Note that I
removed the extra set of parentheses in your .-(#i) when (#i > 0)
moved that recursive call to the end of .colorkey, and
dropped your .--() {#colorkey: #000} .--; and in its place used .colorkey(#key:black) {. (My guess is that was supposed to make .colorkey; color: #colorkey evaluate to color: #000 but actually it wasn't doing anything :) In the code you provided, to define that default you'd need instead to do .colorkey(#key: ~"black") { )

how to pass a string to a mixin and generate a dynamic variable to output color in LESSCSS?

//call the mixin
.mixin-loop(grey, 7);
//the implementation
.mixin-loop(#str, #count) {
.loop (#i) when (#i > 0) {
.#{str}-#{i} {
div { background: "#{#{str}-#{i}}"; }
}
.loop(#i - 1);
}
.loop (#count);
}
//globals.less
#grey-1: #ccc;
#grey-2: #999;
The output I want is this:
//output
.grey-1 div {
background: #ccc;
}
.grey-2 div {
background: #999;
}
But what I'm getting is this:
.#808080-1 div {
background: "#{#808080-1}";
}
.#808080-2 div {
background: "#{#808080-2}";
}
You can use variable interpolation (~) to help with this:
http://lesscss.org/features/#variables-feature-variable-interpolation
This will prevent grey from being converted into it's hex value, and then will allow "#{#{str}-#{i}}" to be displayed as a hex value instead of a string.
//call the mixin
.mixin-loop(~"grey", 2);
//the implementation
.mixin-loop(#str, #count) {
.loop (#i) when (#i > 0) {
.#{str}-#{i} {
div { background: ~"#{#{str}-#{i}}"; }
}
.loop(#i - 1);
}
.loop (#count);
}
//globals.less
#grey-1: #ccc;
#grey-2: #999;

AngularJS - how to refactoring a CSS code style

I have an angular function like this:
$scope.colorValidator = function () {
$scope.token_style = "";
$scope.expdate_style = "";
if (!$scope.$$childHead.billingblock.accountID.$valid) {
$scope.token_style = {border: "1px solid #ff0000"}
}
if (!$scope.$$childHead.billingblock.expDate.$valid) {
$scope.expdate_style = {border: "1px solid #ff0000"}
}
};
How can i set the {border: "1px solid #ff0000"} in a constant variable (maybe like red), and set it in each validation ?
Edit: I'm setting ng-style (in the view) for each input.
You do not need to do that.
Check you markup when fields are not valid, they have ng-dirty and ng-invalid classes applied
Use them to style your controls
.my-special-form .ng-invalid {
border: 1px solid #ff0000
}
Please see here: http://jsbin.com/hekaz/3/edit?css,output
ie:
input.ng-invalid[ng-model="username"] {
border: 5px solid red;
}
input.ng-valid[ng-model="username"] {
border: 5px solid green;
}
I solved it setting it a variable:
var redColor = {border: "1px solid #ff0000"};
if (!$scope.$$childHead.billingblock.accountID.$valid) {
$scope.token_style = redColor;
}
Thank you to everyone for each answer.

Subtracting blur value from box-shadow property through SCSS

I have been cogitating on this for a while now. In my SCSS I have the following:
$shadow: 0 0 25px rgb(46, 46, 46);
div {
box-shadow: $shadow;
}
How can I subtract the 25px of blur by, let's say 10 so that I may use a blur of 15 pixels? Furthermore, how do I select the blur value? Considering I want to apply a box-shadow on a div element:
<div>Lorem Ipsum</div>
The $shadow variable is simply a list of values. If the blur is always going to be the 3rd item in the list (such as in your example), then what you're looking at is something like this:
div {
box-shadow: nth($shadow, 1) nth($shadow, 2) nth($shadow, 3) - 15px nth($shadow, 4);
}
If the blur is in another valid position in the list (maybe it's an inset shadow), then you'll need to start doing things like checking the length of the list and/or examine the first element to see if it is inset:
div {
#if nth($shadow, 1) == inset {
box-shadow: nth($shadow, 1) nth($shadow, 2) nth($shadow, 3) nth($shadow, 4) - 15px nth($shadow, 5);
} #else {
box-shadow: nth($shadow, 1) nth($shadow, 2) nth($shadow, 3) - 15px nth($shadow, 4);
}
}
Alternately, you could do it programatically:
$shadow: 0 0 25px rgb(46, 46, 46);
#function adjust-shadow($shadow, $position, $adjustment) {
$x: ();
$shift: if(nth($shadow, 1) == inset, -1, 0);
#for $i from 1 through length($shadow) {
$p: $i + $shift;
#if $position == color and $i == length($shadow) {
$x: append($x, $adjustment);
} #else if ($position == x-offset and $p == 1) or ($position == y-offset and $p == 2) or ($position == blur and $p == 3) {
$x: append($x, nth($shadow, $i) + $adjustment);
} #else {
$x: append($x, nth($shadow, $i));
}
}
#return $x;
}
.foo {
box-shadow: adjust-shadow($shadow, blur, -15px);
}
.bar {
box-shadow: adjust-shadow($shadow, color, blue);
}
.baz {
box-shadow: adjust-shadow(adjust-shadow($shadow, blur, -15px), y-offset, -2), adjust-shadow($shadow, blur, 10px);
}
Make a new variable for the blur value:
$blur: 25px - 10;
$shadow: 0 0 $blur rgb(46, 46, 46);
div {
box-shadow: $shadow;
}
Depending on your overall needs, you might be better served by writing a mixin.

Place border around multiple cells in a gridview

So I have a Gridview that I would like to modify the look of for only certain cells, and I would like to treat those cells as one (if possible).
So first I am changing some of the cells background color on RowDataBound:
if (e.Row.RowIndex > 1 && e.Row.RowIndex < 7)
{
e.Row.Cells[1].BackColor = Color.Red;
e.Row.Cells[2].BackColor = Color.Red;
e.Row.Cells[3].BackColor = Color.Red;
e.Row.Cells[4].BackColor = Color.Red;
e.Row.Cells[5].BackColor = Color.Red;
}
This will change a 5x5 area of cells to red. Now what I would like to do next is put a border around the outside of that 5x5 area. I found the borderStyle and BorderColor for a cell, but is there a way for me to only turn on a border for one side of a cell so I can create my border?
Thanks
I'd advise you to use classes instead, don't hard-code it like this. It will be easier to maintain etc.
I just thought I would post this as a solution, in case anyone else is looking to do this.
Here is my CSS
<style type="text/css">
.LeftUpperCorner
{
border-left:5px solid black;
border-top:5px solid black;
}
.Top
{
border-top:5px solid black;
}
.RightUpperCorner
{
border-right:5px solid black;
border-top:5px solid black;
}
.Left
{
border-left:5px solid black;
}
.Right
{
border-right:5px solid black;
}
.LeftLowerCorner
{
border-left:5px solid black;
border-bottom:5px solid black;
}
.Bottom
{
border-bottom:5px solid black;
}
.RightLowerCorner
{
border-right:5px solid black;
border-bottom:5px solid black;
}
and my code behind:
if (e.Row.RowIndex == 2)
{
e.Row.Cells[1].CssClass = "LeftUpperCorner";
e.Row.Cells[2].CssClass = "Top";
e.Row.Cells[3].CssClass = "Top";
e.Row.Cells[4].CssClass = "Top";
e.Row.Cells[5].CssClass = "RightUpperCorner";
}
if (e.Row.RowIndex == 3 || e.Row.RowIndex == 4 || e.Row.RowIndex == 5)
{
e.Row.Cells[1].CssClass = "Left";
e.Row.Cells[5].CssClass = "Right";
}
if (e.Row.RowIndex == 6)
{
e.Row.Cells[1].CssClass = "LeftLowerCorner";
e.Row.Cells[2].CssClass = "Bottom";
e.Row.Cells[3].CssClass = "Bottom";
e.Row.Cells[4].CssClass = "Bottom";
e.Row.Cells[5].CssClass = "RightLowerCorner";
}
It may not be the prettiest, but this has not real need to change, and will always be in the same location, so it fits my simple needs.

Resources