Using a Mixin as an Argument in Another Mixin in LESS CSS

Is it possible to pass the declaration of one mixin or style to another mixin as an input parameter?

Consider the following example involving animation keyframes. This is how keyframes are typically defined in pure CSS:

@-moz-keyframes some-name
{
    from { color: red; }
    to { color: blue; }
}

@-webkit-keyframes some-name
{
    from { color: red; }
    to { color: blue; }
}

@keyframes some-name
{
    from { color: red; }
    to { color: blue; }
}

The idea is to simplify these declarations using mixins, so we could have something like this:

.keyframes(name, from, to)
{
    // Here, we need to somehow mimic the structure
    // shown in the example above
}

// Define one animation
.my-from() { color: red; }
.my-to() { color: blue; }
// The following approach does not work because you cannot pass a mixin as a parameter
// in the way shown here, thus I am seeking a solution to this issue
.keyframes('some-name', .my-from, .my-to);

// Define another animation
.another-from() { font-size: 1em; }
.another-to() { font-size: 2em; }
.keyframes('another-name', .another-from, .another-to);

The system will consist of various modules that can be dynamically added and removed from the application. Importing via @import is not applicable since the output CSS is generated on-the-fly based on module information and corresponding LESS styles, along with core LESS dependencies such as mixin libraries.

Note: It would suffice for me if you know a method to pass class definitions instead of mixins. In the example provided, it would involve passing .my-from instead of .my-from(), and so on.

Answer №1

Streamlined approach for LESS 1.7.0+

The latest 1.7.0 update simplifies things significantly by introducing the ability to create rulesets and utilize variables in setting keyframes.

Now, it's possible to pass a mixin through a parameter by a ruleset or directly pass in the property strings themselves. Here's an example:

LESS (using 1.7)

.keyframes(@name, @from, @to) {
    @frames: {
        from { @from(); }
        to { @to(); }
    };
    @pre: -moz-keyframes;
    @-moz-keyframes @name
    {
       @frames();
    }

    @-webkit-keyframes @name
    {
       @frames();
    }

    @keyframes @name
    {
       @frames();
    }
}

.keyframes(testName, {color: red; .myMix(0);}, {color: blue; .myMix(1);});

.myMix(@value) {opacity: @value;}

In this setup, both a property setting and a mixin call are passed, resulting in this output:

CSS Output

@-moz-keyframes testName {
  from {
    color: red;
    opacity: 0;
  }
  to {
    color: blue;
    opacity: 1;
  }
}
@-webkit-keyframes testName {
  from {
    color: red;
    opacity: 0;
  }
  to {
    color: blue;
    opacity: 1;
  }
}
@keyframes testName {
  from {
    color: red;
    opacity: 0;
  }
  to {
    color: blue;
    opacity: 1;
  }
}

This method showcases passing rulesets enclosed in brackets {...}, which are then called using @from() and @to()(similar to calling a mixin). Additional rule sets like @frames are utilized within the keyframes definitions.

More Generically

This snippet demonstrates passing a private mixin to another mixin and then calling it from that secondary mixin:

LESS

.someMixin(@class; @expectedMixin) {
    .@{class} {
      @expectedMixin();
      .myPrivateMix(0.6);
      test: 1;
    }
}

.someMixin(newClass; {.myClass;});

.myClass {
  .myPrivateMix(@value) {opacity: @value;}
}

CSS Output

.newClass {
  opacity: 0.6;
  test: 1;
}

Previous version information is retained below.

Detailed guide on utilizing LESS 1.4.0+

An elaborate process is involved, specifically defining mixins with pattern matching, to effectively use them in modules. Here's a breakdown:

Create Module Mixins

Define module-specific animations as shown below:

// define one animation in a module
.from(my-from){ color: red; }
.to(my-to) { color: blue; }

// define one animation in another module
.from(another-from){ font-size: 1em; }
.to(another-to) { font-size: 2em; }

If individual mixin names are desired, follow this structure:

// define one animation in a module
.my-from(){ color: red; }
.my-to() { color: blue; }

.from(my-from){ .my-from() }
.to(my-to) { .my-to() }   

// define one animation in another module
.another-from(){ font-size: 1em; }
.another-to() { font-size: 2em; }

.from(another-from){ .another-from() }
.to(another-to) { .another-to() }

This setup allows access to the straight mixin .my-from() and enables later mixins to access the singular .from() group via pattern matching.

Define Main Mixin

For the @keyframes scenario, a specific approach is required to ensure accurate application of the animations. The following code blocks illustrate this:

LESS 1.3.3 or under

