Build less @import url dynamically

11,133

Solution 1

It seems to work in 1.4 beta.

1.4

Doing something like this (I tried it out at less2css.org) in LESS:

.gFontImport (@name, @weights, @subsets) {
    @import url('http://fonts.googleapis.com/css?family=@{name}:@{weights}&subset=@{subsets}');
}

.gFontImport("Roboto+Slab",400,latin);

will have the expected output in CSS:

@import url('http://fonts.googleapis.com/css?family=Roboto+Slab:400&subset=latin');

<=1.3.3

If it does not work for you, you can use a workaround that injects the @import call into a selector name:

.gFontImport (@name, @weights, @subsets) {
    @gimport: ~"@import url('http://fonts.googleapis.com/css?family=@{name}:@{weights}&subset=@{subsets}');";
    @{gimport} some-selector {/* */};
}

so calling something like this in LESS:

.gFontImport("Roboto+Slab",400,latin);

will output this in CSS:

@import url('http://fonts.googleapis.com/css?family=Roboto+Slab:400&subset=latin');
some-selector {
  /**/
}

This works, but it is a tiny bit messy. In a javascript implementation of LESS you can use

`'\n'`

and

`'\t'`

in the string interpolation to make it look a bit tidier.

Solution 2

I've made a gist with working mixins for both versions https://gist.github.com/line-o/5568723

Solution 3

A working example, that defines font sets : (with Less v1.7.3)

// Google font import mixin
.gFontImport (@name; @weights: 400; @subsets: latin) {
    @nameEsc: ~`"@{name}".replace(/'([^']+)'/,'$1').replace(' ', '+')`;
    @import url('http://fonts.googleapis.com/css?family=@{nameEsc}:@{weights}&subset=@{subsets}');
}


// Font sets
// The variable @post-fontset is dynamic (user input)
// ------------------

// foo1
.font(@fontset) when (@fontset = foo1){
    .gFontImport('Roboto');
    .gFontImport('Lato');
}
.font-text() when (@post-fontset = foo1){
    font-family:Lato;
}
.font-headings() when (@post-fontset = foo1){
    font-family:Lato;
}
.font-sitetitle() when (@post-fontset = foo1){
    font-family:Roboto;
}

// foo2
.font(@fontset) when (@fontset = foo2){
    .gFontImport('Oswald');
    .gFontImport('Lato');
    .gFontImport('Roboto Slab');
}
.font-text() when (@post-fontset = foo2){
    font-family:'Roboto Slab';
}
.font-headings() when (@post-fontset = foo2){
    font-family:Lato;
}
.font-sitetitle() when (@post-fontset = foo2){
    font-family:Oswald;
}


// Using the mixins in the CSS
// ------------------

// This executes the font import mixin
.font(@post-fontset);

// Site title
h1{.font-sitetitle();}

// Heading
h2, h3, h4, h5, h6{.font-headings();}

// Text
body{.font-text();}
Share:
11,133
line-o
Author by

line-o

Developer with a heart for design, graphics, quality, testing and usability freelance developer and consultant former senior dev at white label eCommerce former senior dev at commerce plus

Updated on June 14, 2022

Comments

  • line-o
    line-o almost 2 years

    While working on a google webfont import mixin, I noticed that it is not possible to build @import URLs dynamically.

    .gFontImport (@name, @weights, @subsets) {
        @url: "http://fonts.googleapis.com/css?family=@{name}:@{weights}&subset=@{subsets}";
        @import url(@url);
    }
    

    Which can be narrowed down to

    @url: "http://localhost/test.css";
    @import url(@url);
    

    Neither any of these additional tests work:

    @import url("@{url}"); // this one renders at least
    
    @import url(~"@{url}");
    

    When the compiler renders the CSS file the @import URL is always left unchanged, e.g. "@{url}"