toRem function

CssValue? toRem(
  1. dynamic value, {
  2. bool treatNumAsRem = false,
  3. bool passThroughUnsupportedUnits = false,
})

Converts a pixel (px) value to its rem equivalent using the current font size found on the HtmlDocument.

  • If value is a String or CssValue:
    • And value already has the correct unit, it will not be converted.
    • And CssValue.unit is not 'px' or 'rem', an error will be thrown unless passThroughUnsupportedUnits is true, in which case no conversion will take place.
  • If value is a num, it will be treated as a px and converted, unless treatNumAsRem is true.
  • If value is null, null will be returned.

Examples (all will output 1.5rem assuming 1rem == 10px):

toRem('15px');
toRem(new CssValue(15, 'px'));
toRem(15);
toRem(1.5, treatNumAsRem: true);
toRem('1.5rem');
new CssValue(1.5, 'rem');

Related: toPx

Implementation

CssValue? toRem(dynamic value, {bool treatNumAsRem = false, bool passThroughUnsupportedUnits = false}) {
  // Because Chrome changes the value of its root font size when zoomed out lower than 90%, we need
  // to automatically wire up the rem change sensor so that any calls to `toRem` when the viewport is
  // zoomed return an accurate value.
  //
  // Only run them when `testMode` is false as a workaround to not break all the individual `toRem` tests
  // that rely on `onRemChange.first`, and so that the dom node that is mounted via `_initRemChangeSensor`
  // is not suddenly present in the dom of all consumer tests - which could break their assertions about
  // a "clean" / empty `document.body`.
  //
  // See: https://jira.atl.workiva.net/browse/AF-1048 / https://bugs.chromium.org/p/chromium/issues/detail?id=429140
  if (browser.isChrome && !component_base.UiProps.testMode) {
    // TODO: Why does Zone.ROOT.run not work in unit tests?  Passing in Zone.current from the call to toRem() within the test also does not work.
//    Zone.ROOT.run(_initRemChangeSensor);
    initRemChangeSensor();
  }

  if (value == null) return null;

  num remValueNum;

  if (value is num) {
    remValueNum = treatNumAsRem ? value : value / rootFontSize;
  } else {
    var parsedValue = value is CssValue ? value : CssValue.parse(value);

    if (parsedValue?.unit == 'rem') {
      remValueNum = parsedValue!.number;
    } else if (parsedValue?.unit == 'px') {
      remValueNum = parsedValue!.number / rootFontSize;
    } else {
      if (passThroughUnsupportedUnits) return parsedValue;

      throw ArgumentError.value(value, 'value', 'must be a px num or a String px/rem value');
    }
  }

  return CssValue(remValueNum, 'rem');
}