// define mixin in mixin file

.keyframes(@selector, @name, @from, @to) {
...

LESS 1.4.0+

.keyframes(@selector, @name, @from, @to) {
...

Utilize the Mixin

To incorporate your defined mixin, use the following syntax:

.keyframes('.changeColor', some-name, my-from, my-to);
.keyframes('.changeFontSize', another-name, another-from, another-to);

Observe Desired Output


...

Answer №2

Easier Animation Code

I recently streamlined ScottS' method by separating @keyframes from -animation:

.keyframes(@name, @from, @to) {
    @newline: `"\n"`;
    .Local(@x){};
    .Local(@x) when (@x="") {(~"}@{newline}/*"){a:a}/**/};

    .setVendor(@pre, @vendor) {
        (~"@{pre}@@{vendor}keyframes @{name} {@{newline}from") {
            .from(@from);
        }
        to {
            .to(@to);
        }
        .Local(@vendor);
    }
    .setVendor(""            , "-webkit-");
    .setVendor(~"}@{newline}",    "-moz-");
    .setVendor(~"}@{newline}",      "-o-");
    .setVendor(~"}@{newline}",         "");
}

.animation(...) {
  -webkit-animation: @arguments;
     -moz-animation: @arguments;
       -o-animation: @arguments;
          animation: @arguments;
}

Usage Example:

.from(a1-from){ width: 10px; }
.to(a1-to) { width: 20px; }
.keyframes(a1-animation, a1-from, a1-to);


.selector {
    // additional CSS styles
    .animation(a1-animation 1s infinite linear);
}

Resulting Output:

@-webkit-keyframes a1-animation {
from {
  width: 10px;
}
to {
  width: 20px;
}
}
@-moz-keyframes a1-animation {
from {
  width: 10px;
}
to {
  width: 20px;
}
}
@-o-keyframes a1-animation {
from {
  width: 10px;
}
to {
  width: 20px;
}
}
@keyframes a1-animation {
from {
  width: 10px;
}
to {
  width: 20px;
}
}
/* {
  a: a;
}
/**/


.selector {
  // some other css
  -webkit-animation: a1-animation 1s infinite linear;
  -moz-animation: a1-animation 1s infinite linear;
  -o-animation: a1-animation 1s infinite linear;
  animation: a1-animation 1s infinite linear;
}

Small Issue:

We now have cleanly separated animations from @keyframes, but there is an unwanted:

/* {
  a: a;
}
/**/

This should not be a problem since most of us run CSS files through minifiers that remove comments anyway.

Answer №3

If you're looking for a solution to create CSS keyframes, you should check out this tool I developed: https://github.com/thybzi/keyframes

Key features:

  • Supports cross-browser keyframes generation across major browsers such as Firefox, Chrome, Safari, Opera, and IE
  • Allows for up to 16 timepoints in each keyframes rule, with room for expansion if necessary
  • Enables the use of mixins, variables, and functions for custom styling at specific timepoints
  • Separates keyframes from animation rules, allowing for versatility in animation application:
    • Multiple animation rules can utilize the same keyframe with varying timing and repetition settings
    • Multiple animations can be employed within a single animation rule
    • Animations can be applied within any parent selector without being created there
  • Produces lightweight and organized LESS code for efficient styling

Getting started:

// Define styles for animation stages
.keyframes-item(fadeIn, 0%) {
    opacity: 0;
}
.keyframes-item(fadeIn, 100%) {
    opacity: 1;
}
// Generate keyframes
.keyframes(fadeIn);

// Apply animation effect to a fading block over 1.5 seconds
.myBlock {
    .animation(fadeIn 1.5s);
}

Answer №4

The proper utilization of mixins doesn't involve following that approach.

Instead, consider implementing the following:

.style-one { ... }
.style-two { ... }
.final-style {
    .style-one;
    .style-two;
    font-family: 'Arial';
    color: teal;
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Display one div and conceal all others

Currently, I am implementing a toggle effect using fadeIn and fadeOut methods upon clicking a button. The JavaScript function I have created for this purpose is as follows: function showHide(divId){ if (document.getElementById(divID).style.display == ...

What could be the reason for the presence of three pixels of white space below this particular table

My table is supposed to have a fixed height of 146px, but there seems to be an extra row of three pixels at the bottom. I've tried various methods to remove any unwanted spacing or padding, but nothing has worked so far. The only solution I found was ...

Blog entries alternating between a pair of distinct hues

I want to create a design where each post container has a different color from the one next to it. Essentially, I would like the containers to alternate between two distinct colors. The left side shows how it currently appears, while the right side depict ...

Arranging divs in a row using jQuery sortable technique

Greetings! I have been attempting to achieve horizontal sorting for two divs but have encountered a couple of issues. Firstly, the divs do not align correctly upon initial page load and secondly, while they can be dragged around, the sortable functionality ...

Checking for the existence of a CSS selector in Jasmine test suite

Testing out the latest version of Jasmine and Karma with an AngularJS instance. I attempted: expect(element('a.topic-heading-link-10')).toBeDefined(); However, I received this response: expect undefined toBeDefined undefined http://example.co ...

Customize the appearance of the 'Update' or 'Publish' WordPress button using code from functions.php or style.css

Current issues with permissions to core files and stylesheets are prompting me to seek ways to customize the LOCATION and APPEARANCE of the 'Update / Publish' button in Wordpress CMS posts/pages. Any tips on how to achieve this despite the challe ...

What could be the reason for Firefox failing to display the border of a table when the tbody is

If Firefox isn't displaying table cell borders correctly in the presence of an empty tbody, a simple solution is to use the pseudo selector tbody:empty {display:none;} to hide the empty tbody element. This will ensure that everything is rendered as ex ...

Remove Vue Component from the styling of current application

We integrated a Vue component (using Vuetify) into our existing .NET MVC application. The issue we are facing is that the Vue component is inheriting all the CSS styles from the rest of the application. Here's a simplified version of the HTML structur ...

What are the steps to create a unique popup div effect with jQuery?

Upon clicking the icon on this page, a mysterious div appears with information. I'm completely baffled by how they achieved this cool effect using css/jQuery tools. Can anyone shed some light on the mechanism behind this? ...

Options for Repeating and Full Width Custom Headers in WordPress

I have been exploring the WP codex extensively, but without success. I have enabled the customizer custom header and can upload images. I can then set some CSS to choose whether I want it to be full width or repeated. However, I would like to add an option ...

Mouse over the image link and update the CSS text effect

I need help with a WordPress plugin and I'm trying to avoid making too many changes to the HTML output. Is there a way to make both the image and text change color when hovered over? You can see what I'm working on here - http://jsfiddle.net/3JE ...

Designing Interactive Circular Dates on Website

Currently, I am working on a webpage using HTML, CSS, JavaScript, and PHP. The goal is to design a page that features 7 circles representing the current date and the next 6 days. Users should be able to click an arrow to navigate to the following 7 days. ...

Display everything when an option is clicked

I have a filter that is working perfectly. When I select a specific category, it filters out only rows with that category. However, I am stuck on how to display all rows again after clicking on the first option. My objective is to show all rows when "Categ ...

What are the elevated sections in bootstrap?

Having come from Semantic-UI and starting to learn Bootstrap, I must say that despite its widespread popularity, I find Bootstrap a bit lacking compared to what Semantic-UI has to offer in terms of basic stylings. Currently, I am on the lookout for the Bo ...

Using Jquery for Animation: Tips on Revealing Text After Changing Element Color or Styles

Hey everyone, I ran into a bit of trouble while working with jQuery and trying out some animations. My goal was to make a textbox appear and display text when a button is highlighted, similar to a gallery setup. However, I managed to get halfway through th ...

`CSS Toggle Smooth Transition Effect`

I am working on creating 2 CSS toggle buttons that currently have a fade in and out effect when clicked. I would like them to have a sliding animation from right to left instead. Below is the HTML, CSS, and a link to a fiddle containing my code. Thank yo ...

Is there a way to modify the header color in LESS? I attempted to do so, but unfortunately, my changes were unsuccessful

I have encountered an issue with my HTML code. Here's a snippet of it: <html> <head> <link rel="less/less.js" href="css/style.less"> </head> <header> This is a header. </header> </html> Within style.less ...

Set restrictions on the element with a fixed position

My div has a position: fixed that scrolls correctly, but I want it to stop when it reaches specific y-axis boundaries. How can I achieve this without flickering and maintaining performance? The behavior of Twitter's right panel is similar to what I&ap ...

jQuery not targeting absolute positioned duplicates of the <div>'s

(Please find the code link at the bottom of this question) I have been working on a radial menu for a web project. However, I've encountered an issue that has me stuck for hours now. No matter what I try, I can't seem to get any response from th ...

Fixed headers remain in place as you scroll horizontally on a single table

Within my system, I have organized two tables: table one and table 2 are stacked on top of each other. I've managed to freeze the column headers so that they are displayed vertically, remaining static as users scroll horizontally. To achieve this effe ...