typst_library/layout/
columns.rs

1use std::num::NonZeroUsize;
2
3use crate::diag::SourceResult;
4use crate::engine::Engine;
5use crate::foundations::{elem, Content, NativeElement, Packed, Show, StyleChain};
6use crate::layout::{BlockElem, Length, Ratio, Rel};
7
8/// Separates a region into multiple equally sized columns.
9///
10/// The `column` function lets you separate the interior of any container into
11/// multiple columns. It will currently not balance the height of the columns.
12/// Instead, the columns will take up the height of their container or the
13/// remaining height on the page. Support for balanced columns is planned for
14/// the future.
15///
16/// # Page-level columns { #page-level }
17/// If you need to insert columns across your whole document, use the `{page}`
18/// function's [`columns` parameter]($page.columns) instead. This will create
19/// the columns directly at the page-level rather than wrapping all of your
20/// content in a layout container. As a result, things like
21/// [pagebreaks]($pagebreak), [footnotes]($footnote), and [line
22/// numbers]($par.line) will continue to work as expected. For more information,
23/// also read the [relevant part of the page setup
24/// guide]($guides/page-setup-guide/#columns).
25///
26/// # Breaking out of columns { #breaking-out }
27/// To temporarily break out of columns (e.g. for a paper's title), use
28/// parent-scoped floating placement:
29///
30/// ```example:single
31/// #set page(columns: 2, height: 150pt)
32///
33/// #place(
34///   top + center,
35///   scope: "parent",
36///   float: true,
37///   text(1.4em, weight: "bold")[
38///     My document
39///   ],
40/// )
41///
42/// #lorem(40)
43/// ```
44#[elem(Show)]
45pub struct ColumnsElem {
46    /// The number of columns.
47    #[positional]
48    #[default(NonZeroUsize::new(2).unwrap())]
49    pub count: NonZeroUsize,
50
51    /// The size of the gutter space between each column.
52    #[resolve]
53    #[default(Ratio::new(0.04).into())]
54    pub gutter: Rel<Length>,
55
56    /// The content that should be layouted into the columns.
57    #[required]
58    pub body: Content,
59}
60
61impl Show for Packed<ColumnsElem> {
62    fn show(&self, engine: &mut Engine, _: StyleChain) -> SourceResult<Content> {
63        Ok(BlockElem::multi_layouter(self.clone(), engine.routines.layout_columns)
64            .pack()
65            .spanned(self.span()))
66    }
67}
68
69/// Forces a column break.
70///
71/// The function will behave like a [page break]($pagebreak) when used in a
72/// single column layout or the last column on a page. Otherwise, content after
73/// the column break will be placed in the next column.
74///
75/// # Example
76/// ```example
77/// #set page(columns: 2)
78/// Preliminary findings from our
79/// ongoing research project have
80/// revealed a hitherto unknown
81/// phenomenon of extraordinary
82/// significance.
83///
84/// #colbreak()
85/// Through rigorous experimentation
86/// and analysis, we have discovered
87/// a hitherto uncharacterized process
88/// that defies our current
89/// understanding of the fundamental
90/// laws of nature.
91/// ```
92#[elem(title = "Column Break")]
93pub struct ColbreakElem {
94    /// If `{true}`, the column break is skipped if the current column is
95    /// already empty.
96    #[default(false)]
97    pub weak: bool,
98}