Typed CSSOM

Hi houdiños,

Being able to describe the type of CSS values has been an important part of
the custom properties proposals that we've talked about in this group.

I'd like to explore whether we can extend this notion to JavaScript - i.e.
provide typed JS objects rather than strings when accessing custom CSS
values. I'd also like to see whether we can retrofit the existing CSSOM
with this idea. These ideas were discussed in the January f2f but I don't
think we've talked about it much on list since.

My reasons are basically those provided in Sydney: converting CSS strings
to values is tedious, error-prone, and a source of performance problems.

So to get the ball rolling - here's a partial proposal that only covers
numbers and lengths. Obviously we'll eventually want to expose the rest of
the types too, but we need to start somewhere :) Bikeshed away!

(1) Access to typed CSSOM
A new OM can't just start to replace existing CSSOM functionality with
typed versions because this will break lots of things. Instead we should
create a new interface, StylePropertyMap, that is accessible alongside the
old methods:

interface StyleValue {
  boolean isInitial();
  boolean isInherit();
  boolean isDefault();
  boolean isUnset();
  attribute DOMString cssString;
}

interface StylePropertyMap {
  StyleValue get(DOMString property);
  sequence<StyleValue> getAll(DOMString property);
  void set(DOMString property, StyleValue or sequence<StyleValue> or
DOMString value);
  void append(DOMString property, StyleValue or sequence<StyleValue> or
DOMString value);
  iterable<DOMString, StyleValue or DOMString>;
  stringifier;
};

interface ComputedStylePropertyMap : StylePropertyMap {
};

interface SpecifiedStylePropertyMap : StylePropertyMap {
  boolean has(DOMString property);
  sequence<DOMString> getProperties();
}

partial interface Element {
  readonly attribute SpecifiedStylePropertyMap styleMap;
};

partial interface Document {
  ComputedStylePropertyMap getComputedStyleMap(Element element);
};

partial interface CSSStyleRule {
  readonly attribute SpecifiedStylePropertyMap styleMap;
};

(2) Numbers

Number properties like z-index or opacity should have a very simple
wrapping:

interface NumberValue : StyleValue {
  double value;
}

An open question: where and when does validation happen? What happens if I
try to set an out-of-range number to opacity? Will this be consistent
across all properties?

(3) Lengths

Usually, lengths are simple single-unit values (e.g. 50px or 30em).
However, it is possible for calc values to be used instead. The following
API tries to capture common use-cases without allowing web devs to
accidentally write code that will break when calc values are fed in:

enum LengthType {
  "px", "percent", "em", // ...
}

interface Length : StyleValue {
  Length add(Length value); // can throw
  Length subtract(Length value); // can throw
  Length multiply(double value); // can throw
  Length divide(double value); // can throw
  static Length parse(DOMString cssString);
  static Length fromValue(double value, LengthType type);
  static Length fromDictionary({...});
}

[Constructor(DOMString cssString),
 Constructor(Length),
 Constructor({
  // … all the props.
})]
interface CalcLength : Length {
  attribute double? px;
  attribute double? percent;
  attribute double? em;
  attribute double? ex;
  attribute double? ch;
  attribute double? rem;
  attribute double? vw;
  attribute double? vh;
  attribute double? vmin;
  attribute double? vmax;
  attribute double? cm;
  attribute double? mm;
  attribute double? q;
  attribute double? in;
  attribute double? pc;
  attribute double? pt;
}

// lengths that are *just* keywords don't become SimpleLengths or
CalcLengths.
interface SimpleLength : Length {
  attribute double value;
  readonly attribute LengthType type;
}

In particular, lengths can be manipulated using the Length API without
knowing whether they're simple or calc expressions. One downside is that
developers need to check whether a Length is a SimpleLength before
extracting the Length value - but then again, in practice they should be
doing this anyway.

(4) Everything else

I realize that there are lots of details missing! Hopefully there's enough
here to kick off a conversation, though - is this a direction we want to go
in, and does the API sketched out above look like it could work?

Ideally, I'd like to either start incorporating some of this stuff in the
CSS Properties and Values specification, or alternatively begin a new ED
(CSSOM Level 2?) WDYT?

Cheers,
    -Shane

Received on Monday, 10 August 2015 01:05:48 UTC