How to get the nth element of #rest in Less? [duplicate] - less

I currently have -webkit specific attributes in my Less CSS sheet, I am trying to update them with mixins to add -moz attributes, like this:
.transition(#1) {
-webkit-transition: #1;
-moz-transition: #1;
}
div {
.transition(all .5s);
}
The example above works fine, however I also have things like that:
div {
-webkit-transition: border-color .3s, background .3s;
}
And I can’t call the mixin as .transition(border-color .3s, background .3s) because it has more arguments than defined in the mixin. So what I am doing at the moment is this:
.transition(#1) {
-webkit-transition: #1;
-moz-transition: #1;
}
.transition-2(#1, #2) {
-webkit-transition: #1, #2;
-moz-transition: #1, #2;
}
div {
.transition-2(border-color .3s, background .3s);
}
This is annoying, I need to add redundant code in my sheet any time I’m using a number of arguments not previously used before; and I have this problem with others CSS3 properties too, for example box-shadow when I need to add inset at the beginning.
Is there any way to declare mixins flexible in their number of arguments with Less, just like CSS3 properties are?

For this case, the redundant mixin code can be avoided using any one of the below mentioned options.
Option 1: (Simplest solution - thanks to seven-phases-max for highlighting the miss)
We can use semi-colon as a separator/delimiter for arguments and when we add a semi-colon at the end after specifying all properties that need to be transitioned (in a comma separated format), the whole part before it would be considered as one single argument.
Extract from the official Less website:
Using comma as mixin separator makes it impossible to create comma separated lists as an argument. On the other hand, if the compiler sees at least one semicolon inside mixin call or declaration, it assumes that arguments are separated by semicolons and all commas belong to css lists
.transition(#1) {
-webkit-transition: #1;
-moz-transition: #1;
}
div{
.transition(border-color .5s, background .3s, color .3s;);
}
So the above code when compiled would result in
div {
-webkit-transition: border-color 0.5s, background 0.3s, color 0.3s;
-moz-transition: border-color 0.5s, background 0.3s, color 0.3s;
}
Option 2:
Pass the input values to the mixin (how many ever specific properties need to be transitioned) within quotes. Within the mixin, use the ~ or the e() in-built functions to strip the quotes.
.transition(#1) {
-webkit-transition: ~"#{1}";
-moz-transition: ~"#{1}";
}
div {
.transition("border-color .5s, background .3s");
}
div#sample2 {
.transition("border-color .3s, background .3s, color .3s");
}
will produce the below CSS when compiled
div {
-webkit-transition: border-color .5s, background .3s;
-moz-transition: border-color .5s, background .3s;
}
div#sample2 {
-webkit-transition: border-color .3s, background .3s, color .3s;
-moz-transition: border-color .3s, background .3s, color .3s;
}
Option 3:
Less does allow creation of mixins which allow/accept variable number of inputs using the ... option. Hence you can use the same mixin as in your original code by adding the ... to the input variable and calling it as you had originally wanted.
.transition(#args...) {
-webkit-transition: #args;
-moz-transition: #args;
}
div {
.transition(border-color .5s, background .3s);
}
The above will compile successfully but the only problem is that it would produce the below output when compiled. As you can see, the problem is that the parameter values are space separated and not comma separated (as they should be for the CSS to work properly).
div {
-webkit-transition: border-color 0.5s background 0.3s;
-moz-transition: border-color 0.5s background 0.3s;
}
Ofcourse we could write complex replace functions using regular expressions but that would really make the code messy. Instead we could use loops and some built-in functions to achieve the required output (like shown below).
.transition(#args...) {
.loop-args(#argCount) when (#argCount > 0) {
.loop-args(#argCount - 1);
#arg: extract(#args, #argCount);
-webkit-transition+: #arg;
-moz-transition+: #arg;
}
.loop-args(length(#args));
}
div {
.transition(border-color .5s, background .3s, color .3s);
}
Basically what we are doing is use the ... to accept multiple arguments as input to the mixin and then loop over each argument and add it to the CSS property's value. The +: (merge function introduced in Less v1.5.0) is used to produce the comma separated output.
When compiled, it would produce the below output:
div {
-webkit-transition: border-color 0.5s, background 0.3s, color 0.3s;
-moz-transition: border-color 0.5s, background 0.3s, color 0.3s;
}

You could try
.transition(#1) {
-webkit-transition: #1;
-moz-transition: #1;
}
.transition-2(#1, #2) {
.transition(#1); // this includes all the stuff from transition(#1)
color:red; // additional stuff
}
As for your actual question, I dont believe that LESS itself has any sort of "rest" style arguments passing.

Related

Vue.js animation: Enter after Leave and not simultaneously

I have two components and a fade-in/fade-out animation set up for them.
For a brief moment, both components exist on the page at different opacities, and the scrollbar shows up and disappears.
Is there a way to avoid this? A way to start the fade-in animation only after the fade-out animation is done?
The Animation:
.view-leave-active {
transition: opacity 0.5s ease-in-out, transform 0.5s ease;
}
.view-enter-active {
transition: opacity 0.5s ease-in-out, transform 0.5s ease;
transition-delay: 0.5s; /* Increasing this doesn't seem to work */
}
.view-enter, .view-leave-to {
opacity: 0.5; /* It should be 1, but setting it to 0.5 allows you to see exactly what's happening */
}
.view-enter-to, .view-leave {
opacity: 1;
}
Any help would be very much appriciated!
To further elaborate on my comment: VueJS transition components support the mode property, where you can specify the sequence of transitions when toggling between two elements.
Since you do not want both elements to appear at the same time when one is transitioning in while the other is transitioning out, you should be using:
mode="out-in"
Based on the documentation:
out-in: Current element transitions out first, then when complete, the new element transitions in.

Rare IE10 bug: CSS animation of background-position fails with multiple backgrounds and percentage

This is a very specific bug - however, I would love for someone to show me a workaround! The bug basically consists in IE10 failing to do CSS animation of background-position when these two conditions are met at the same time:
Having multiple backgrounds
Setting background-position in percent
Here's a demo, compare Chrome with IE10:
http://codepen.io/dalgard/pen/LiyIK
You need to put a percentage sign after the zeros.
It must be so:
#keyframes move {
0% { background-position: 0%, 0%; }
100% { background-position: 0%, 100%; }
}

LESS: Mixin with a unique argument to manage css3 transitions

Using LESS CSS, I would like to simplify my code using Mixins to put "out" transitions declarations, but the following syntax is wrong. The problem is in the attribute #color-time definition that has 2 arguments:
.links-transition (#color-time:color 1s, border-color 1s)
{
-webkit-transition:#color-time;
-moz-transition:#color-time;
-ms-transition:#color-time;
-o-transition:#color-time;
transition:#color-time;
}
a
{
color:red;
.links-transition;
}
In official documentation I found that putting a ; at the end, teach LESS how to consider arguments, considering them separated by ;, so one argument in my case like this:
.links-transition (#color-time:color 1s, border-color 1s;)
Unfortunately this does not run. I think it depends since white space... is there a correct syntax to obtain the correct CSS without using 2 arguments in Mixin recall?
Thank you.
You can use string escaping and interpolation like this:
.links-transition (#arg:"color 1s, border-color 1s") {
#color-time: ~"#{arg}";
-webkit-transition:#color-time;
-moz-transition:#color-time;
-ms-transition:#color-time;
-o-transition:#color-time;
transition:#color-time;
}
a {
color:red;
.links-transition ("color 2s, border-color 2s");
}
it will return this CSS:
a {
color: red;
-webkit-transition: color 2s, border-color 2s;
-moz-transition: color 2s, border-color 2s;
-ms-transition: color 2s, border-color 2s;
-o-transition: color 2s, border-color 2s;
transition: color 2s, border-color 2s;
}
hope this does what you want.
For more ideas: there are some additinal approaches/solutions that you can find on SO, like this two for example:
Less CSS: Mixins with Variable Number of Arguments
Multiple properties are getting treated as separate arguments in mixins
Update: in LESS 1.4 beta it works the way you wanted to do it:
.links-transition (#color-time: color 1s, border-color 1s;) {
-webkit-transition:#color-time;
-moz-transition:#color-time;
-ms-transition:#color-time;
-o-transition:#color-time;
transition:#color-time;
}
a {
color:red;
.links-transition (color 2s, border-color 2s;);
}
has the same output as the above solution. Comma separated argunets are possible since 1.3.2, however they can apparently not include whitespaces.

Controlling rotation axis with webkit 3d transform

I'm creating a card-flip effect using webkit transformations. I have it working as I like in one section, where I have a DIV that rotates around its center axis giving the look of a card that is flipping over.
I now want to add this same effect to a page transition. I'm using the same CSS and HTML structure, but in this case I'm not getting an effect that rotates around a center axis.
Instead, it looks like the transformation is rotating along the y axis anchored to the left of the object rather than the center (so it looks like a door opening, rather than a card flipping).
I've been reading through the spec's but can't figure out which property controls the rotation axis' position. What do I need to add or change with this to get the flip working?
html structure:
<div id="frontbackwrapper">
<div id="front"></div>
<div id="back"></div>
</div>
and the css (.flip is being added via jQuery to start the effect)
#frontbackwrapper {
position: absolute;
-webkit-perspective: 1000;
-webkit-transition-duration: 1s;
-webkit-transform-style: preserve-3d;
-webkit-transition: 1s;
}
#frontbackwrapper.flip {
-webkit-transform: rotateY(180deg);
}
#frontbackwrapper.flip #front,
#frontbackwrapper.flip #back {
-webkit-transform: rotateY(180deg);
-webkit-transition: 1s;
}
#front, #back {
position: absolute;
-webkit-backface-visibility: hidden;
}
#back {
-webkit-transform: rotateY(180deg);
}
Try this on your wrapper
-webkit-transform-origin: 50% 0 0;
Though you may or may not have to have its width explicitly set.

