As we discussed in the Marquee Syntax article, most of the syntax in markdown is semantic, meaining that it concerns itself with the nature of what it encodes, rather than the look of it. The other side of the coin, how it looks, will be dealt with in this article. Note that this division between semantics and style is also seen in HTML5 where the looks is fully relegated to CSS and the tags are all semantic.
HTML has CSS to take care of styling for it, and that has over the years morphed into a sprawling and powerful language of it’s own. Both too complicated to support for something like marquee, and too complicated to be needed for styling markdown (after all it’s main goal is to style full webpages, not documents). Marquee instead defines it’s own limited styling system which is simple enough to reason about, and powerful enough to support what is needed for markdown text. Many concepts are borrowed from CSS so if you are used to that you should feel pretty much at home.
In marquee, a style defines the full specification for how an element
(block or span) should visually appear. It holds 23 different settings
concerning everything from font rendering, to spacing, coloring, and
alignment. Rather than going through all here, I’ll point towards the
documentation for the style()
function.
While span and block elements takes the same style specifications,
some settings only apply to block elements and are ignored for spans.
These are lineheight
, align
,
indent
, hanging
, margin
,
bullets
, and img_asp
.
A style set is a collection of styles, each style related to a
specific type of element. It does not need to provide a style for all
elements in the text, and the elements doesn’t need to be complete. The
only hard requirement is that it contains a complete style named
base
, from which everything else can be derived. marquee
ships with a style set called classic_style()
which aims to
mimic the standard look of rendered markdown. New style sets can either
be build from the ground up or based off of
classic_style()
.
Marquee uses a very simple inheritance model for it’s styling, that can be boiled down to a single short sentance:
An element inherits any unspecified from it’s parent element.
Any setting in a style object set to NULL
will be
inherited from the parent all the way down to the base style (which is
the reason why that style must be complete). As an example, let’s look
at the style for the em
element in the
classic_style()
:
The only thing it touches is the italic
setting,
everything else is borrowed from whatever element it is placed into.
There are two other ways to influence style inheritance. The first
one is wrapping a value in skip_inherit()
. This will
instruct marquee to inherit the value one level up in the hierarchy
rather than from the direct parent (if the parent of the parent is also
set to skip_inherit()
it moves up yet another level, and so
on). The second one is wrapping a numeric value in
relative()
which will instruct marquee to use the relative
value as a multiplier applied to the parent.
All sizes in a style is in (big)points (the distinction between
bigpoints and points are rather small and boring. Bigpoints are 1/72
inches, which is what we use). Instead of setting a style setting
directly to a numeric value, you can make it relative to the font size
of the style using em()
. This is beneficial for
e.g. padding, margin, indent, etc. where you often want it to scale with
the font size. In the case you set the size to an em value, it will be
relative to it’s parent and effectively be equivalent to using
relative()
. There is a variant of em values called
rem()
(root em). Instead of making the setting relative to
the size of the current element it makes it relative to the size in the
base element of the document.
A style has three settings that relates to the four sides of a box.
margin
, padding
, and border_size
.
These are set to values constructed with trbl()
, which
works like margin settings in CSS. If you provide it with 1 value it
will set all sides to that value. If you provide it with two values and
it will set top and bottom to the first and left and right to the
second. If you provide it with three values it will set the top to the
first, left and right to the second, and bottom to the third. If you
provide it with four values it will set the top to the
first, right to the second, bottom to
the third, and left to the fourth (the bold first
letters gives a clue to why the constructor is named as it is).