Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unitless values eg for "ew" values #12

Open
tobireif opened this issue Feb 17, 2018 · 5 comments
Open

Unitless values eg for "ew" values #12

tobireif opened this issue Feb 17, 2018 · 5 comments

Comments

@tobireif
Copy link

I had a case where I wanted to use an "ew" value as a multiplier, but that resulted in an invalid calc() expression:

https://bugs.chromium.org/p/chromium/issues/detail?id=813325

Is it possible to ask EQCSS for a unit-less value? (eg like "ew" but without a unit, or just any value based on element width without a unit, for use as a multiplier)

@tomhodgins
Copy link
Owner

Howdy Toby!

I see what you mean, here's the code for EW inside the EQCSS plugin:

// Element width units
case 'ew':

  return elements[j].offsetWidth / 100 * $1 + 'px'

break

So you should be able to use the same formulas directly in any EQCSS query with eval("")

The formulas would be:

  • 1 ew: eval("offsetWidth / 100")
  • 1 eh: eval("offsetHeight / 100")
  • 1 emin: eval("Math.min(offsetWidth / 100, offsetHeight / 100)")
  • 1 emax: eval("Math.max(offsetWidth / 100, offsetHeight / 100)")

The numbers that offsetWidth and offsetHeight return are in pixels, but unless you add px to them they remain as 'unitless' numbers. So in the case that you wanted to write a calc() expression to combine them with 10px to end up with a number that ended in px, you could skip expressing it as EW and instead put something like this in your code:

@element div {
  :self {
    font-size: calc(10px * eval('offsetWidth / 100'));
  }
}

@tobireif
Copy link
Author

Thanks Tom!

That's a great option for now.

Also, perhaps it's something to consider to add this to the CSS API (so that EQCSS users can get unitless values without having to use eval/JS).

@tomhodgins
Copy link
Owner

I'm not sure what you mean when you say:

add this to the CSS API (so that EQCSS users can get unitless values without having to use eval/JS)

The feature definitely uses JS to arrive at the number ew represents, it's just a shorthand for places where users were writing eval("offsetWidth / 100 * something") in code, but if you want more flexibility you can use eval("") and get just the numbers you need - possibly avoid calc() entirely if the numbers you're working with can be computed in JS inside the eval("").

I don't think having a shorthand like ew that, by default didn't do anything, and required something like calc(10ew * 1px) in order to be used would be very unintuitive though. I think most users would expect a unit to work as-is, like 10ew and if that didn't work, it's not obvious why it didn't. In this case all we have to work with (from JavaScript) are pixels, so it makes sense that the measurement done in pixels is returned in pixels I think.

I've experimented with unitless values for offsetWidth and offsetHeight with plugins like CSSplus/Varsity and Varius, both of which set CSS variables that can be used inside calc with something like calc( * 1px) to be coerced into px units, but it's not as nice to write things that way. On the most recent incarnation of this sort of functionality, jsincss-element-units, I've gone back to defining them with px supplied:

switch(unit) {

  case 'ew':
    return tag.offsetWidth / 100 * number + 'px'

  case 'eh':
    return tag.offsetHeight / 100 * number + 'px'

  case 'emin':
    return Math.min(tag.offsetWidth, tag.offsetHeight) / 100 * number + 'px'

  case 'emax':
    return Math.max(tag.offsetWidth, tag.offsetHeight) / 100 * number + 'px'

}

@tobireif
Copy link
Author

I'm not sure what you mean when you say:

add this to the CSS API (so that EQCSS users can get unitless values without having to use eval/JS)

Adding this as option to the proto-CSS-API of EQCSS could look like this:

font-size: calc(12px * number(2ew));

It would be an addition to the API which would allow devs to get the unitless value without using eval(). It's just an idea, that's all - eval is OK enough 😀

Anything can be done in eval, and anything can be done in JS - the latter would mean I'd write my JS and not use EQCSS 😀 So I'm generally happy if my CSS stays pure CSS / proto-CSS / non-JS. But small exceptions using eval are OK enough.

@tomhodgins
Copy link
Owner

One thing I just spotted in the wild this week is some code that uses an external function to calculate numbers: https://www.freedomfirstsociety.org

In the source code of the website you'll see this EQCSS code:

@element #b-trail {
  $this {
    padding-top: eval("trailFunc2()");
    padding-bottom: eval("trailFunc2()");
  }
}

It calls the trailFunc2() function in JS, which says:

var trailFunc2 = function() {
  var x = document.getElementById("img-responsive").clientHeight;
  var y = document.getElementById("trail1").clientHeight;
  var z = (Math.max((x - y), 0)/2) +"px";
  return z;
};

This is one way you can include complex JS-based math calculations to supply values, use eval("")keep your CSS cleaner and your JS in JS, and with EQCSS you have support for this IE8+. If you only need support where CSS variables work, this sort of usage could also be set from JS as a CSS variable, and then var(--trailFunc2) might always have the current value, then their CSS would look like this:

#b-trail {
  padding-top: var(--trailFunc2);
  padding-bottom: var(--trailFunc2);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants