Convert px to em in Less

2019-02-05 09:51发布

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?

标签: css less
5条回答
地球回转人心会变
2楼-- · 2019-02-05 10:12

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');
        }
    }
}
查看更多
ら.Afraid
3楼-- · 2019-02-05 10:23

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;
}
查看更多
女痞
4楼-- · 2019-02-05 10:36

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.

查看更多
Root(大扎)
5楼-- · 2019-02-05 10:37

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!

查看更多
女痞
6楼-- · 2019-02-05 10:37

If you're compiling your LESS on the server side, you can do this with CSSHub

/* Test unit convert */
div {
  .unit-convert(font, ~'bold em(14px)/1.2 @{csshub_font-stack-arial}');

  // Ignore base: @csshub_font-size: 100%;
  .unit-convert(margin, ~'rem(18px) rem(20px) rem(15px)', true);

  // Default: 100% == 16px == 1em == 12pt == 1rem
  .unit-convert(font-size, ~'px(100%)');         // Test: % to px
  .unit-convert(font-size, ~'pt(16px)');         // Test: px to pt
  .unit-convert(font-size, ~'em(12pt)');         // Test: pt to em
  .unit-convert(font-size, ~'rem(1em)');         // Test: em to rem
  .unit-convert(font-size, ~'percent(1rem)');    // Test: rem to %
}

This generates this css

/* Test unit convert */
div {
  font: bold 0.875em/1.2 Arial, 'Helvetica Neue', Helvetica, sans-serif;
  margin: 1.125rem 1.25rem 0.9375rem;
  font-size: 16px;
  font-size: 12pt;
  font-size: 1em;
  font-size: 1rem;
  font-size: 100%;
}
查看更多
登录 后发表回答