Using LESS / CSS / Mixins and passing values from classes - css

I have this little snippet of css which i want to use transform and then add rotate into it but getting a failure... am i doing this wrong? Im new to LESS so sorry if im going about this wrong.
CSS:
.class {
&::before {
.transform(.rotate(#deg: 45deg));
}
&::after {
.transform(.rotate(#deg: -45deg));
}
}
MIXIN:
.transform(#string){
-webkit-transform: #string;
-moz-transform: #string;
-ms-transform: #string;
-o-transform: #string;
}
.rotate (#deg) {
-webkit-transform: rotate(#deg);
-moz-transform: rotate(#deg);
-ms-transform: rotate(#deg);
-o-transform: rotate(#deg);
}

So the way you have things set up above, you're basically passing the entire rotate mixin into the transform mixin. Which, if it actually knew how to parse, would end up with pretty garbled code. Instead, you can just use the top mixin and pass rotate into it. This is a better route, because it would allow you to use multiple transforms (which is a pretty common usage). Here's an example:
.transform(#string){
-webkit-transform: #string;
-moz-transform: #string;
-ms-transform: #string;
-o-transform: #string;
}
.class {
&::before {
.transform(rotate(45deg));
}
}
And if you wanted to call rotate and translate at a future time, it would be as easy as adding translate, as well.
.class {
&::before {
.transform(translateY(-50%) rotate(45deg));
}
}

Related

Processed SASS file missing vendor prefix from custom mixin

I am trying to convert from CSS to SASS and having trouble making a vendor prefix mixin for the transform property only. Any help or pointers is appreciated as I can't see where I am going wrong and I have tried Googling around with no luck.
Issue - Once SASS has processed it is stripping out the vendor prefix where it only includes the transform property.
Bellow is the sample output I am trying to achieve -
-webkit-transform: rotate(-45deg) translate(-9px, 6px);
-ms-transform: rotate(-45deg) translate(-9px, 6px);
transform: rotate(-45deg) translate(-9px, 6px);
Mixin -
#mixin transform-prefix($values...) {
#each $vendor in ('-webkit-', '-ms-', '') {
#{$vendor}transform: #{$values};
}
}
&.active .line1 {
#include transform-prefix(rotate(-45deg), translate(-9px, 6px));
}
Output -
.slide-nav-button.active .line1 {
transform: rotate(-45deg), translate(-9px, 6px);
}
I have also tried this mixin but it strips out the prefix -
#mixin transform-prefix($values...) {
-webkit-transform: $values;
-ms-transform: $values;
transform: $values;
}
I know I'm late to respond.
but I'm going to fix this by only moving transform: into the first line of mixin
look like this
#mixin myBox($rot) {
transform: $rot;
-webkit-transform: $rot;
-ms-transform: $rot;
}

How to create a 'transform' mixin in SCSS that uses several arguments?

I want to create a mixin for transform that has two arguments - translate and rotate. I've tried it in several ways but none of them works and I do not know why.
#mixin transform($transforms) {
-moz-transform: $transforms;
-o-transform: $transforms;
-ms-transform: $transforms;
-webkit-transform: $transforms;
transform: $transforms;
}
#mixin rotate ($deg) {
#include transform(rotate(#{$deg}deg));
}
#mixin translate($x, $y) {
#include transform(translate($x, $y));
}
In nav.scss I included it like this
#include transform(rotate(45));
#include transform(translate(0,9px));
It doesn't change anything in the presentation page.
Without mixin I simply use:
span:before {
transform: translateY(9px) rotate(45deg);
}
and it works but I want to achieve the same result with a mixin, but I don't know how. I started learning SASS a few days ago.
In general, I would recommend you use Autoprefixer to handle vendor prefixes as you'll often add way more prefixes than needed.
In the case of transform, you would probably be fine just adding
-webkit-transform: ...;
transform: ...;
Also, it becomes rather hard to handle when you need to deal with property values:
transition: transform 300ms;
// prefixed
-webkit-transition: -webkit-transform 300ms;
transition: -webkit-transform 300ms;
transition: transform 300ms;
transition: transform 300ms, -webkit-transform 300ms;
To answer your question I think the easiest way is to use argument-lists (allows any number of arguments to be passed) joined together in a space-separated list:
// Mixin
#mixin transform($transforms...) {
// combine the passed transforms into a space separated list
$transform-list: join($transforms, null, space);
// print out the transforms
-webkit-transform: $transform-list;
-moz-transform: $transform-list;
-ms-transform: $transform-list;
-o-transform: $transform-list;
transform: $transform-list;
}
// Include
span::before {
#include transform(
rotate(90deg),
translate(0,9px),
// ... add more transforms if you need
);
}
// CSS output
span::before {
-webkit-transform: rotate(90deg) translate(0, 9px);
-moz-transform: rotate(90deg) translate(0, 9px);
-ms-transform: rotate(90deg) translate(0, 9px);
-o-transform: rotate(90deg) translate(0, 9px);
transform: rotate(90deg) translate(0, 9px);
}
I don't think that you need to nest the mixins like that. You can take advantage of optional arguments and the keyword syntax:
#mixin transformNew($rotate: 0, $translate: translate(0, 0)) {
-moz-transform: rotate(#{$rotate}deg) $translate;
-o-transform: rotate($rotate) $translate;
-ms-transform: rotate(#{$rotate}deg) $translate;
-webkit-transform: rotate(#{$rotate}deg) $translate;
transform: rotate(#{$rotate}deg) $translate;
}
div {
#include transformNew($translate: translate(10px, 40px));
background: red;
}
The arguments for the mixin now have a default value, if you want to call it with only one argument. You can call arguments explicitly by using the keyword syntax. In my example I wanted only the second argument, so I did this: #include transformNew($translate: translate(10px, 40px));. If you only need the first argument, then it is enough to just pass the value, no need for the keyword.
If you need both arguments, you can simply pass them both. In your code, if you called the mixin twice, you had overwritten the first value with the second call.
That won't happen here. I also created a codepen for you to play around with the code.

WebStorm scss compiler error with transition/transform

I am trying to make a web page, and I need to use some images with transform/transition. But the Scss compiler from WebStorm gives me that error.
What can I do ? See in the image above.
For your #include you need to #mixin.
#MIXIN example:
#mixin protoName($someValue) {
-webkit-protoName: $someValue;
-moz-protoName: $someValue;
-ms-protoName: $someValue;
protoName: $someValue;
}
For yours code it can be something like this:
#mixin transform($val) {
-webkit-transform: $val;
-moz-transform: $val;
-ms-transform: $val;
transform: $val;
}
main {
.wrap {
#include transform(rotate(45deg) translate3d(0,0,0));
}
}
And your output look like this:
main .wrap {
-webkit-transform: rotate(45deg) translate3d(0,0,0);
-moz-transform: rotate(45deg) translate3d(0,0,0);
-ms-transform: rotate(45deg) translate3d(0,0,0);
transform: rotate(45deg) translate3d(0,0,0);
}
You can read more about it Here

Combine CSS3 browser compatibility tags to one

is it possible to combine all browser compatible tags like -webkit, -moz, -ms, -o for one styling? So for example:
#-webkit-keyframes pulsate,
#-moz-keyframes pulsate,
#-ms-keyframes pulsate,
#-o-keyframes pulsate,
keyframes pulsate {
from {opacity: 1 }
to { -webkit-transform: scale(1.5);
-moz-transform: scale(1.5);
-ms-transform: scale(1.5);
-o-transform: scale(1.5);
transform: scale(1.5);
opacity: 0 }
}
If it's not. Is there any document about that to read?
No, it's not possible. However, you can write just the unprefixed version and then use something like -prefix-free or Autoprefixer to add the prefixes for you. Or you can use a preprocessor. You can read a bit more about your options in this article.
If you do want to write everything by hand, the good news is that you don't need the -ms- prefix for animations. IE10 supports them unprefixed, while IE9 doesn't support them at all. So you only need to write this:
#-webkit-keyframes { to { -webkit-transform: scale(1.5); transform: scale(1.5); opacity: 0; } }
#-moz-keyframes { to { -moz-transform: scale(1.5); opacity: 0; } }
#-o-keyframes { to { -o-transform: scale(1.5); opacity: 0; } }
#keyframes { to { transform: scale(1.5); opacity: 0; } }
You don't necessarily need the from keyframe either. If it's missing it gets automatically generated from the default values or those already specified outside the keyframes.

Combining multiple "transform" entries in Less

I have two mixins which both convert to -webkit-transform:
.rotate(#deg) {
-webkit-transform: rotate(#deg);
}
.scale(#factor) {
-webkit-transform: scale(#factor);
}
When I use them together:
div {
.rotate(15deg);
.scale(2);
}
... they (as expected) show up as:
div {
-webkit-transform: rotate(15deg);
-webkit-transform: scale(2);
}
This doesn't seem to be valid CSS as the second has precedence over the first; the first is discarded. To combine transform entries it should be:
-webkit-transform: rotate(15deg) scale(2);
How can I accomplish such CSS to be generated by LESS, i.e. multiple transform entries that are combined correctly?
Starting from Less v1.7.0, merging property values with a space separator is possible and there is no need to club the two mixins into one.
The below Less code
.rotate(#deg) {
-webkit-transform+_: rotate(#deg);
}
.scale(#factor) {
-webkit-transform+_: scale(#factor);
}
div{
.rotate(45deg);
.scale(1.5);
}
will compile into the following CSS:
div {
-webkit-transform: rotate(45deg) scale(1.5);
}
Provide your transforms as arguments for a single mixin:
.transform(#scale,#rotate) {
-webkit-transform: #arguments;
}
I guess, you also could achieve to concatenate your separate mixins into one with the help of guards, but I'm not entirely sure;)
I think you are not able to achieve this in another way, since the parser would have to modify code afterwards which should not be possible.
I think there is a simple way over it, create a div container for the eleemnt, and apply first transform to the cntainer, leaving the second one for the element itself
I was having problems getting #arguments to work. I used the #rest variable which did the trick
LESS example:
.transform(#rest...) {
transform: #rest;
-ms-transform: #rest;
-webkit-transform: #rest;
}
.someClass{
.transform(translate3D(0,0,0),scale(1,1));
}
.otherClass{
.transform(translate3D(0,0,0),rotate(1,1));
}
.anotherClass{
.transform(rotate(1,1));
}
Output CSS:
.someClass {
transform: translate3D(0, 0, 0) scale(1, 1);
-ms-transform: translate3D(0, 0, 0) scale(1, 1);
-webkit-transform: translate3D(0, 0, 0) scale(1, 1);
}
.otherClass {
transform: translate3D(0, 0, 0) rotate(1, 1);
-ms-transform: translate3D(0, 0, 0) rotate(1, 1);
-webkit-transform: translate3D(0, 0, 0) rotate(1, 1);
}
.anotherClass {
transform: rotate(1, 1);
-ms-transform: rotate(1, 1);
-webkit-transform: rotate(1, 1);
}

Resources