Wysiwig is hard #4, editing StyleSheets...

Editing stylesheets in a wysiwyg editor can be hard. For multiple reasons:

  1. stylesheets are of three different kinds: embedded into the document through a <style> element, linked through a <link> element, or imported from another stylesheet (and nesting is possible) through an @import rule. In html5, the possibility to have embedded styles anywhere in the document adds another layer of complexity, in particular in the case of presence of the scoped attribute... I must admit BlueGriffon is not ready for that yet, I have not resolved all the technical issues related to scoping. In particular, the specificity of scoped styles is unchanged and I am not sure this is coherent with the spirit of the CSS Cascade. This may have deep implications on the wysiwyg editing side but an ID selector's specificity should probably be added to all scoped styles.

    Listing all stylesheets applied to a given document is simple using one single CSS OM call. Determining if a stylesheet is embedded, linked or imported is done through the parentStyleSheet and ownerNode attributes on CSSRule and StyleSheet interfaces.

    Serialization of a stylesheet is painful. I had to write thousands (yes, really) of lines of JS to handle that because unknown CSS rules are not preserved by the browsers' style engines. Even if they were, an editor just cannot consider a vendor-prefixed property has to be output unchanged. A style change by the user could affect vendor-prefixed styles stored as unknown rules in the CSS OM...

  2. adding a given style to a given element is hard; not only you must find all the style rules that apply to the element for the property you want to edit, but you also need the specificities of those rules. When you have the list of couples (rule, specificity of the rule), you must find the rule of highest specificity. If that rule is editable, i.e. if the stylesheet can be modified by the application, then you must create a style rule or a style attribute of a high enough specificity and/or importance overriding the current style. If the stylesheet is not editable (file not writable, remote resource), then you may have to create a new embedded or linked stylesheet (or use a style attribute) to apply the style you want. I don't even want to think about the scoped styles case for the time being, it's a nightmare.

  3. html5 defines a new presentational attribute on all elements: the hidden attribute... It is not entirely clear to me if a true value of that boolean attribute should map to the CSS display: none; style or use another mechanism to hide the element. In the case of the former choice, this will add another layer of complexity to the editing algo for the display property. Furthermore, in the case what's the position of the hidden attribute in the CSS cascade? I think the html5 author's spirit make it override all other styles. But that's not how the Cascade works, giving a very low specificity to presentational attributes. Should the hidden and the style attributes have the same specificities? Should hidden exist at all? I don't think it should. It's presentational and we have the display property anyway. The only reason why it should exist could be an accessibility reason, voice browsers often using the DOM and not the CSS OM. By the way, the spec says "When specified on an element, it indicates that the element is not yet, or is no longer, relevant". Does it imply that styles contained in a <style hidden> should not apply any more? In other terms, does it disable the stylesheet? This hidden attribute is a can of worms, underspecified, and it will raise tons of technical issues in the near future.

  4. editing an embedded stylesheet is a pain. I'm sure you thought this should be the easiest case. No external file or remote resource, everything is inside text nodes. Simple, eh? It's not. It's not if you want the dialog editing such a stylesheet to be non-modal... Let me explain: if the dialog is not modal, then all changes to the styles are immediately applied. Let's suppose my embedded stylesheet contains only p { color: red; } and that I want to change that color to blue. I have two choices depending on the frameworks I am using:
    1. first case, I have access to an abstraction layer allowing me to tweak directly the source of the stylesheet; then I can change the red into a blue, and replace the textual contents of the style element by the new stylesheet
    2. I have only access to the CSS OM; then I can change the property value in the CSS OM, serialize the stylesheet and then replace the textual contents of the style element
  5. But in both cases above, I have a serious problem: the stylesheet I was editing does not exist any more! The style rule I was editing does not exist any more! They were replaced by a new stylesheet and a new style rule after parsing of the new textual contents... So if I kept a reference to the stylesheet and style rule I edited, they suddenly get a null ownerNode, my whole UI still shows style objects that are now only references to objects unrelated any more to the document. That implies that every style change, I repeat every style change, in an embedded stylesheet from a non-modal UI should totally reflow the UI or at least, reassociate all UI to new style objects that did not exist before... Urgh, to say the least.

Editing styles in a wysiwyg editor is not, as I heard it during a chat a few months ago, "only a matter of a few calls to the CSS OM". It's painful, expensive both in terms of performance and footprint, sometimes tricky in terms of UX and requires stuff that the CSS OM does not implement . It can be really hard.


1. On Wednesday 18 May 2011, 10:15 by Henri Sivonen

The hidden attribute is handled as display: none; in the UA style sheet:

The only way the hidden attribute differs from rolling your own .hidden { display: none; } class is that the theoretical UAs that don't support CSS (including theoretical assistive technology mappings that don't pay attention to computed style; real ones do) are supposed to know to hide stuff that has the hidden attribute.

Basically, if you want to argue against the hidden attribute, you need to argue against the principle that CSS is optional.

2. On Wednesday 25 May 2011, 13:14 by romulus

A ce propos, et peut-être est-ce lié, mais dans Bluegriffon je n'ai pas trouvé de moyen de créer une feuille de style externe, un peu comme le faisait Cascade avec NVU (et après Kompozer, non non ne me frappez pas, je ne trolle pas !) Quand on touche au css, Blugriffon génère toujours du code à l'intérieur de la page. J'ai peut-être mal regardé ? Pourtant j'ai passé quelques heures dessus. Si non, bien évidemmnent un grand bravo pour le boulot de titan réalisé.
PS: Il y a un forum des utilisateurs francophones de BG ?