mirror of
https://github.com/typst/typst
synced 2025-05-13 20:46:23 +08:00
511 lines
15 KiB
Markdown
511 lines
15 KiB
Markdown
---
|
|
description: Typst's tutorial.
|
|
---
|
|
|
|
# Advanced Styling
|
|
In the previous two chapters of this tutorial, you have learned how to write a
|
|
document in Typst and how to change its formatting. The report you wrote
|
|
throughout the last two chapters got a straight A and your supervisor wants to
|
|
base a conference paper on it! The report will of course have to comply with the
|
|
conference's style guide. Let's see how we can achieve that.
|
|
|
|
Before we start, let's create a team, invite your supervisor and add them to the
|
|
team. You can do this by going back to the app dashboard with the four-circles
|
|
icon in the top left corner of the editor. Then, choose the plus icon in the
|
|
left toolbar and create a team. Finally, click on the new team and go to its
|
|
settings by clicking 'manage team' next to the team name. Now you can invite
|
|
your supervisor by email.
|
|
|
|

|
|
|
|
Next, move your project into the team: Open it, going to its settings by
|
|
choosing the gear icon in the left toolbar and selecting your new team from the
|
|
owners dropdown. Don't forget to save your changes!
|
|
|
|
Now, your supervisor can also edit the project and you can both see the changes
|
|
in real time. You can join our [Discord server](https://discord.gg/2uDybryKPe)
|
|
to find other users and try teams with them!
|
|
|
|
## The conference guidelines { #guidelines }
|
|
The layout guidelines are available on the conference website. Let's take a look
|
|
at them:
|
|
|
|
- The font should be an 11pt serif font
|
|
- The title should be in 17pt and bold
|
|
- The paper contains a single-column abstract and two-column main text
|
|
- The abstract should be centered
|
|
- The main text should be justified
|
|
- First level section headings should be 13pt, centered, and rendered in small
|
|
capitals
|
|
- Second level headings are run-ins, italicized and have the same size as the
|
|
body text
|
|
- Finally, the pages should be US letter sized, numbered in the center of the
|
|
footer and the top right corner of each page should contain the title of the
|
|
paper
|
|
|
|
We already know how to do many of these things, but for some of them, we'll need
|
|
to learn some new tricks.
|
|
|
|
## Writing the right set rules { #set-rules }
|
|
Let's start by writing some set rules for the document.
|
|
|
|
```example
|
|
#set page(
|
|
>>> margin: auto,
|
|
paper: "us-letter",
|
|
header: align(right)[
|
|
A fluid dynamic model for
|
|
glacier flow
|
|
],
|
|
numbering: "1",
|
|
)
|
|
#set par(justify: true)
|
|
#set text(
|
|
font: "Linux Libertine",
|
|
size: 11pt,
|
|
)
|
|
|
|
#lorem(600)
|
|
```
|
|
|
|
You are already familiar with most of what is going on here. We set the text
|
|
size to `{11pt}` and the font to Linux Libertine. We also enable paragraph
|
|
justification and set the page size to US letter.
|
|
|
|
The `header` argument is new: With it, we can provide content to fill the top
|
|
margin of every page. In the header, we specify our paper's title as requested
|
|
by the conference style guide. We use the `align` function to align the text to
|
|
the right.
|
|
|
|
Last but not least is the `numbering` argument. Here, we can provide a
|
|
[numbering pattern]($numbering) that defines how to number the pages. By
|
|
setting into to `{"1"}`, Typst only displays the bare page number. Setting it to
|
|
`{"(1/1)"}` would have displayed the current page and total number of pages
|
|
surrounded by parentheses. And we could even have provided a completely custom
|
|
function here to format things to our liking.
|
|
|
|
## Creating a title and abstract { #title-and-abstract }
|
|
Now, let's add a title and an abstract. We'll start with the title. We center
|
|
align it and increase its font weight by enclosing it in `[*stars*]`.
|
|
|
|
```example
|
|
>>> #set page(width: 300pt, margin: 30pt)
|
|
>>> #set text(font: "Linux Libertine", 11pt)
|
|
#align(center, text(17pt)[
|
|
*A fluid dynamic model
|
|
for glacier flow*
|
|
])
|
|
```
|
|
|
|
This looks right. We used the `text` function to override the previous text
|
|
set rule locally, increasing the size to 17pt for the function's argument. Let's
|
|
also add the author list: Since we are writing this paper together with our
|
|
supervisor, we'll add our own and their name.
|
|
|
|
```example
|
|
>>> #set page(width: 300pt, margin: 30pt)
|
|
>>> #set text(font: "Linux Libertine", 11pt)
|
|
>>>
|
|
>>> #align(center, text(17pt)[
|
|
>>> *A fluid dynamic model
|
|
>>> for glacier flow*
|
|
>>> ])
|
|
#grid(
|
|
columns: (1fr, 1fr),
|
|
align(center)[
|
|
Therese Tungsten \
|
|
Artos Institute \
|
|
#link("mailto:tung@artos.edu")
|
|
],
|
|
align(center)[
|
|
Dr. John Doe \
|
|
Artos Institute \
|
|
#link("mailto:doe@artos.edu")
|
|
]
|
|
)
|
|
```
|
|
|
|
The two author blocks are laid out next to each other. We use the
|
|
[`grid`]($grid) function to create this layout. With a grid, we can control
|
|
exactly how large each column is and which content goes into which cell. The
|
|
`columns` argument takes an array of [relative lengths]($relative) or
|
|
[fractions]($fraction). In this case, we passed it two equal fractional sizes,
|
|
telling it to split the available space into two equal columns. We then passed
|
|
two content arguments to the grid function. The first with our own details, and
|
|
the second with our supervisors'. We again use the `align` function to center
|
|
the content within the column. The grid takes an arbitrary number of content
|
|
arguments specifying the cells. Rows are added automatically, but they can also
|
|
be manually sized with the `rows` argument.
|
|
|
|
Now, let's add the abstract. Remember that the conference wants the abstract to
|
|
be set ragged and centered.
|
|
|
|
```example:0,0,612,317.5
|
|
>>> #set text(font: "Linux Libertine", 11pt)
|
|
>>> #set par(justify: true)
|
|
>>> #set page(
|
|
>>> "us-letter",
|
|
>>> margin: auto,
|
|
>>> header: align(right + horizon)[
|
|
>>> A fluid dynamic model for
|
|
>>> glacier flow
|
|
>>> ],
|
|
>>> numbering: "1",
|
|
>>> )
|
|
>>>
|
|
>>> #align(center, text(17pt)[
|
|
>>> *A fluid dynamic model
|
|
>>> for glacier flow*
|
|
>>> ])
|
|
>>>
|
|
>>> #grid(
|
|
>>> columns: (1fr, 1fr),
|
|
>>> align(center)[
|
|
>>> Therese Tungsten \
|
|
>>> Artos Institute \
|
|
>>> #link("mailto:tung@artos.edu")
|
|
>>> ],
|
|
>>> align(center)[
|
|
>>> Dr. John Doe \
|
|
>>> Artos Institute \
|
|
>>> #link("mailto:doe@artos.edu")
|
|
>>> ]
|
|
>>> )
|
|
>>>
|
|
<<< ...
|
|
|
|
#align(center)[
|
|
#set par(justify: false)
|
|
*Abstract* \
|
|
#lorem(80)
|
|
]
|
|
>>> #lorem(600)
|
|
```
|
|
|
|
Well done! One notable thing is that we used a set rule within the content
|
|
argument of `align` to turn off justification for the abstract. This does not
|
|
affect the remainder of the document even though it was specified after the
|
|
first set rule because content blocks _scope_ styling. Anything set within a
|
|
content block will only affect the content within that block.
|
|
|
|
Another tweak could be to save the paper title in a variable, so that we do not
|
|
have to type it twice, for header and title. We can do that with the `{let}`
|
|
keyword:
|
|
|
|
```example:single
|
|
#let title = [
|
|
A fluid dynamic model
|
|
for glacier flow
|
|
]
|
|
|
|
<<< ...
|
|
|
|
>>> #set text(font: "Linux Libertine", 11pt)
|
|
>>> #set par(justify: true)
|
|
#set page(
|
|
>>> "us-letter",
|
|
>>> margin: auto,
|
|
header: align(
|
|
right + horizon,
|
|
title
|
|
),
|
|
<<< ...
|
|
>>> numbering: "1",
|
|
)
|
|
|
|
#align(center, text(17pt)[
|
|
*#title*
|
|
])
|
|
|
|
<<< ...
|
|
|
|
>>> #grid(
|
|
>>> columns: (1fr, 1fr),
|
|
>>> align(center)[
|
|
>>> Therese Tungsten \
|
|
>>> Artos Institute \
|
|
>>> #link("mailto:tung@artos.edu")
|
|
>>> ],
|
|
>>> align(center)[
|
|
>>> Dr. John Doe \
|
|
>>> Artos Institute \
|
|
>>> #link("mailto:doe@artos.edu")
|
|
>>> ]
|
|
>>> )
|
|
>>>
|
|
>>> #align(center)[
|
|
>>> #set par(justify: false)
|
|
>>> *Abstract* \
|
|
>>> #lorem(80)
|
|
>>> ]
|
|
>>>
|
|
>>> #lorem(600)
|
|
```
|
|
|
|
After we bound the content to the `title` variable, we can use it in functions
|
|
and also within markup (prefixed by `#`, like functions). This way, if we decide
|
|
on another title, we can easily change it in one place.
|
|
|
|
## Adding columns and headings { #columns-and-headings }
|
|
The paper above unfortunately looks like a wall of lead. To fix that, let's add
|
|
some headings and switch our paper to a two-column layout. The
|
|
[`columns`]($columns) function takes a number and content, and layouts the
|
|
content into the specified number of columns. Since we want everything after the
|
|
abstract to be in two columns, we need to apply the column function to our whole
|
|
document.
|
|
|
|
Instead of wrapping the whole document in a giant function call, we can use an
|
|
"everything" show rule. To write such a show rule, put a colon directly behind
|
|
the show keyword and then provide a function. This function is given the rest of
|
|
the document as a parameter. We have called the parameter `rest` here, but you
|
|
are free to choose any name. The function can then do anything with this
|
|
content. In our case, it passes it on to the `columns` function.
|
|
|
|
```example:single
|
|
>>> #let title = [
|
|
>>> A fluid dynamic model
|
|
>>> for glacier flow
|
|
>>> ]
|
|
>>>
|
|
>>> #set text(font: "Linux Libertine", 11pt)
|
|
>>> #set par(justify: true)
|
|
>>> #set page(
|
|
>>> "us-letter",
|
|
>>> margin: auto,
|
|
>>> header: align(
|
|
>>> right + horizon,
|
|
>>> title
|
|
>>> ),
|
|
>>> numbering: "1",
|
|
>>> )
|
|
>>>
|
|
>>> #align(center, text(
|
|
>>> 17pt,
|
|
>>> weight: "bold",
|
|
>>> title,
|
|
>>> ))
|
|
>>>
|
|
>>> #grid(
|
|
>>> columns: (1fr, 1fr),
|
|
>>> align(center)[
|
|
>>> Therese Tungsten \
|
|
>>> Artos Institute \
|
|
>>> #link("mailto:tung@artos.edu")
|
|
>>> ],
|
|
>>> align(center)[
|
|
>>> Dr. John Doe \
|
|
>>> Artos Institute \
|
|
>>> #link("mailto:doe@artos.edu")
|
|
>>> ]
|
|
>>> )
|
|
>>>
|
|
>>> #align(center)[
|
|
>>> #set par(justify: false)
|
|
>>> *Abstract* \
|
|
>>> #lorem(80)
|
|
>>> ]
|
|
>>> #v(4mm)
|
|
<<< ...
|
|
|
|
#show: rest => columns(2, rest)
|
|
|
|
= Introduction
|
|
#lorem(300)
|
|
|
|
= Related Work
|
|
#lorem(200)
|
|
```
|
|
|
|
Now there is only one thing left to do: Style our headings. We need to make them
|
|
centered and use small capitals. Because the `heading` function does not offer
|
|
a way to set any of that, we need to write our own heading show rule.
|
|
|
|
```example:50,250,265,270
|
|
>>> #let title = [
|
|
>>> A fluid dynamic model
|
|
>>> for glacier flow
|
|
>>> ]
|
|
>>>
|
|
>>> #set text(font: "Linux Libertine", 11pt)
|
|
>>> #set par(justify: true)
|
|
>>> #set page(
|
|
>>> "us-letter",
|
|
>>> margin: auto,
|
|
>>> header: align(
|
|
>>> right + horizon,
|
|
>>> title
|
|
>>> ),
|
|
>>> numbering: "1",
|
|
>>> )
|
|
#show heading: it => [
|
|
#set align(center)
|
|
#set text(12pt, weight: "regular")
|
|
#block(smallcaps(it.body))
|
|
]
|
|
|
|
<<< ...
|
|
>>>
|
|
>>> #align(center, text(
|
|
>>> 17pt,
|
|
>>> weight: "bold",
|
|
>>> title,
|
|
>>> ))
|
|
>>>
|
|
>>> #grid(
|
|
>>> columns: (1fr, 1fr),
|
|
>>> align(center)[
|
|
>>> Therese Tungsten \
|
|
>>> Artos Institute \
|
|
>>> #link("mailto:tung@artos.edu")
|
|
>>> ],
|
|
>>> align(center)[
|
|
>>> Dr. John Doe \
|
|
>>> Artos Institute \
|
|
>>> #link("mailto:doe@artos.edu")
|
|
>>> ]
|
|
>>> )
|
|
>>>
|
|
>>> #align(center)[
|
|
>>> #set par(justify: false)
|
|
>>> *Abstract* \
|
|
>>> #lorem(80)
|
|
>>> ]
|
|
>>>
|
|
>>> #v(4mm)
|
|
>>> #show: rest => columns(2, rest)
|
|
>>>
|
|
>>> = Introduction
|
|
>>> #lorem(35)
|
|
>>>
|
|
>>> == Motivation
|
|
>>> #lorem(45)
|
|
```
|
|
|
|
This looks great! We used a show rule that applies to all headings. We give it a
|
|
function that gets passed the heading as a parameter. That parameter can be used
|
|
as content but it also has some fields like `title`, `numbers`, and `level` from
|
|
which we can compose a custom look. Here, we are center-aligning, setting the
|
|
font weight to `{"regular"}` because headings are bold by default, and use the
|
|
[`smallcaps`]($smallcaps) function to render the heading's title in small
|
|
capitals.
|
|
|
|
The only remaining problem is that all headings look the same now. The
|
|
"Motivation" and "Problem Statement" subsections ought to be italic run in
|
|
headers, but right now, they look indistinguishable from the section headings. We
|
|
can fix that by using a `where` selector on our set rule: This is a
|
|
[method]($scripting/#methods) we can call on headings (and other
|
|
elements) that allows us to filter them by their level. We can use it to
|
|
differentiate between section and subsection headings:
|
|
|
|
```example:50,250,265,245
|
|
>>> #let title = [
|
|
>>> A fluid dynamic model
|
|
>>> for glacier flow
|
|
>>> ]
|
|
>>>
|
|
>>> #set text(font: "Linux Libertine", 11pt)
|
|
>>> #set par(justify: true)
|
|
>>> #set page(
|
|
>>> "us-letter",
|
|
>>> margin: auto,
|
|
>>> header: align(
|
|
>>> right + horizon,
|
|
>>> title
|
|
>>> ),
|
|
>>> numbering: "1",
|
|
>>> )
|
|
>>>
|
|
#show heading.where(
|
|
level: 1
|
|
): it => block(width: 100%)[
|
|
#set align(center)
|
|
#set text(12pt, weight: "regular")
|
|
#smallcaps(it.body)
|
|
]
|
|
|
|
#show heading.where(
|
|
level: 2
|
|
): it => text(
|
|
size: 11pt,
|
|
weight: "regular",
|
|
style: "italic",
|
|
it.body + [.],
|
|
)
|
|
>>>
|
|
>>> #align(center, text(
|
|
>>> 17pt,
|
|
>>> weight: "bold",
|
|
>>> title,
|
|
>>> ))
|
|
>>>
|
|
>>> #grid(
|
|
>>> columns: (1fr, 1fr),
|
|
>>> align(center)[
|
|
>>> Therese Tungsten \
|
|
>>> Artos Institute \
|
|
>>> #link("mailto:tung@artos.edu")
|
|
>>> ],
|
|
>>> align(center)[
|
|
>>> Dr. John Doe \
|
|
>>> Artos Institute \
|
|
>>> #link("mailto:doe@artos.edu")
|
|
>>> ]
|
|
>>> )
|
|
>>>
|
|
>>> #align(center)[
|
|
>>> #set par(justify: false)
|
|
>>> *Abstract* \
|
|
>>> #lorem(80)
|
|
>>> ]
|
|
>>>
|
|
>>> #v(4mm)
|
|
>>> #show: rest => columns(2, rest)
|
|
>>>
|
|
>>> = Introduction
|
|
>>> #lorem(35)
|
|
>>>
|
|
>>> == Motivation
|
|
>>> #lorem(45)
|
|
```
|
|
|
|
This looks great! We wrote two show rules that each selectively apply to the
|
|
first and second level headings. We used a `where` selector to filter the
|
|
headings by their level. We then rendered the subsection headings as run-ins. We
|
|
also automatically add a period to the end of the subsection headings.
|
|
|
|
Let's review the conference's style guide:
|
|
- The font should be an 11pt serif font ✓
|
|
- The title should be in 17pt and bold ✓
|
|
- The paper contains a single-column abstract and two-column main text ✓
|
|
- The abstract should be centered ✓
|
|
- The main text should be justified ✓
|
|
- First level section headings should be centered, rendered in small caps and in 13pt ✓
|
|
- Second level headings are run-ins, italicized and have the same size as the
|
|
body text ✓
|
|
- Finally, the pages should be US letter sized, numbered in the center and the
|
|
top right corner of each page should contain the title of the paper ✓
|
|
|
|
We are now in compliance with all of these styles and can submit the paper to
|
|
the conference! The finished paper looks like this:
|
|
|
|
<img
|
|
src="3-advanced-paper.png"
|
|
alt="The finished paper"
|
|
style="box-shadow: 0 4px 12px rgb(89 85 101 / 20%); width: 500px; max-width: 100%; display: block; margin: 24px auto;"
|
|
>
|
|
|
|
## Review
|
|
You have now learned how to create headers and footers, how to use functions and
|
|
scopes to locally override styles, how to create more complex layouts with the [`grid`]($grid) function and how to write show rules for individual functions, and the whole document. You also learned how to use the
|
|
[`where` selector]($styling/#show-rules) to filter the headings by their level.
|
|
|
|
The paper was a great success! You've met a lot of like-minded researchers at
|
|
the conference and are planning a project which you hope to publish at the same
|
|
venue next year. You'll need to write a new paper using the same style guide
|
|
though, so maybe now you want to create a time-saving template for you and your
|
|
team?
|
|
|
|
In the next section, we will learn how to create templates that can be reused in
|
|
multiple documents. This is a more advanced topic, so feel free to come back
|
|
to it later if you don't feel up to it right now.
|