Search code examples
for-looplessmixinsless-mixins

LESS: associative array in LOOP


I need to add an icon to a page, depending by its content. In other words, if a page contain an image, a gallery, a video... I'll add an icon indicating its nature.

To do this, I add CSS class to body tag and use descendant selector to add icons in the proper position.

Obviously this task results in a lot of repeating code in CSS, so I would like to generate it with a LESS Loop.

Here my actual attempt (icons are icon-fonts):

@icons:"\e926", "\e90e", "\e914";

.icons-loop(@i; @ico) when (@i <= length(@ico)) {

  @page-type:extract(@ico, @i);

  .page-type_@{page-type}
  {
      #icon_container:before
      {
        content: extract(@icons, @i);
      }
  }

  .icons-loop((@i + 1), @ico);
}

.icons(@ico...) {
  .icons-loop(1, @ico);
}

.icons(image, gallery, video);

I wrote this, taking inspiration from other similar question like this.

It works, but I admit that is not yet what I really would like, for two reasons:

  • I think that current need of a variable @icons to declare icon entities, and a mixins .icons to declare different page-type is not so intuitive, due to eterogeneous type. It should be better to be able to use LESS variable in both declarations, for coherency
  • Could be surely better to write a sort of associative array, in which I could declare in the same place, correspondance between page-type and relative icon. Something like this:

@page-type: image, "\e926"; gallery, "\e90e"; video, "\e914";

Any ideas?


Solution

  • Yes, you can certainly achieve the associative array behavior in Less as shown below as Less can split and extract values both based on comma as well as space.

    In this case we separate multiple page-icon combinations by a comma and then within each page-icon combo, the page type and icon value are separated by space.

    @page-icon-list: image "\e926", gallery "\e90e", video "\e914"; //the 2D array
    
    .loop(@index) when (@index > 0){
        @page-icon: extract(@page-icon-list, @index); //extract based on comma separator each page-icon combo
        @page-type: extract(@page-icon,1); //first part of the extracted value is the page type
        @icon: extract(@page-icon,2); //second part is the icon
        .page-type_@{page-type}{
          #icon_container:before
          {
            content: @icon;
          }        
        }
        .loop(@index - 1);
    }
    .loop(length(@page-icon-list)); //pass the length as counter (split based on comma)