Convert px to em in Less

14,003

Solution 1

You could do this to convert px to em.

@font-size: 16;         // Your base font-size in pixels
@em: @font-size*1em;    // Shorthand for outputting ems, e.g. "12/@em"
@rem: @font-size*1rem;  // Shorthand for outputting ems, e.g. "12/@rem"

h1{
  font-size: 20/@em;
}

Solution 2

With LESS you can build your own functions. I use this function with the grunt-contrib-less package. The formatting is slightly different from the usual less functions formatting. Note you need to insert less as a parameter with this package.

em: function(less, fontsize, basefontsize){
    if (less.functions.functionRegistry.get('ispixel')){
        basefontsize = (basefontsize) ? basefontsize.value : 16
        return fontsize.value/basefontsize+'em';
    }
}

Now you can just call this function in your LESS stylesheets as

.class{
    font-size:em(16px);
}

Which will compile to

.class{
    font-size:1em;
}

Note ems will still be relative to the container's css. So the font-size of 1em will not be 16px if the wrapping div has a font-size set of 0.8em for example.

Update: The non-grunt-contrib-less version

If you put this in a javascript file which you include in your html before your less file, you can use the function as stated above.

$.extend(less.functions, {
    em: function(fontsize, basefontsize){
        if (this.ispixel(fontsize)){
            basefontsize = (basefontsize) ? basefontsize.value : 16
            return new(tree.Dimension)(fontsize.value/basefontsize,'em');
        }
    }
}

Solution 3

LESS doesn't have such a feature, according to documentation.

Built-in unit or convert functions do not provide such a convertion.

Note that Scss' implementation of this function assumes convertion using one global font-size value. You can easily achieve same thing in LESS with the use of variables:

@em: 16px;    // LESS variable - default value for 1em

And then use it like this:

div {
  height: @em;
  width: 6 * @em;
}

Code above compiles to:

div {
  height: 16px;
  width: 96px;
}

Note that this (and Scss' version, too) is not the way that real em work, because in CSS dimensions specified in em are computed based on font size of element on which they are used.

Solution 4

If you're compiling your LESS on the server side, and I personally would never do otherwise you can do this with LESS mixins and no custom functions.

That of course means you can't automatically calculate based on the size of the current node, but thwat's a little sounding scary to me. Here's another way to just convert pixels to ems.

Global less mixins

@emInPx: 16;    // 16px per em (global default)

.convertEm(@selector, @amt) when (isem(@amt))
{
    @{selector}: @amt;
}
.convertEm(@selector, @amt, @emInPx: @emInPx) when (ispixel(@amt))
{
    @{selector}: unit((@amt / @emInPx), em);
}

Example usage

img.cat
{
    .convertEm(max-width, 5em);
    .convertEm(max-height, 3em);
}
img.dog
{
    .convertEm(max-width, 100px);
    .convertEm(max-height, 75px);
}

Note that I use the same .convertEm(..) mixin for both pixels and ems, since you may not even know if the value is passed as a parameter. The guarded mixin correctly picks the right formula to convert.

This generates this css

img.cat {
  max-width: 5em;
  max-height: 3em;
}
img.dog {
  max-width: 6.25em;
  max-height: 4.6875em;
}

This all assumes 1em corresponds to 16px. If not you can change the default or pass it in depending upon the context you're in:

img.mouse
{
    .convertEm(max-width, 100px, 32px);
    .convertEm(max-height, 75px, 32px);
}

Disclaimer: I still don't fully understand how or if server generated LESS works can work with custom javascript functions so I'm assuming that when you generate server side you can't add custom functions. If I'm wrong please someone let me know!

Share:
14,003
Annie
Author by

Annie

Updated on June 05, 2022

Comments

  • Annie
    Annie almost 2 years

    What is the equivalent of Scss' emCalc() in less?

    padding: emCalc(24px);
    

    in Scss will calculate em based on the viewpoint and zoom level. Is there any built-in function in less?