In my CSS I have to create classes that make reference to a 'hair colour' and 'hairstyle'
I have written a mixin to help make my CSS writing more efficient:
#mixin hair($hair, $colour) {
.hair-#{$colour} .#{$hair} {
background:image-url("xsppsfhair#{$hair}#{$colour}.svg") center top no-repeat,
image-url("xsppsheadgrey.svg") center top no-repeat,
image-url("xsppsbhair#{$hair}#{$colour}.svg") center top no-repeat;
}
}
#include hair(spikyboy, blonde);
#include hair(curlyafroboy, blonde);
This produces the following CSS
.hair-blonde .spikyboy {
background: url('../images/xsppsfhairspikyboyblonde.svg?1348681869') center top no-repeat, url('../images/xsppsheadgrey.svg?1348834673') center top no-repeat, url('../images/xsppsbhairspikyboyblonde.svg?1348682005') center top no-repeat;
}
.hair-blonde .curlyafro {
background: url('../images/xsppsfhaircurlyafroblonde.svg?1348681869') center top no-repeat, url('../images/xsppsheadgrey.svg?1348834673') center top no-repeat, url('../images/xsppsbhaircurlyafroblonde.svg?1348682005') center top no-repeat;
}
This is great, but as I have a total combination of 35 hair colours and hair styles, I still end up with way too many #includes.
On this page, it says SASS has an #each which can be used to loop through lists. There is a further example here. However, both these examples only show looping through 1 list. Is it possible to loop through two lists?
I have tried many variations of my code, but none seem to work. I thought the following would definitely work, but I just get an error message about $colour being undefined.
$hairstyle: (red, blonde, ltbrown);
$haircolour: (red, blonde, ltbrown);
#each $hair in $haircolour, $colour in $haircolour {
.hair-#{$colour} .#{$hair} {
background:image-url("xsppsfhair#{$hair}#{$colour}.svg") center top no-repeat,
image-url("xsppsheadgrey.svg") center top no-repeat,
image-url("xsppsbhair#{$hair}#{$colour}.svg") center top no-repeat;
}
.girl.hair-#{$colour} #eyelash {
background: image-url("xsppseyelash#{$colour}.svg") center top no-repeat;
}
}
Could someone please give me some pointers as to what I am doing wrong?
What you need to do is create a loop inside the first loop (I've simplified a bit so it's easier to see):
#mixin style-matrix($colors, $styles) {
#each $s in $styles {
#each $c in $colors {
.#{$s} .#{$c} {
background:image-url("xsppsfhair-#{$s}-#{$c}.svg");
}
}
}
}
$colors: blonde, brunette, auburn;
$styles: beehive, pixie, bob;
#include style-matrix($colors, $styles);
You get this output:
.beehive .blonde {
background: image-url("xsppsfhair-beehive-blonde.svg");
}
.beehive .brunette {
background: image-url("xsppsfhair-beehive-brunette.svg");
}
.beehive .auburn {
background: image-url("xsppsfhair-beehive-auburn.svg");
}
.pixie .blonde {
background: image-url("xsppsfhair-pixie-blonde.svg");
}
.pixie .brunette {
background: image-url("xsppsfhair-pixie-brunette.svg");
}
.pixie .auburn {
background: image-url("xsppsfhair-pixie-auburn.svg");
}
.bob .blonde {
background: image-url("xsppsfhair-bob-blonde.svg");
}
.bob .brunette {
background: image-url("xsppsfhair-bob-brunette.svg");
}
.bob .auburn {
background: image-url("xsppsfhair-bob-auburn.svg");
}
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'm trying to create a LESS mixin into which I can pass a text string to be used to construct an svg file name and a png file name.
My first attempt is below. Perhaps you can see what I'm trying to do.
.make-bg-svg(#name){
#svg: ~"../images/#{name}.svg";
#png: ~"../images/#{name}.png";
height: 200px;
background: transparent url(~"#{svg}");
.no-svg & {
background: transparent url(~"#{png}") no-repeat;
}
}
// usage
.out-of-business {
.make-bg-svg('out-of-business');
}
Any help would be appreciated.
Updated
I just figured it out and updated the example above.
Just in case you don't need that many quotes, the following is equal:
.make-bg-svg(#name) {
#svg: ~"../images/#{name}.svg";
#png: ~"../images/#{name}.png";
height: 200px;
background: transparent url(#svg);
.no-svg & {
background: transparent url(#png) no-repeat;
}
}
// usage
.out-of-business {
.make-bg-svg(out-of-business);
}
I am looking to develop this mixin further, so I can pass multiple arguements through the mixin without having to re-create the include every time e.g:
NOT THIS:
#include main-container(red);
#include main-container(blue);
BUT THIS:
#include main-container(red, blue);
Current Code
#mixin main-container-bg($name){
&.#{$name}-bg{
background:url("/images/"#{$name}"-angle-bg.png") center 78px no-repeat;
}
}
I believe I need a for statement alongside an each statement to loop my mixin though all of the arguments in the #include later in the scss.
Any idea's?
Any help is welcomed.
-Neil
You could use the #each directive and pass a list to the mixin in this way
#mixin main-container-bg($listcolours) {
#each $colour in $listcolours {
&.#{$colour}-bg{
background:url(/images/#{$colour}-angle-bg.png) center 78px no-repeat;
}
}
}
div {
#include main-container-bg((red, blue));
}
The generated CSS is
div.red-bg {
background: url(/images/red-angle-bg.png) center 78px no-repeat;
}
div.blue-bg {
background: url(/images/blue-angle-bg.png) center 78px no-repeat;
}
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;
}
I'm kind of new to Sass, but I'm attempting to create a workflow for myself. I generate "color packs" for my theme designs and need to specify the following variables for my mixin. Is there a better way to do this?:
// folder,filename,extension,repeat,x-pos,y-pos
#mixin background ($folder:style1, $img:file, $type:png, $repeat:no-repeat, $x:0, $y:0) {
background-image: url(./images/#{$folder}/#{$img}.#{$type});
background-repeat: #{$repeat};
background-position: #{$x}px #{$y}px;
}
I'm inserting like so:
#nav {
#include background(style2,myimage,png,repeat-x,10,10);
}
which yields this:
#nav {
background-image: url(./images/style2/myimage.png);
background-repeat: repeat-x;
background-position: 10px 10px;
}
I'd prefer to use CSS shorthand when possible, but I ran into errors with the output. I'd appreciate any expert advice if this is not the best way to do it.
depending on how your packs are structured/applied you might be able to use a loop to generate a bunch of generic styles. See the documentation here: http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#id35
Do you really need 3 separate components to get your image url? wouldn't: $img and then setting that to /folder/img.ext be far easier?
Also, you don't need the #{} for repeat by the way.
I hope this is what you're after… the question is not very specific in terms of what you need the outcome to actually be.
Cheers,
Jannis
Update:
Okay, I see you've updated your question (thanks for that). I believe this could be a little better for general use:
#mixin background($imgpath,$position:0 0,$repeat: no-repeat) {
background: {
image: url($imgpath);
position: $position;
repeat: $repeat;
}
}
.testing {
#include background('/my/img/path.png');
}
This will then output:
.testing {
background-image: url("/my/img/path.png");
background-position: 0 0;
background-repeat: no-repeat;
}
Or you can use the shorthand version:
#mixin backgroundShorthand($imgpath,$position:0 0,$repeat: no-repeat) {
background: transparent url(#{$imgpath}) $repeat $position;
}
.testing2 {
#include backgroundShorthand('/my/img/path.png');
}
Which will generate:
.testing2 {
background: transparent url(/my/img/path.png) no-repeat 0 0;
}
Lastly if you want to specify your base path to your image directory separately you can do the following:
$imagedir:'/static/images/'; // define the base path before the mixin
#mixin backgroundShorthandWithExternalVar($filename,$position:0 0,$repeat: no-repeat) {
background: transparent url(#{$imagedir}#{$filename}) $repeat $position;
}
.testing3 {
#include backgroundShorthandWithExternalVar('filename.png');
}
This will then generate:
.testing3 {
background: transparent url(/static/images/filename.png) no-repeat 0 0;
}
Is this what you needed?
If not feel free to update the question or reply/comment.
some other sample:
path to the image:
$path--rel : "../images";
color
$black: #000000;
creating the mixin:
#mixin background-image($img, $background-position, $background-color) {
background-image: url('#{$path--rel}/#{$img}');
background-repeat: no-repeat;
background-position: $background-position;
background-color: $background-color ;
}
using the mixing:
.navbar-inverse {
#include background-image("header.png", right, $black);
}
result:
.navbar-inverse {
background-image: url("../images/header.png");
background-repeat: no-repeat;
background-position: right;
background-color: #000000;
}
take one $var and it will make it easier for you.
$list: pranav shah
=author-images
#each $author in $list
.photo-#{$author}
background: image-url("avatars/#{$author}.png") no-repeat
.author-bio
+author-images
css
.author-bio .photo-adam {
background: url('/images/avatars/adam.png') no-repeat;
}
.author-bio .photo-john {
background: url('/images/avatars/john.png') no-repeat;
}
.author-bio .photo-wynn {
background: url('/images/avatars/wynn.png') no-repeat;
}
.author-bio .photo-mason {
background: url('/images/avatars/mason.png') no-repeat;
}
.author-bio .photo-kuroir {
background: url('/images/avatars/kuroir.png') no-repeat;
}