I was looking at bootsrap mixins.less and noticed a tilde in front of box-shadow value. What purpose does it serve? If my website supports IE9 and higher should I be using it?
.box-shadow(~"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px #{color-rgba}");
That is the tilde-quote CSS escaping.
In LESS, a tilde ~ before a string "" literal outputs the string
as-is, because it may be a syntax error in pure LESS.
In this particular instance, it's used in order to escape the comma , character at the string which belongs to the multiple values of box-shadow property.
Because the comma is used to separate the arguments of less mixins. So they did:
.foo {
.box-shadow(~"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px #{color-rgba}");
}
Alternatively, they could pass a list of values into the .box-shadow() mixin.
From the doc:
if the compiler sees at least one semicolon inside mixin call or
declaration, it assumes that arguments are separated by semicolons and
all commas belong to css lists
...
use dummy semicolon to create mixin call with one argument containing
comma separated css list: .name(1, 2, 3;)
Hence, they could just use a semicolon at the end of the value to make the compiler treat that as a list:
.bar {
.box-shadow(
inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px #color-rgba;
// They could append a semicolon here ^
);
}
Which is as the same as:
.bar {
#list: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px #color-rgba;
.box-shadow(#list);
}
Here is an example of the above approaches.
Related
I have the following =>
#header-height: 40;
#footer-height: 20;
I would like to be able to do
min-height: calc(~'100% - '#header-height+#footer-height'px') !important;
which return me
100%-60px
but my test fail as I get
min-height: calc(100% - 40+20 'px') !important;
You can use ${var} syntax to insert variable into less string expression:
min-height: ~'calc(100% - #{header-height}px - #{footer-height}px)' !important;
Moreover, it is better to execute the whole calc(...) command due ~'calc(...)' syntax
Simple question: I don't understand what the Advanced arguments do in Less CSS, as per http://lesscss.org/features/#mixins-parametric-feature-advanced-arguments-and-the-rest-variable . I've battled to get my head around how it's explained there.
I understand this:
.mixin(#a: 1) {
But I don't understand the following two, where the ... is introduced:
.mixin(...) { // matches 0-N arguments
.mixin() { // matches exactly 0 arguments
.mixin(#a: 1) { // matches 0-1 arguments
.mixin(#a: 1; ...) { // matches 0-N arguments
.mixin(#a; ...) { // matches 1-N arguments
.mixin(#a; #rest...) { // #rest is bound to arguments after #a
// #arguments is bound to all arguments }
I'm learning Less because I'm very keen on bootstrap, but this puzzled me.
Thank you very much!
Well, okay you should also read http://lesscss.org/features/#mixins-parametric-feature-pattern-matching.
In Less only mixin that match the number of arguments of the caller are compiled. Notice also that when two or more mixins match, all of them are compiled into CSS.
When you mixin got one argument, like that shown below:
.mixin(#a) {}
Only callers with one argument match and will be compiled: .mixin(3); or .mixin(1) and so on. But NOT .mixin() or .mixin(1,2,3)
When you set a default value for the first argument, for instance 3, as shown below:
.mixin(#a: 3) {}
Now not only calls with 1 argument match, but also calls with zero arguments:
.mixin(#a: 3) {property: #a;}
p{ .mixin();}
outputs:
p {
property: 3;
}
Now take a look to the special ... argument, that argument matches any number of arguments. So .mixin(...) will match and get compiled the following callers .mixin(), .mixin(1) and .mixin(1,2,3,4).
When you prepend a name (including the #) to the ... argument the values will be assigned to a variable with that name:
.mixin(#listofvariables...) {
p: #listofvariables;
}
p {
.mixin(one; two; three);
}
outputs:
p {
p: one two three;
}
Notice that ... assigns the arguments to a list, which can be manipulated with the list functions too.
An mixin such as .mixin(#a; ...) is a variant of the preceding two use cases. This mixins requires a first argument set, followed by zero or any other arguments.
#arguments is a special variable that contains a list of all argument of the mixin:
.mixin(#a; #b) {p1: #arguments; p2:extract(#arguments,2); p3:#b;}
p {.mixin(1; 2);}
outputs:
p {
p1: 1 2;
p2: 2;
p3: 2;
}
So the #arguments variable can be used in any mixin and does not require an ... argument.
What would a caller for a mixin like this look like? .mixin(#a; ...)
could it be something like this: .mixin(#a,53px); ? How does it
determine where the 53px goes to?
The 53px is not assigned to a variable, but it is the second item of the #arguments list. You can get it by extract(#arguments,2).
An use case for the .mixin(#a; ...) {} can be to assign a property always when .mixin() regardless the number of arguments, example:
.mixin(#a; ...) { color: #a;}
.mixin(#a) { background-color: contrast(#a); width:100%;}
.mixin(#a; #b;) { background-color: contrast(#a); width:#b;}
div {
.mixin(red);
}
div.small {
.mixin(red,50%);
}
outputs:
div {
color: red;
background-color: #ffffff;
width: 100%;
}
div.small {
color: red;
background-color: #ffffff;
width: 50%;
}
notice that the .mixin(#a; #rest...) {} assigns 35px the first item of the #rest list. And so the following Less code:
.mixin(#color,#padding...) {
color: #color;
padding: #padding
}
div {
.mixin(red; 10px; 20px; 5px; 5px);
}
outputs:
div {
color: red;
padding: 10px 20px 5px 5px;
}
We need to display currency amounts in a browser table and since those are numbers, they should be right aligned.
Problem is with currencies like Japan which do not have floating point currencies.
So for them, we cannot show 5.10 Yen
Now, the requirement is to show something like this:
(Note the alignment and the mixing of decimal currencies with non-decimal)
5.23
12.00
3.24
5
9
11.00
In the above, 5 and 9 are Japanese Yens while others are USD
So the requirement is to replace floating points with spaces for currencies like JPY. Spaces are required to have proper alignment of the currencies.
Offcourse, for other currencies, the 2 decimal places should be there.
Does anyone know how the above can be done?
Thanks a lot in advance!!
Based on the below replies:
1) The values are sent from a Java server and fed into a JavaScript library SlickGrid
2) We want to control values at the server level because the SlickGrid code is not very amenable for this kind of work.
3) Currencies are being stored as floats because customer wants to see them that way :( and that's kind of correct because mostly people are bothered about dollars not cents, but then, some people are concerned about cents too.
I was really hoping of some option with DecimalFormat only as that would have been the best solution.
Else I would have to resort to the ugly solution of parsing and string massaging.
Currency should never be stored as a floating point number. It should always be integer amounts of the lowest denomination you are working with (Yen, Cents, Paise).
If you need to work with amounts smaller than the lowest natural denomination, store currency as integer amounts representing multiples of a specified fraction. For example 6 tenths of a Yen.
As for the formatting, there is a discussion of simple options here.
following CSS is basically taken from the link in jsj's answer (extracting the most relevant portion)
HTML only version:
td { font-family: monospace; }
span.int {
text-align: right;
float: left;
width: 3em;
}
span.fractional {
text-align: left;
float: right;
width: 2em;
}
<table>
<tr><td><span class="int">5</span><span class="fractional">.23</span></td></tr>
<tr><td><span class="int">12</span><span class="fractional">.00</span></td></tr>
<tr><td><span class="int">3</span><span class="fractional">.24</span></td></tr>
<tr><td><span class="int">5</span><span class="fractional"></span></td></tr>
<tr><td><span class="int">9</span><span class="fractional"></span></td></tr>
<tr><td><span class="int">11</span><span class="fractional">.00</span></td></tr>
</table>
JavaScript version:
function spanInt(content){ var span = document.createElement('span');span.className = 'int'; span.textContent = content; return span; }
function spanFractional(content){ var span = document.createElement('span'); span.className = 'fractional'; span.textContent = content; return span;}
function tableCell_int(value){
var td = document.createElement('td');
td.appendChild(spanInt(value));
td.appendChild(spanFractional(''));
return td;
}
function tableCell_float(value){
var intPart = Math.floor(value);
var fracPart = value - intPart;
var td = document.createElement('td');
td.appendChild(spanInt(intPart));
td.appendChild(spanFractional('.' + Math.round(100*fracPart)));
return td;
}
function tr(cell){
var elt = document.createElement('tr');
elt.appendChild(cell);
return elt;
}
var theTable = document.getElementById('theTable');
function add_int(value){ theTable.appendChild(tr(tableCell_int(value))); }
function add_float(value){ theTable.appendChild(tr(tableCell_float(value))); }
add_float(5.23); add_float(12); add_float(3.24);
add_int(5); add_int(9); add_float(11);
td { font-family: monospace; }
span.int {
text-align: right;
float: left;
width: 3em;
}
span.fractional {
text-align: left;
float: right;
width: 2em;
}
<table id='theTable'></table>
I'm trying to use CSS3 border-image for a simple button design: the left slice of the image should be the left border of the text, the right slice the right border, and the middle slice should be repeated (or stretched - it does not matter) as background. I need a fallback for browsers not supporting border-image - just using the middle slice as a background, without edges would be acceptable. The problem is, if I do this:
.button {
border: solid 1px white;
border-size: 0 5px;
background: ('button-slice.png') repeat;
border-image: url('button.png') 0 5 0 5 fill;
-moz-border-image: url('button.png') 0 5 0 5;
/* repeat for other vendor prefixes */
}
the image from the background property will overlap the borders and mess up the button for browsers which support border-image.
Is there a lightweight way of solving this problem (whithout introducing modernizr or similar javascript checks)?
change the border-image 0 5 0 5 to 1 1 5 1 :
border-image: url('button.png') 1 1 5 1 fill;
-moz-border-image: url('button.png') 1 1 5 1;
border-image generator online
border-image is tricky for fallbacks. Doing...
.button {
border: solid 1px white;
border-size: 0 5px;
background: ('button-slice.png') repeat;
background: rgba(0,0,0,0);
border-image: url('button.png') 0 5 0 5 fill;
-moz-border-image: url('button.png') 0 5 0 5;
/* repeat for other vendor prefixes */
}
Should work for all browsers except IE9.
Since you only have a left and right border, I would suggest using pseudo-elements...
.button {
border: solid 1px white;
background: ('button-slice.png') repeat;
position: relative;
}
.button:before, .button:after {
content: '';
width: 5px;
position: absolute;
height: 100%;
background: transparent url('button.png') 0 0 no-repeat;
top: 0;
}
.button:before {left: -5px;}
.button:after {right: -5px;}
This technique should show nice buttons in all modern browsers plus IE8. Older browsers fallback without the edges.
It seems that new versions of FF support both border-image parameters and one override another.
Try reversing the order of those lines as so:
-moz-border-image: url('button.png') 0 5 0 5;
border-image: url('button.png') 0 5 0 5 fill;
In this way, browsers that support both parameters and override one with the later will take the version with the fill.
Is it possible to assign a variable based on another variable using less css?
pseudo code:
#userpick = red; /* this changes based on user pick */
#color1 = red;
#color2 = blue;
if( #userpick == #color1)
#systempick = #color2
else( #userpick == #color2)
#systempick = #color1
I want to be able to use #systempick as a color value not as a css style. For example:
border: 5px dashed #systempick;
Doesn't use a mixin, but resolves your desire
If the #userpick is stored as a string instead, then that could be used to access another variable name based off of it (a variable variable), like so:
LESS
#userpick: "blue"; /* this changes based on user pick, saved as a string */
#setopposite: "#{userpick}-opp";
//set opposing values
#red-opp: blue;
#blue-opp: red;
#systempick: ##setopposite;
.test {
color: #systempick;
}
CSS Output (note how blue outputs #ff0000, i.e. red)
/* this changes based on user pick */
.test {
color: #ff0000;
}
Since you are dealing with colors, the #userpick needs to be saved as a string because otherwise, LESS will automatically assign it a hex value rather than the color name.
You can use guards in mixins to change the color that is used, e.g.
.a when (#userpick = #color1) {
color: #color2;
}
.a when (#userpick = #color2) {
color: #color1;
}
You might get code duplication but its the only way to get an if statement.
Other ways are possible (e.g. inline javascript if using less.js or a function plugin if using dotless) but are probably a little hacky.
I was able to get what I needed, however this may not work on the PHP port of Less.
This was a bit tricky since you can assign variables only once. There are also some restrictions regarding scope of variables. I'm also comparing color values using HSV (hue, saturation, value)
.set_colors(#F00, #00F, #F00); /* pass red, blue and user pick */
.set_colors(#c1, #c2, #u) when (hue(#c1) = hue(#u)) and (saturation(#c1) = saturation(#u)) and (lightness(#c1) = lightness(#u)){
#color1 = #c1;
#color2 = #c2;
#userpick = #c1;
#systempick = #c2;
}
.set_colors(#c1, #c2, #u) when (hue(#c2) = hue(#u)) and (saturation(#c2) = saturation(#u)) and (lightness(#c2) = lightness(#u)){
#color1 = #c1;
#color2 = #c2;
#userpick = #c2;
#systempick = #c1;
}