Page 1 of 1

Efficient CSS Tips

Posted: Thu Feb 27, 2014 5:52 pm
by odaata
I'm developing a framework for TEI, which has a complex data model, so my CSS is quite large and complicated. I've noticed that as the XML file grows in size the editor slows down quite a bit.

I think it's because of the CSS: I've removed my custom Extension bundle from the framework and it doesn't speed it up much at all and on top of that, if I use very simple CSS, the pages speed up a lot. I've also profiled the app a bit and there don't seem to be any memory links, but every little action performed in Oxygen is causing the CPU to spike. Based on all that, I *think* the problem lies with my CSS being inefficiently written for the implementation used by Oxygen (The Flute CSS Parser, right?). Does anyone out there have experience with Flute and can share some tips on writing efficient CSS for it within the context of XML editing in Oxygen?

I've found the articles below on writing efficient CSS for web browsers. They suggest using id (#) tags and class (.) tags to do styling, but those aren't options for styling XML in Oxygen. In lieu of these, I have used a lot of descendant rules like element > element { }. Are these also inefficient in the Oxygen/Flute world as well? The articles also recommend avoiding pseudo classes because they are super slow, but the Oxygen documentation seems to imply that they are the way to go. Thoughts?

https://developer.mozilla.org/en-US/doc ... icient_CSS
http://www.onextrapixel.com/2012/05/03/ ... rendering/

Likewise, I'm assuming the article below does NOT apply to Oxygen, since it seems the improvements in CSS are only found in browser implementations.

http://calendar.perfplanet.com/2011/css ... he-better/

Thanks in advance for any guidance you can offer!

Re: Efficient CSS Tips

Posted: Fri Feb 28, 2014 12:16 pm
by alex_jitianu
Hello,

The CSS parsing speed should not be a problem for the slowdown. It is performed only at document load time and is quite cheap compared to other operations done at that stage.

In our implementation we do not optimize id and class selectors for they are not very common in XML styling, as you mentioned. There is a (slight) performance penalty though in using descendant selectors element element instead of child selectors element > element. The :hover and :focus pseudo-classes have the same performance implications in Oxygen as they do in browsers. However, the performance of custom pseudoclasses is the same as that of the attribute selectors which is quite fast. The advantage of using pseudoclasses is that they are not constrained by the schema and they do not have to appear in the final document.

The Oxygen selectors that may cause performance problems are the subject selectors [1] introduced in 15.2, structural pseudoclasses (e.g. nth-child) and sibling selectors (e + e or e ~ e. The problem is not necesarily the selector matching algorithm but the fact that they cause larger screen areas to be repainted when editing inside their matched nodes.

There is also the oxy_xpath CSS function which is very powerful but should be used with care. It evaluation of the given XPath expression is performed quite often when the document is edited and it may block the user interface if the expression takes long to evaluate (e.g. searching in a 100MB document).

If you can send us the framework you are working with and a sample document, maybe we can give you better insights regarding performance.

Thanks,
Alex

[1] http://oxygenxml.com/doc/ug-editor/#ref ... ector.html

Re: Efficient CSS Tips

Posted: Mon Mar 03, 2014 4:11 pm
by alex_jitianu
Hello,

We've analyzed your framework and I think it is a good idea to post what you've discovered so that others that read this post will benefit from it.

The general advice is that both oxy_xpath and :hover pseudo-classes are very powerful but there is a trade-off between expressiveness and performance:

- the scrolling performance can be improved by optimizing the following rules:

*:hover:after {
border:1px dashed black;
}

handShift[new]:hover:after,
[hand]:hover:after {
link: oxy_xpath("if (local-name() eq 'handShift') then data(@new) else data(@hand)");
-oxy-append-content: url('../images/hand_open-16.png');
}

You should try and write the selectors as specific as possible when working with the :hover class. The :hover pseudo class is automatically set on the ancestors of the hovered element so with the above rules a lot of elements will change their layout while you move the mouse or scroll. Visually you wont see any change because the rule matches on the :after pseudo-element and a 'content' property should also be set if the element is to be created.

- the performance on typing can be improved by restricting the use of oxy_xpath. A little after the document is being changed these XPaths will be executed and all the nodes that depend on oxy_xpath will update their layout. This means that after you type text and you stop you will notice that the editor freezes for a couple of seconds. What you can do to prevent this:
1. Check if you can rewrite the condition from the XPath in a CSS selector. For example this rule:

Code: Select all

handShift[new]:hover:after,
[hand]:hover:after {
link: oxy_xpath("if (local-name() eq 'handShift') then data(@new) else data(@hand)");
}
can be rewritten into two rules:

Code: Select all

handShift[new]:hover:after {
link: attr(new)
}

[hand]:hover:after {
link: attr(hand);
}
2. When adding form controls, instead of giving the possible values through oxy_xpath you can use a schema manager filter which is asked about the possible values for a particular attribute. You can implement some sort of caching for values that do not change frequently (e.g. during typing). You can clear this cache when the document is changed using an AuthorListener.

3. In our current implementation, nodes that have oxy_xpath in their styles are repainted for every change in the document (e.g. text insertion in completely different part of the document). If the oxy_xpath that defines the style of a node, uses information only from the current node, you can use a StylesFilter to achieve the same effect.

Best regards,
Alex