On their site, they give an example of how to use #arguments:
.box-shadow (#x: 0, #y: 0, #blur: 1px, #color: #000) {
box-shadow: #arguments;
-moz-box-shadow: #arguments;
-webkit-box-shadow: #arguments;
}
.box-shadow(2px, 5px);
Which results in:
box-shadow: 2px 5px 1px #000;
-moz-box-shadow: 2px 5px 1px #000;
-webkit-box-shadow: 2px 5px 1px #000;
It appears it just takes all the arguments and separates them with spaces. I actually want the arguments separated by commas for use with linear-gradient:
background: linear-gradient(top, #arg1, #arg2, #arg3...);
Is this possible with less?
Inspired by #Allan's answer, I had to use the following to get #arguments passed to a linear gradient function:
.linear-gradient-multi( ... ) {
background-image: -webkit-linear-gradient( ~`"#{arguments}".slice(1,-1)` );
...
}
Only then could I call the mixin with percentages and variables:
.linear-gradient-multi(left, #CCC 0%, #DDD #percent, #FFF #percent + 1, #FFF 100%);
You can do something like this
.mixin(...) {
filter: gradient( ~`#{arguments}.join(",")` );
}
test {
.mixin("x1","x2","x3")
}
You should use back-ticks to be able to run some javascript. but that means that all elements inside the arguments array should be valid javascript variables, that's why when calling the mixin you should wrap all the arguments in quotes to make them javascript strings. the above code will be compiled to:
test {
filter: gradient(x1,2,3);
}
Related
I'm looking for a feature that may or may not be available in LESS.
I have a mixin that adds a "glow" with box-shadow, which I use on various elements - buttons, inputs etc.
.glow() {
box-shadow: 0 0 5px skyBlue;
}
What I'm looking for is a way to make the mixin add the box-shadow as a new comma-seperated value if the element already has a box-shadow.
So, I want this:
.button {
box-shadow: inset 0 5px 10px black;
.glow();
}
To compile to this:
.button {
box-shadow: inset 0 5px 10px black, 0 0 5px skyBlue;
}
I think I recall seeing a similar feature in SASS, but I can't find it anywhere now.
Does this feature exist in LESS, or is there some alternative way to achieve a similar result?
The feature you're looking for is merge. You'd do this:
.glow() {
box-shadow+: 0 0 5px skyBlue;
}
.button {
box-shadow+: inset 0 5px 10px black;
.glow();
}
Note that both rulesets need to use the + syntax for it to work.
Or, you could declare the glow rule as a variable:
#glow: 0 0 5px skyBlue;
.button {
box-shadow: inset 0 5px 10px black, #glow;
}
Can I use a pseudo element to declare a variable in Sass? I want my variable to be the first letter of a given string inside a list item. My watcher throws an error and won't compile.
Sass:
$firstLetter: li::first-letter
=newItem ($firstLetter)
$m
#extend %liStyle
#if $firstLetter == "m"
background-color: #3a495c
color: white
box-shadow: 0 3px 0 #14bbb1
display: list-item
font-family: sans-serif
font-size: .889em
border: 1px solid #ebeaec
&:hover
box-shadow: 0 3px 0 #ffdc00
&:active
box-shadow: 0 3px 0 #d86969
Thanks!
Variables must be of a specific type (string, integer, length, color, etc.), there is no "selector" type. If you need to have a variable to contain a selector, then it needs to be quoted and treated as a string:
$firstLetter: "li::first-letter";
#{$firstLetter} {
color: red;
}
I want to convert a base color in HEX (#color) to rgba and use that in a mixin like .box-shadow(x y b color);
I have seen a load of mixins to convert HEX to RGBA and set background-color, and I know I can create my own mixing for box-shadow. But is there a generic solution so we can use any existing mixin.
Tried/want something like this (doesn't work) :
/** Extend LESS functions like (lighten, darken, mix) **/
rgbaColorIn(#color, #opacity : 1){
return rgba( red(#color), green(#color), blue(#color), #opacity );
}
// ----- or ------
/** Passing in a reference to mixin and params **/
.rgbaColorIn(#selector, #params, #color, #opacity : 1){
#rgbaColor: rgba( red(#color), green(#color), blue(#color), #opacity );
#selector(#params #color);
}
There is no return keyword in less. If you want a mixin that returns a value, then you can define a variable inside it, for example:
.rgbaColorIn(#color, #opacity : 1){
#result: rgba( red(#color), green(#color), blue(#color), #opacity );
}
which you can access in the scope you call the mixin:
.section {
.rgbaColorIn(red, 50%);
background-color: #result;
}
But if you just want to generate a RGBA from a RGB color, you can use the fade function:
.section {
#result: fade(red, 50%);
background-color: #result;
}
which will render the same result in CSS:
.section {
background-color: rgba(255, 0, 0, 0.5);
}
A .box-shadow mixin to pass the RGB color and opacity/alpha separately could be something like this:
.box-shadow(#x; #y; #b; #color; #opacity) {
box-shadow: #x #y #b fade(#color, #opacity);
-moz-box-shadow: #x #y #b fade(#color, #opacity);
-webkit-box-shadow: #x #y #b fade(#color, #opacity);
}
Which you could use in a selector like this:
.section {
.box-shadow(2px; 2px; 1px; pink; 50%);
}
and obtain this CSS:
.section {
box-shadow: 2px 2px 1px rgba(255, 192, 203, 0.5);
-moz-box-shadow: 2px 2px 1px rgba(255, 192, 203, 0.5);
-webkit-box-shadow: 2px 2px 1px rgba(255, 192, 203, 0.5);
}
To get an rgba value (assuming you are giving it something other than 100% opacity, since LESS will just keep it as a hex value in that case), just use the fade() function. So...
LESS
#color: #ff0000;
.test {
box-shadow: 2px 2px 5px fade(#color, 99%);
}
CSS Output
.test {
box-shadow: 2px 2px 5px rgba(255, 0, 0, 0.99);
}
Good answers, I guess you also could do directly calling a box-shadow cross-browser function:
.toShadow(#color: red) {
#color-rgba: rgba(red(#color), green(#color), blue(#color), .6);
.box-shadow(~"inset 0 0 3px #{color-rgba}");
}
When using LESS, i found usefull to mix classes, in order to create a new class based on other class properties, but sometimes i need to override them.
like:
.btn {
border-radius: 10px;
background-color: blue;
font-size:10px;
}
.btn_warning {
.btn;
background-color: yellow;
font-size: 12px;
}
The output has duplicated properties:
.btn {
border-radius: 10px;
background-color: blue;
font-size:10px;
}
.btn_warning {
border-radius: 10px;
background-color: blue;
font-size:10px;
background-color: yellow;
font-size: 12px;
}
I know there are multiple aproaches for this, like multiple classes on dom, or even #extend to build multiple selectors, but navigator still overriding at runtime the properties.
Is there any reason to duplicate same properties when mixin? Seems a simple way for making "independent" groups of properties, but not nice if has duplicated values.
LESS does not account for removal of duplicate properties within a block, at least in part because of this reason stated here (quote slightly modified for grammar fix):
The trouble is that people frequently use multiple properties in order
to provide a fallback for older browsers. Removing the properties is
not something that it would be good to do generically.
It is left up to the programmer to not program it for duplication. You can set up a basic mixin like what Danny Kijkov noted in his answer, or...
Solution #1 (Complex, but Powerful to Fully Define)
You can get elaborate in building a master button maker mixin. Something like this:
LESS (Mixin)
.makeBtn(#ext: null; #rad: 10px; #color: blue; #size: 10px;) {
.set-extension() when (#ext = null) {
#class-extension: ~'';
}
.set-extension() when not (#ext = null) {
#class-extension: ~'_#{ext}';
}
.set-extension();
.btn#{class-extension} {
border-radius: #rad;
background-color: #color;
font-size: #size;
//define various addtions based on extensions here
.specialExtensionProps() when (#ext = danger) {
border: 3px solid red;
}
.specialExtensionProps() when (#ext = someExtName) {
my-special-prop: yep;
}
.specialExtensionProps();
}
}
LESS (Use the Mixin Various Ways)
.makeBtn(); //makes base button
.makeBtn(warning; #color: yellow; #size: 12px); //makes modified button
.makeBtn(danger; #color: red;); //makes modified button
.makeBtn(someExtName, 15px); //makes modified button
CSS Output
.btn {
border-radius: 10px;
background-color: #0000ff;
font-size: 10px;
}
.btn_warning {
border-radius: 10px;
background-color: #ffff00;
font-size: 12px;
}
.btn_danger {
border-radius: 10px;
background-color: #ff0000;
font-size: 10px;
border: 3px solid red;
}
.btn_someExtName {
border-radius: 15px;
background-color: #0000ff;
font-size: 10px;
my-special-prop: yep;
}
In case you did not know, note the above demonstrated LESS functionality of setting only some variables from the set of mixin variables. So for the first two specialized .makeBtn() calls, I only set a few variables, out of order from the mixin, by explicitly calling the variable name to set (e.g. #color: yellow). This allows me to "skip" over setting the #size. In the last example, I was only setting the first two values, so I did not need to put any variable names.
I don't know if the above helps you get what you want, but it does offer a different way of being able to reduce code size.
Solution #2
You mentioned :extend(), which could be well used here to avoid duplication:
LESS
.btn {
border-radius: 10px;
background-color: blue;
font-size:10px;
}
.btn_warning {
&:extend(.btn);
background-color: yellow;
font-size: 12px;
}
CSS Output
.btn,
.btn_warning {
border-radius: 10px;
background-color: blue;
font-size: 10px;
}
.btn_warning {
background-color: yellow;
font-size: 12px;
}
Solution #3
In your case, if all the buttons will be of either class .btn or a .btn_SOMETHING form, and you are not using .btn_ for anything else but buttons, then you might be able to just use the CSS cascade to apply styles and prevent duplication of CSS code like so (no special LESS required):
LESS and CSS Output
.btn, [class *= btn_] {
border-radius: 10px;
background-color: blue;
font-size:10px;
}
.btn_warning {
background-color: yellow;
font-size: 12px;
}
Any html with the class btn_warning will first get the base button styles from the attribute selector [class *= btn_] while the actual btn_warning class will override the things set to be overridden.
Solution #4
If you split the class names in the html (so class="btn warning" rather than class="btn_warning"), then this works to avoid duplication:
LESS and CSS Output
.btn {
border-radius: 10px;
background-color: blue;
font-size:10px;
}
.btn.warning {
background-color: yellow;
font-size: 12px;
}
What about this solution?
.btn(#size: 10px, #color:blue) {
border-radius: 10px;
background-color: #color;
font-size:#size;
}
.btn_warning {
.btn(12px, yellow);
}
this is my style.less code:
.transition {
-ms-transition: all 0.3s ease-in-out;
-moz-transition: all 0.3s ease-in-out;
-o-transition: all 0.3s ease-in-out;
-webkit-transition: all 0.3s ease-in-out;
transition: all 0.3s ease-in-out;
}
.shadow {
padding: 10px 10px 10px 10px;
margin: 10px 10px 10px 10px;
-moz-box-shadow: 0px 0px 10px #808080;
-o-box-shadow: 0px 0px 10px #808080;
-webkit-box-shadow: 0px 0px 10px #808080;
box-shadow: 0px 0px 10px #808080;
}
.shadow:hover {
-moz-box-shadow: 0px 0px 10px #a5a5a5;
-o-box-shadow: 0px 0px 10px #a5a5a5;
-webkit-box-shadow: 0px 0px 10px #a5a5a5;
box-shadow: 0px 0px 10px #a5a5a5;
}
.radius {
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
#t1 {
.shadow;
.transition;
.radius;
}
but when I hover #t1 the shadow doesn't change. I want to know why it doesn't work and expect add #t1:hover and inherit the style is there any other way?
You need to change the .hover class to include the :hover state as part of the class definition:
.hover {
...styles...
&:hover {
...hover state styles...
}
}
.someOtherClass {
.hover;
}
Example
In order to have the :hover styles generated correctly you need to connect .shadow and .shadow:hover via the & operator so they belong together:
.shadow {
/*normal styles*/
&:hover{
/* hover styles */
}
}
The rest can stay the same, because
#t1{
.shadow;
}
will now automatically generate both, the normal and the hover rules.
You can try it out here: Online-Less-Converter
Every additional block you add to .shadow via the & operator will automatically be applied to #t1 as well, so if you add another:
.shadow{
&:hover{}
&.foo{
/* another set of rules*/
}
}
#t1{
.shadow; /* this will now generate 3 ruleblocks for #t1*/
}
the .foo ruleblock will be generated for #t1 as well:
#t1{...}
#t1:hover{...}
#t1.foo{/* another set of rules*/}