webkit translateX animation is rolling back to initial position

I am trying to do a images gallery for mobile webkit,
The only way it is actually fast enough is using the hardware accelerated translateX .
My problem is that the div take back its initial position at the end of the animation. I add the slideGalLeft class cliking on the left button. to the animated div
You can see an example here, in the callback events section:
http://position-absolute.com/jqtouch/demos/main/#home
.slideGalLeft {
-webkit-animation-name: slideColis;
}
#-webkit-keyframes slideColis {
from { -webkit-transform: translateX(0%); }
to { -webkit-transform: translateX(-100%); }
}
Do not use webkit animation for this as it comes back to the default values once played.
Instead define
.slideGalleft{
-webkit-transition: -webkit-transform 1s linear;
-webkit-transform: translateX(0%);
}
and using Javascript, either set -webkit-transform: translateX(100%); or add a CSS class to your element which set the final transform value and webkit will animate it properly
Guillaume's answer is great. However, if you are looking for hardware acceleration, you must let the webkit engine know you want 3D rendering (what makes hardware acceleration active).
According to http://www.html5rocks.com/tutorials/speed/html5/#toc-hardware-accell, this is done by adding translateZ(0) to your rule, like so:
.slideGalleft{
-webkit-transition: -webkit-transform 1s linear;
-webkit-transform: translateX(0%) translateZ(0);
}
Follow Guillaume's advice beyond that.
Use:
-webkit-animation-fill-mode: none/backwards/forwards/both;
This allows you to define at what end of your animation the element remains when the animation is finished.
I was able to make it work by adding a "display:none" style on the finish of the animation. Use the following CSS:
.paused {
-webkit-animation-play-state: paused;
}
.hiddendiv {
display:none;
}
Then in your jQuery code:
$('div.sideimage').click(
function () {
$(this).removeClass("paused").delay(2000).queue(
function(next) {
$(this).addClass("hiddendiv");
next();
}
);
}
);
Should work!