I made this less loop to generate css code needed to a specific task.
(included at bottom of page).
Is it safe to say that writing less-loops reduce development time but also generates unnecessary code styles?
I can see a lot of benefits of using this technique but none of them include performance optimization aspects.
#items : 12;
#color-base : red;
#slice : 30deg;
.looop (#i) when (#i>0){
.looop(#i - 1);
li:nth-child(#{i}){
transform: rotate((#i*#slice)-30) skewY(-2*#slice);
.text {
background : spin(#color-base, 30);
}
}
}
.looop(#items);
You can optimize it a bit:
#items : 12;
#excluded-items: 1, 2, 5;
#color-base : red;
#slice : 30deg;
.looop (#i) when (#i>0) {
.looop(#i - 1);
li:nth-child(#{i}){
transform: rotate((#i*#slice)-30) skewY(-2*#slice);
}
}
.looop(#items);
li {
.text {
background : spin(#color-base, 30);
}
}
Related
My task is to convert all less to scss files . I used npm dependency "less-scss-convertor" for the same .
But when i am creating scss files i am getting these three errors repeatedly .
1st scenario -
In my common.scss i have defined
$S: "all and (max-width: 767px)";
in some other scss file i am using -
#media $S {
.test-class {
font-size: 8px;
}
}
error1 - "media query expression must begin with '('"
2nd scenario -
In color.scss -
#mixin test-class("black", 1, 2);
#mixin generate-color-class($color, $arg1,
$arg2) when ($arg2 > 0) {
.${color}-${arg1} {
color: ~"${${color}-${arg1}}";
}
#include generate-color-class($color,
($arg1 + 1), ($arg2 - 1));
}
error 2 - Invalid CSS after "...te-color-class(": expected ")", was '"black", 1, 2);'
3rd scenario -
#mixin vertical-translate($percent) {
-ms-transform: translateY($percent);
-webkit-transform: translateY($percent);
transform: translateY($percent);
}
.Headerclass {
#include vertical-translate (-50%);
}
error 3 - no mixin named vertical-translate
Any pointers where i am going wrong ?
1st scenario
You need to use the interpolation syntax of Sass: #{$var}
About Interpolation
#media #{$S} {
.test-class {
font-size: 8px;
}
}
2nd scenario
See how mixins work with Sass. It's very different from Less.
About Mixins
3rd scenario
It works for me. Maybe you should remove the white space.
vertical-translate(-50%);
I have noticed that a piece of Less I thought was working as expected is not actually generating all the styles I need - my for loop is not working.
The less in question is:
.for(#list, #code) {
& {
.loop(#i:1) when (#i =< length(#list)) {
#value: extract(#list, #i);
#code();
.loop(#i + 1);
}
.loop();
}
}
.role-variants(#variants, #props){
.for(#variants, {
.security_class_#{value} {
#props();
}
});
}
#admin-roles: admin, admin_manager, admin_user, admin_manager_user;
html{
body{
&.admin{
.role-variants(#admin-roles, {display: block;});
}
}
}
on http://less2css.org/ this compiles correctly, generating the classes I expect.
When I compile locally, I only get the following class:
html body.admin .security_class_admin {
display: block
}
My for loop is not working locally, though it seems to be valid and working using the less compiler. Any ideas on how I can modify it to work locally, or perhaps I need to update my environment to a specific version, though it seems to be up to date.
Thanks again for your help.
Jamie
my loop was malformed - this loop now works as expected:
.for(#list, #code) {
& {
.loop(#i) when (#i > 0) {
#value: extract(#list, #i);
#code();
.loop((#i - 1));
}
.loop(length(#list));
}
}
Unfortunately I'm having to go back through my CSS and re-write some styling to make sure it works for IE8 (client needs it). I have a function that adds z-index to elements,
.mobile-pane {
....
....
/* won't work for IE8 */
/* #for $i from 1 through 4 {
&:nth-child(#{$i}) {
z-index: #{$i};
}
} */
&:first-child {
z-index: 1;
& + .mobile-pane {
z-index: 2;
& + .mobile-pane {
z-index: 3;
& + .mobile-pane {
z-index: 4;
}
}
}
}
}
As you can see, the function is clearly commented out. However (I'm using CompileSASS for Visual Studio), in the output window, I see this:
CompileSass 8:35:55 AM:Sass compilation failed for main.
Error: C:/projectFolder/source/sass/components/header:219: unbound variable $i
In Google WebDev, I'm seeing the function's output, ....:nth-child(2) { z-index:2; } ... and so on, not
.mobile-pane:first-child+.mobile-pane {
z-index: 2;
}
, as I would expect. I'm some-what new to SCSS, so I don't know if this is a known problem, or if CompileSass is not reading the comments correctly.
I understand that I could leave the function in, and just have the IE8 z-index CSS below it, and it will still work, but I wanted to leave the function, in case in the future IE8 was no longer a requirement.
My question - is it normal for SCSS to do this, or is it the extension?
Accessing variables within CSS comments is expected, declaring variables within comments is not.
$i: 100;
/* commenting about #{$i} */
Output:
/* commenting about 100 */
Meanwhile:
/*
$j: 100;
commenting about #{$j} */
Raises an error:
Undefined variable: "$j".
If you want to comment out blocks of code that access variables that don't exist due to being commented out, use double slashes instead:
$j: 100;
.foo {
// content: $j;
}
I built a mixin to handle icon sprites in my solution, which basically loops through a list of class names and sets the background position relative to it's index in the sprite
#icon_size-small: 16;
#icon_size-medium: 24;
#icon_size-large: 32;
.commonIcons(#iconSize, #y: 1, #x: 0) {
#posY: (#iconSize * #y);
#posX: (#iconSize * #x);
background: url('images/icons/commonIcons#{iconSize}x#{iconSize}.png') -#posX + 0px -#posY + 0px no-repeat;
height: #iconSize + 0px;
width: #iconSize + 0px;
}
I then call this mixin inside of another one like this
.icons_list-small(#modifier, #x) {
.icon-clock { .commonIcons(#icon_size-small, 1, #x); }
.icon-checkmark { .commonIcons(#icon_size-small, 2, #x); }
.icon-stop { .commonIcons(#icon_size-small, 3, #x); }
etc
and the whole thing is then actually used like this
.small-button {
.icons_list-small(0);
}
So the background position is calculated based on which .icons_list-xxx I use, and the parameter I'm sending in in .small-button decides which y-index is shown (the sprite has 3 variants in a row).
This all works fine when generated as children inside of .small-button, but I've now run up against a case where I need the list generated as sibling selectors to .small-button (giving me .small-button.icon-clock { })
Implementing it like these examples gives me parse errors, understandably:
.small-button.icons_list-small(0);
or
.small-button {
&.icons_list-small(0);
}
So the question: does anyone have a suggestion for what I can do in this instance?
Thanks for any help guys!
Edit: I found a fix myself, but if anyone has a more elegant solution I'd be happy to hear it!
What I did was extend the .icons_list-small mixin like this
.icons_list-small(#modifier, #x) {
#{modifier}.icon -clock { .commonIcons(#icon_size-small, 1, #x); }
Which is then called like this
.icons_list-small(~".icon--inverted", 0);
One solution would be to use the & in your mixin:
.icons_list-small(#x) {
&.icon-clock {
.commonIcons(#icon_size-small, 1, #x);
}
&.icon-checkmark {
.commonIcons(#icon_size-small, 2, #x);
}
&.icon-stop {
.commonIcons(#icon_size-small, 3, #x);
}
}
And when you want to obtain the previous behaviour, to use:
.small-button {
& * {
.icons_list-small(0);
}
}
Which would generate
.small-button *.icon-clock {...}
...
that is equivalent (in CSS) to
.small-button .icon-clock {...}
...
And using it without the & *:
.small-button {
.icons_list-small(0);
}
will generate:
.small-button.icon-clock {...}
...
Say I have three separate color schemes that are used on various pages in a site. Each color has a a light, medium and dark tint defined, and the color scheme is defined by a class in the body. Assume that the "red" color scheme is the default. Like this:
Color Definitions:
#red-lt: #121;
#red-md: #232;
#red-dk: #343;
#green-lt: #454;
#green-md: #565;
#green-dk: #676;
#blue-lt: #787;
#blue-md: #898;
#blue-dk: #909;
Basic Default Style Example
body { background-color: #red-dk;
#container { background-color: #red-md;
p { color: #red-dk; }
}
}
Different Color Scheme Style Example
body.green { background-color: #green-dk;
#container { background-color: #green-md;
p { color: #green-dk; }
}
}
I'd like to use variables so that I don't have to re-write all of the color variations for each scheme, so that I can just write something like this:
body.[color-var] { background-color: #[color-var]-dk;
#container { background-color: #[color-var]-md;
p { color: #[color-var]-dk; }
}
}
…but I can't quite wrap my head around how to accomplish that. Help…?
Use interpolation and escaping, parentheses in the selector and parametric mixins to get the desired effect:
Dynamic variables by interpolation: In a string, "#{variable}" is replaced with the value of the variable. They can also be nested: Given #{#{var}-foo} and #var: bar;, the result is "barfoo".
The resulting value is quoted. To remove these quotes, prefix ~.
Dynamic selectors by Selector interpolation: body.#{var} turns into body.bar.
Example:
#red-md: #232;
#red-dk: #343;
.setColor(#color) {
body.#{color} { background-color: ~"#{#{color}-dk}";
#container { background-color: ~"#{#{color}-md}";
p { color: ~"#{#{color}-md}"; }
}
}
}
.setColor(~"red"); // Escape to prevent "red" turning "#FF0000"
//.setColor(~"blue"); etc..
Turns into:
body.red {
background-color: #334433;
}
body.red #container {
background-color: #223322;
}
body.red #container p {
color: #223322;
}
Note: When the answer was originally written, selector interpolation did not exist. See the previous revision for the solution if you're working with an old LESS compiler (before LESS 1.3.1a). Support for the old method will be dropped in LESS 1.4.0.
If those values really follow a predictable format like that, seems like a perfect case for a parametric mixin:
Less:
#red: #232;
#green: #565;
#blue: #898;
.theme (#color) {
background-color: #color - #111;
#container {
background-color: #color;
p { color: #color + #111; }
}
}
body.red {
.theme(#red);
}
Compiled CSS:
body.red{background-color:#112211;}
body.red #container{background-color:#223322;}
body.red #container p{color:#334433;}
I know this question is pretty old, but for those that come to this post my answer maybe can help
I`m not really sure for what you want to use this, but one of my suggestion is based on #ScottS answer. On my real world, I need to create a web app, where it would show several brands and each brand have their own text color, background and so on... so I started to chase a way to accomplish this in LESS, what I could easily do on SASS and the result is below:
LESS
// Code from Seven Phase Max
// ............................................................
// .for
.for(#i, #n) {.-each(#i)}
.for(#n) when (isnumber(#n)) {.for(1, #n)}
.for(#i, #n) when not (#i = #n) {
.for((#i + (#n - #i) / abs(#n - #i)), #n);
}
// ............................................................
// .for-each
.for(#array) when (default()) {.for-impl_(length(#array))}
.for-impl_(#i) when (#i > 1) {.for-impl_((#i - 1))}
.for-impl_(#i) {.-each(extract(#array, #i))}
// Brands
#dodge : "dodge";
#ford : "ford";
#chev : "chev";
// Colors
#dodge-color : "#fff";
#ford-color : "#000";
#chev-color : "#ff0";
// Setting variables and escaping than
#brands: ~"dodge" ~"ford" ~"chev";
// Define our variable
.define(#var) {
#brand-color: '#{var}-color';
}
// Starting the mixin
.color() {
// Generating the loop to each brand
.for(#brands); .-each(#name) {
// After loop happens, it checks what brand is being called
.define(#name);
// When the brand is found, match the selector and color
.brand-#{name} & {
color: ##brand-color;
}
}
}
.carColor {
.color();
}
Te result will be:
CSS
.brand-dodge .carColor {
color: "#fff";
}
.brand-ford .carColor {
color: "#000";
}
.brand-chev .carColor {
color: "#ff0";
}
This is very tricky and I had to use several elements to get what I needed, first used a set of mixins provided by Seven Phase Max and you can find it here and than, the #ScottS answer was the piece that was missing fro my puzzle... hope this helps you and others that need to create a set of Variables to be part of another variable and create a more dynamic less file.
You can copy my entire code and test at http://lesstester.com/
Try this
#red-lt: #121;
#red-md: #232;
#red-dk: #343;
#green-lt: #454;
#green-md: #565;
#green-dk: #676;
#blue-lt: #787;
#blue-md: #898;
#blue-dk: #909;
#color: 'red-lt';
div{
background: ##color;
border: 1px solid lighten(##color,20%);
}
To my knowledge, variable variable names are not supported in LESS. You could however restructure your declarations in a more semantic manner:
/* declare palette */
#red-lt: #121;
#red-md: #232;
#red-dk: #343;
#green-lt: #454;
#green-md: #565;
#green-dk: #676;
#blue-lt: #787;
#blue-md: #898;
#blue-dk: #909;
/* declare variables based on palette colors */
#lt: #red-lt;
#md: #red-md;
#dk: #red-dk;
/* ...and only use them for main declarations */
body { background-color: #dk;
#container { background-color: #md;
p { color: #dk; }
}
}
This should let you switch between palettes quite painlessly by avoiding explicit color references.