Here is the following mixin:
.a () {background-image: url(one.png);}
now, I want .b inherits .a but it should add a second background image layer, eg:
.b {
.a; <-- import
background-image: url(second.png);
}
will generate:
.b {
background-image: url(one.png);
background-image: url(second.png); /* wins */
}
and not
.b {
background-image: url(one.png), url(second.png);
}
which is what I would like...
Is it possible to deal with this in LESS?
This is possible in LESS, just not exactly as you have it written. In order to achieve what you are looking for you would have to set up the images as variables, like so:
#a:url('../images/img-a.png') top left repeat;
#b:url('../images/img-b.png') top left repeat;
Then when you are defining a class or id you would add the variables in like so:
.someClass {
background:#a, #b;
}
Related
What I basically want to do
#gradientType: radial-gradient;
background: #gradientType(to bottom, ...)
I want to put a CSS Function, a gradient in this case (btw: are these called functions? I'm not sure) in a Less variable and call it later with the variable like #variable()?
Why? Maintainability!
I have a file variables.less where I want to change to gradient (ie) for a couple of places on the fly.
So instead of
.a { background: linear-gradient(..) }
.b { background: linear-gradient(..) }
.c { background: linear-gradient(..) }
I would have something like
.a { background: #myGradient(..) }
.b { background: #myGradient(..) }
.c { background: #myGradient(..) }
Linear gradients (linear-gradient(to bottom, red, blue)) and Radial gradients (radial-gradient(circle, red, blue)) kind of have the same syntax. So I would have four variables like gradientType, gradientOpts, gradientStart, gradientStop and change the gradient type based on the variable. This is just a simplified example.
To answer your question directly, you can use variable interpolation to achieve this.
#myGradient: radial-gradient;
.a { background: ~"#{myGradient}(to bottom, red, blue)"; }
.b { background: ~"#{myGradient}(to bottom, green, yellow)"; }
.c { background: ~"#{myGradient}(to bottom, orange, gold)"; }
But I would suggest using something like a parameterized mixin to handle things like this. Below is the code for a sample mixin which creates either a radial-gradient or linear-gradient depending on the input variable.
#gradType: linear-gradient;
.a { .background(#gradType; to bottom; red; blue); }
.b { .background(#gradType; to bottom; green; yellow); }
.c { .background(#gradType; to bottom; orange; gold); }
.background(#gradType; #gradOpts; #gradStart; #gradEnd){
& when (#gradType = linear-gradient){
background: linear-gradient(#gradOpts, #gradStart, #gradEnd);
}
& when (#gradType = radial-gradient){
background: radial-gradient(#gradOpts, #gradStart, #gradEnd);
}
}
The catch with using guarded mixins (like the above) is that when the #gradType variable has a value outside of the two possible ones (say conical-gradient was the value) then the code would just fail and will not cause any errors to be thrown. This would be a problem when you're writing a library that is going to be used by others (and so want to throw an error when the value is invalid). In such cases, you could change the code like given below. When this approach is used, Less compiler would throw an error when an invalid input value is provided for the #gradType variable.
#gradType: linear-gradient;
.a { .background(#gradType; to bottom; red; blue); }
.b { .background(#gradType; to bottom; green; yellow); }
.c { .background(#gradType; to bottom; orange; gold); }
.background(linear-gradient; #gradOpts; #gradStart; #gradEnd){
background: linear-gradient(#gradOpts, #gradStart, #gradEnd);
}
.background(radial-gradient; #gradOpts; #gradStart; #gradEnd){
background: radial-gradient(#gradOpts, #gradStart, #gradEnd);
}
I have one mixins inside another mixins
.background(#url: #base-url , #repeat: repeat, #pos1: left, #pos2: center, #color: transparent){
background:#arguments;
}
Which is used in :
.divider{
overflow:hidden;
.background(#url: url("#{base-url}/divider.png") , #repeat: repeat-x, #pos2: bottom);
}
.class{
.divider;
}
Is it possible to change only #pos2 in .divider mixins?
Of course you can, add parameter to your .divider mixin and use that parameter as such:
.divider(#pos2: bottom) {
overflow:hidden;
.background(url("#{base-url}/divider.png"), repeat-x, #pos2);
}
.class{
.divider(top); // you can use whatever value you want, or ignore it to use the default value 'bottom'
}
I want to create something like a themepicker. I use LESS.css.
LESS.css has a variable which contains the main colors :
#colorOne: #222;
#colorTwo: #fff;
#darkGradientStart: lighten(#colorOne, 10%);
#darkGradientStop: lighten(#colorOne, 5%);
#lightGradientStart: #colorTwo;
#lightradientStop: darken(#colorTwo, 7%);
I want to change them if the tag has the color-class like this:
<body class='theme-blue'>
then I have written this in my less.css (after the default variables)
.theme-blue{
#colorOne: blue;
}
but it still uses the default #222. It is not overwritten.
How can I solve this problem?
Thanks
You cannot overwrite variables in LESS (within the same scope). The documentation specifically says:
Note that variables in LESS are actually ‘constants’ in that they can only be defined once.
For what you desire, you need to do a mixin:
Example LESS Code
.colorDefs(#c1: #222, #c2: #fff) {
#colorOne: #c1;
#colorTwo: #c2;
#darkGradientStart: lighten(#colorOne, 10%);
#darkGradientStop: lighten(#colorOne, 5%);
#lightGradientStart: #colorTwo;
#lightGradientStop: darken(#colorTwo, 7%);
}
.theme-blue {
//import color definitions
.colorDefs(blue, yellow);
// use them
color: #colorOne;
background-color: #colorTwo;
.gradient1 {
background-image: linear-gradient(top, #darkGradientStart, #darkGradientStop);
}
.gradient1 {
background-image: linear-gradient(top, #lightGradientStart, #lightGradientStop);
}
}
.theme-green {
//import different color definitions
.colorDefs(green, red);
// use them
color: #colorOne;
background-color: #colorTwo;
.gradient1 {
background-image: linear-gradient(top, #darkGradientStart, #darkGradientStop);
}
.gradient1 {
background-image: linear-gradient(top, #lightGradientStart, #lightGradientStop);
}
}
Example CSS Output
.theme-blue {
color: #0000ff;
background-color: #ffff00;
}
.theme-blue .gradient1 {
background-image: linear-gradient(top, #3333ff, #1a1aff);
}
.theme-blue .gradient1 {
background-image: linear-gradient(top, #ffff00, #dbdb00);
}
.theme-green {
color: #008000;
background-color: #ff0000;
}
.theme-green .gradient1 {
background-image: linear-gradient(top, #00b300, #009a00);
}
.theme-green .gradient1 {
background-image: linear-gradient(top, #ff0000, #db0000);
}
Solving 4K (i.e. a lot of) Lines of Code
ed1nh0 commented about having 4K lines of code using the color variables, and not being able to "put that in a mixin." Let me make a few comments on that:
If 4K lines of code depend upon the body class to define the colors, then it is probably best to split each color into its own css file, and only load that file as needed (i.e. not grouping every code color into one file). This then calls into question whether you really want to be controlling color by body class.
Regardless of whether one does what is recommended in 1., I believe one could still handle this with 4K of lines that use the colors. I believe the issue is not in using a mixin to define the color values themselves (i.e. not 4K lines of color variable definitions), but rather in the 4K lines of properties, classes, etc. that need repeating that are using the colors. But that repetition can be handled just as easily by wrapping it all in a mixin also. So my original answer above could be abstracted further to this (note that .colorDefs is the same as above and not repeated here):
LESS
.themeProperties() { // Imagine inside here the 4K lines of code
// use them
color: #colorOne;
background-color: #colorTwo;
.gradient1 {
background-image: linear-gradient(top, #darkGradientStart, #darkGradientStop);
}
.gradient1 {
background-image: linear-gradient(top, #lightGradientStart, #lightGradientStop);
}
}
.theme-blue {
//import color definitions
.colorDefs(blue, yellow);
.themeProperties(); //4K lines repeated here
}
.theme-green {
//import different color definitions
.colorDefs(green, red);
.themeProperties(); //4K lines repeated here
}
The above does assume that there are not differences in how the variables are used by the properties, just what the values of those properties are. If there were any "differences," then some tweaking mixins may need to be done for certain situations, but the concept should still hold.
What you are doing would get compiled like this in css:
.theme-blue{
#222: blue;
}
See why it doesn't work now? :)
If you are trying to override the color style, you should do it the usual css way:
.theme-blue{
color: blue;
}
#blue:#0000FF;
#green:#00FF00;
.theme-blue {
color:#blue;
}
.theme-green {
color:#green;
}
This is in particular reference to the Compass spriting framework
Following the documentation here http://compass-style.org/help/tutorials/spriting/#magic-selectors
I have used this method so that this:
selectors/ten-by-ten.png
selectors/ten-by-ten_hover.png
.edit {
#include selectors-sprite(ten-by-ten);
}
generates:
.selectors-sprite, .edit {
background: url('/selectors-sedfef809e2.png') no-repeat;
}
.edit {
background-position: 0 0;
}
.edit:hover, .edit.ten-by-ten_hover, .edit.ten-by-ten-hover {
background-position: 0 -20px;
}
which is really great. However, I was wondering If/How in another instance I could include the "ten-by-ten.png" image from the sprite without including the magically attached hover state?
i.e.
I want this:
.view {
background: url('selectors/ten-by-ten.png') no-repeat;
}
Where hovering over this icon does not trigger the :hover state (ten-by-ten_hover.png).
But I was wondering if there was a way to achieve this still referencing the sprited image?
Thanks for any help/advice.
You can add sprites directly to an element using the #extend directive. The syntax is #extend .folder prefix - sprite name - state (ie, .selectors-sprite-name_hover):
.view {
#extend .selectors-ten-by-ten
}
&:hover {
#extend .selectors-ten-by-ten_hover
}
&:active {
#extend .selectors-ten-by-ten_active
}
.selectors-ten-by-ten_hover, .selectors-ten-by-ten_active, etc returned class not found errors for me in Compass.
This worked however:
.viewHover { #extend .selectors-ten-by-ten:hover; }
.viewActive { #extend .selectors-ten-by-ten:active; }
I want to use the following style in GWT client bundle:
.myClass tr:hover {
background: url("myImage.png") 185px 2px no-repeat;
}
I declared the image as follows:
#Source("resources/myImage.png")
#ImageOptions(repeatStyle = RepeatStyle.None)
ImageResource myImage();
and changes the style to:
#sprite .myClass tr:hover {
gwt-image: "myImage";
background-position: 185px 2px;
}
But it does not work. There are several images in the generated XYZ.cache.png. So if I change the background-position in firebug I see the complete image bundle.
How can I move the background image to the right position?
#sprite .myClass tr:hover {
gwt-image: "myImage";
}
div.myClass tr:hover{
background-position: 185px 2px;
}
As you noticed, gwt-image will be default remove 'background-position' along with some other ones. To override the default position of 0 0, add a more specific css rule with the position you desire.
The generated width property of ImageSprite does not work because the width of tr element is fix. It is better zu create a td with an image element (as ImageResource) on the right side of table row. CSS looks like:
<code>
div.myClass img {
visibility: hidden;
}
div.myClass tr:hover img {
visibility: visible;
}
</code>
So solution assumes there are no more images in the table.