Styling an MNX document
MNX uses a lightweight but powerful syntax for setting visual styles on notational elements. This syntax is a subset of CSS (Cascading Style Sheets).
This styling system is primarily intended to control visual aspects of a score, as opposed to structural aspects. For structural aspects — such as line breaks, page breaks and stave order — please see <system-layout>.
Overview
There are two ways to style an MNX element: using inline styles and using style rules.
Using inline styles is as simple as including the appropriate style properties directly in the appropriate MNX element. For example, here we have a <note>
element with an inline color
attribute, meaning the note should use a specific color:
<note pitch="C5" color="#0080FF" />
Inline styles cascade — that is, they apply recursively to any child element as well. For example, this <sequence>
element has a color
attribute, so the inner <note>
elements will "inherit" that color:
<sequence color="#0080FF">
<event value="/4">
<note pitch="C5"/>
</event>
<event value="/4">
<note pitch="E5"/>
</event>
<event value="/4">
<note pitch="G5"/>
</event>
<event value="/4">
<note pitch="C6"/>
</event>
</sequence>
The downside of inline styles is that the style information is scattered throughout your document, rather than living in a single place. For example, if you decide to change the color of all the notes from blue to red, you'll have to change every single inline style.
Style rules give you a way to centralize your style decisions, adding an elegant level of indirection. Instead of "hard-coding" your styles directly inline, you use a separate element called <style>
that defines rules to apply to your document.
The <style>
element defines two things — a style property and a selector (the types of MNX elements to which the style is applied). There are two types of selectors, element selectors and class selectors.
An element selector lets you target style rules to specific elements by name. For example, here we define a style that says "all <note>
elements should be colored blue:"
<style selector="note" color="#0000ff">
A class selector lets you create styles that can then be referred-to from elements. Here we define a style that says "all elements with the style class "emphasized"
should be colored blue:
<style selector=".emphasized" color="#0000ff">
Note the dot at the start of ".emphasized"
. This means emphasized
is a style class as opposed to an MNX element name.
Once you've defined this emphasized
style, you can assign it to MNX elements by using the class
attribute, like so:
<note pitch="C5" class="emphasized" />
Location of <style>
An MNX document can have <style>
elements in a few different places, including <global>
, <page>
and <score>
. See here for more.
The styles defined within a <style>
element will only apply to the relevant section of the document, depending on where the <style>
element lives. See "Algorithm for calculating an element's applied styles" below.
Style properties
Here is the full list of style properties MNX currently supports. These can be used in <style>
elements, and they can be used inline in any styleable MNX element (see below).
- color
(Yes, this list is very short at the moment!)
Styleable MNX elements
Many MNX elements are styleable — meaning they accept style properties as XML attributes. For a full list, see here.
Algorithm for calculating an element's applied styles
To determine which style properties apply to a given target element, use the following algorithm:
1. Gather all of the styles that apply directly to the target element. In order from highest priority to lowest priority, these are:
- Inline styles in the element itself (e.g., XML attributes such as
color
). - Applicable class selectors defined in
<style>
elements in the applicable<page>
. - Applicable class selectors defined in
<style>
elements in the applicable<score>
. - Applicable class selectors defined in
<style>
elements in the applicable<system-layout>
or<system-layout-change>
. - Applicable class selectors defined in
<style>
elements in<global>
. - Applicable element selectors defined in
<style>
elements in the applicable<page>
. - Applicable element selectors defined in
<style>
elements in the applicable<score>
. - Applicable element selectors defined in
<style>
elements in the applicable<system-layout>
or<system-layout-change>
. - Applicable element selectors defined in
<style>
elements in<global>
.
2. For each of these categories, sort the results within the category such that later declarations in the document take priority over earlier ones. For scores and layouts, this has the effect that more specific elements override their ancestors. It also means that when multiple class names or specific values are provided in a target element, later ones override earlier ones.
3. Traverse these results, saving the highest-priority result for each style property. This results in a computed value for each style property.
4. If no computed value is found for a given style property for this element, determine the default value by ascending the element's property inheritance chain. This chain is defined as follows:
- If the target element is within
<part>
:- All ancestors of the target up to and including
<part>
. - The
<measure-global>
element with the same measure index as the target, and this<measure-global>
element's ancestors up to and including<global>
. - The most specific layout element that applies to the target element, and its ancestors up to and including
<layouts>
. - The most specific score element that applies to the target element, and its ancestors up to and including
<score>
.
- All ancestors of the target up to and including
- If the target element is within
<global>
:- All ancestors of the target up to and including
<global>
. - The most specific layout element that applies to the target element, and its ancestors up to and including
<layouts>
. - The most specific score element that applies to the target element, and its ancestors up to and including
<score>
.
- All ancestors of the target up to and including
- If the target element is a layout element:
- All ancestors of the target up to and including
<layouts>
. - The most specific element within a
<score>
that applies to the target element, and its ancestors up to and including<score>
.
- All ancestors of the target up to and including
- If the target element is a score element:
- All ancestors of the target up to and including
<score>
.
- All ancestors of the target up to and including
For each ancestor consulted during this search, examine its computed value. If one is found, the search terminates and that value is used as the target element's default value.
If no computed value is found on an ancestor and the search completes at <global>
, then the property assumes an initial value determined by the host application, or by the property's initial value as given in the MNX specification.