or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

base-classes.mdconfiguration.mddocument.mdfigures.mdindex.mdlayout.mdlists.mdmath.mdquantities.mdreferences.mdsectioning.mdtables.mdtext-formatting.mdtikz.mdutilities.md

layout.mddocs/

0

# Layout and Positioning

1

2

Advanced layout control with positioning, spacing, alignment, and minipage environments for precise document formatting. PyLaTeX provides comprehensive tools for managing document layout, from simple spacing commands to complex multi-column layouts and precise element positioning.

3

4

## Capabilities

5

6

### Spacing Commands

7

8

Control horizontal and vertical spacing between document elements with precise measurements.

9

10

```python { .api }

11

class HorizontalSpace(CommandBase):

12

def __init__(self, size, *, star=True):

13

"""

14

Add horizontal space between elements.

15

16

Parameters:

17

- size: str, amount of space to add (e.g., '1cm', '10pt', '0.5in')

18

- star: bool, use starred version (hspace*) that doesn't disappear at line breaks

19

"""

20

21

class VerticalSpace(CommandBase):

22

def __init__(self, size, *, star=True):

23

"""

24

Add vertical space between elements.

25

26

Parameters:

27

- size: str, amount of space to add (e.g., '1cm', '10pt', '0.5em')

28

- star: bool, use starred version (vspace*) that doesn't disappear at page breaks

29

"""

30

```

31

32

Usage example:

33

34

```python

35

from pylatex import Document, Section, NoEscape

36

from pylatex.position import HorizontalSpace, VerticalSpace

37

38

doc = Document()

39

40

with doc.create(Section('Spacing Examples')):

41

doc.append('Text before horizontal space')

42

doc.append(HorizontalSpace('2cm'))

43

doc.append('Text after 2cm space')

44

45

doc.append(VerticalSpace('1cm'))

46

doc.append('Text after 1cm vertical space')

47

48

# Negative spacing (overlap)

49

doc.append('Overlapping')

50

doc.append(HorizontalSpace('-0.5cm'))

51

doc.append('Text')

52

53

# Various units

54

doc.append(VerticalSpace('2em')) # Relative to font size

55

doc.append('Text after 2em space')

56

57

doc.append(VerticalSpace('12pt')) # Points

58

doc.append('Text after 12pt space')

59

60

doc.append(VerticalSpace('0.2in')) # Inches

61

doc.append('Text after 0.2 inch space')

62

```

63

64

### Alignment Environments

65

66

Control text and content alignment within specific regions of the document.

67

68

```python { .api }

69

class Center(Environment):

70

"""

71

Center-aligned environment.

72

73

Requires:

74

- ragged2e package (automatically added)

75

"""

76

77

class FlushLeft(Environment):

78

"""

79

Left-aligned environment.

80

81

Requires:

82

- ragged2e package (automatically added)

83

"""

84

85

class FlushRight(Environment):

86

"""

87

Right-aligned environment.

88

89

Requires:

90

- ragged2e package (automatically added)

91

"""

92

```

93

94

Usage example:

95

96

```python

97

from pylatex import Document, Section

98

from pylatex.position import Center, FlushLeft, FlushRight

99

100

doc = Document()

101

102

with doc.create(Section('Text Alignment')):

103

with doc.create(Center()):

104

doc.append('This text is centered on the page.')

105

doc.append('Multiple lines are all centered.')

106

107

with doc.create(FlushLeft()):

108

doc.append('This text is left-aligned.')

109

doc.append('Even in a document with different default alignment.')

110

111

with doc.create(FlushRight()):

112

doc.append('This text is right-aligned.')

113

doc.append('Useful for signatures or dates.')

114

115

# Centering specific elements

116

with doc.create(Section('Centered Elements')):

117

doc.append('Normal paragraph text flows naturally.')

118

119

with doc.create(Center()):

120

doc.append('--- Important Notice ---')

121

122

doc.append('Back to normal text flow after the centered element.')

123

```

124

125

### MiniPage Environment

126

127

Create flexible sub-documents within the main document with independent formatting and layout control.

128

129

```python { .api }

130

class MiniPage(Environment):

131

def __init__(self, *, width=NoEscape(r"\textwidth"), pos=None,

132

height=None, content_pos=None, align=None,

133

fontsize=None, data=None):

134

"""

135

Create a minipage environment for complex layouts.

136

137

Parameters:

138

- width: str or NoEscape, width of minipage (default: full text width)

139

- pos: str, vertical alignment relative to baseline ('c', 't', 'b')

140

- 'c': center (default)

141

- 't': top

142

- 'b': bottom

143

- height: str, fixed height of minipage

144

- content_pos: str, content position within minipage ('c', 't', 'b', 's')

145

- 'c': center

146

- 't': top

147

- 'b': bottom

148

- 's': stretch (spread content)

149

- align: str, text alignment within minipage

150

- fontsize: str, font size for minipage content

151

- data: initial content

152

153

Requires:

154

- ragged2e package (automatically added)

155

"""

156

```

157

158

Usage example:

159

160

```python

161

from pylatex import Document, Section, NoEscape

162

from pylatex.position import MiniPage

163

from pylatex.figure import StandAloneGraphic

164

165

doc = Document()

166

167

with doc.create(Section('Complex Layouts')):

168

# Side-by-side content

169

with doc.create(MiniPage(width=NoEscape(r'0.45\textwidth'))) as left:

170

left.append('This is the left column content. ')

171

left.append('It can contain multiple paragraphs and will wrap ')

172

left.append('within the specified width.')

173

174

doc.append(NoEscape(r'\hfill')) # Push to opposite sides

175

176

with doc.create(MiniPage(width=NoEscape(r'0.45\textwidth'))) as right:

177

right.append('This is the right column content. ')

178

right.append('Both minipages will appear side by side ')

179

right.append('on the same horizontal line.')

180

181

# Text and image layout

182

with doc.create(Section('Mixed Content Layout')):

183

with doc.create(MiniPage(width=NoEscape(r'0.6\textwidth'),

184

pos='t')) as text_box:

185

text_box.append('Detailed explanation of the concept. ')

186

text_box.append('This text appears alongside the diagram. ')

187

text_box.append('The minipage allows precise control over ')

188

text_box.append('the text width and positioning.')

189

190

doc.append(NoEscape(r'\hfill'))

191

192

with doc.create(MiniPage(width=NoEscape(r'0.35\textwidth'),

193

pos='t')) as image_box:

194

image_box.append(StandAloneGraphic('diagram.png',

195

image_options=NoEscape(r'width=\textwidth')))

196

197

# Vertical alignment examples

198

with doc.create(Section('Vertical Alignment')):

199

with doc.create(MiniPage(width=NoEscape(r'0.3\textwidth'),

200

height='4cm', pos='t', content_pos='t')) as top:

201

top.append('Content aligned to top of minipage.')

202

203

doc.append(NoEscape(r'\hfill'))

204

205

with doc.create(MiniPage(width=NoEscape(r'0.3\textwidth'),

206

height='4cm', pos='t', content_pos='c')) as center:

207

center.append('Content centered in minipage.')

208

209

doc.append(NoEscape(r'\hfill'))

210

211

with doc.create(MiniPage(width=NoEscape(r'0.3\textwidth'),

212

height='4cm', pos='t', content_pos='b')) as bottom:

213

bottom.append('Content aligned to bottom.')

214

```

215

216

### Advanced Layout Patterns

217

218

#### Multi-Column Layouts

219

220

```python

221

from pylatex import Document, Section, NoEscape

222

from pylatex.position import MiniPage

223

224

doc = Document()

225

226

with doc.create(Section('Three-Column Layout')):

227

# Three equal columns

228

column_width = NoEscape(r'0.32\textwidth')

229

230

with doc.create(MiniPage(width=column_width, pos='t')) as col1:

231

col1.append('First Column')

232

col1.append('Content for the first column goes here. ')

233

col1.append('This could be text, lists, or other elements.')

234

235

doc.append(NoEscape(r'\hfill'))

236

237

with doc.create(MiniPage(width=column_width, pos='t')) as col2:

238

col2.append('Second Column')

239

col2.append('Content for the second column. ')

240

col2.append('Each column is independent.')

241

242

doc.append(NoEscape(r'\hfill'))

243

244

with doc.create(MiniPage(width=column_width, pos='t')) as col3:

245

col3.append('Third Column')

246

col3.append('Final column content. ')

247

col3.append('Columns align at the top.')

248

249

# Asymmetric layout

250

with doc.create(Section('Asymmetric Layout')):

251

# Wide left, narrow right

252

with doc.create(MiniPage(width=NoEscape(r'0.7\textwidth'))) as main:

253

main.append('Main Content Area')

254

main.append('This wider area contains the primary content. ')

255

main.append('It takes up most of the page width.')

256

257

doc.append(NoEscape(r'\hfill'))

258

259

with doc.create(MiniPage(width=NoEscape(r'0.25\textwidth'))) as sidebar:

260

sidebar.append('Sidebar')

261

sidebar.append('Notes, references, or supplementary information.')

262

```

263

264

#### Boxed Content

265

266

```python

267

from pylatex import Document, Section, Command, NoEscape

268

from pylatex.position import MiniPage, Center

269

270

doc = Document()

271

272

with doc.create(Section('Boxed Content')):

273

# Framed minipage

274

with doc.create(Center()):

275

doc.append(Command('fbox',

276

MiniPage(width=NoEscape(r'0.8\textwidth'), data=[

277

'Important Information',

278

NoEscape(r'\\[0.5em]'),

279

'This content is highlighted in a box for emphasis. ',

280

'The minipage provides the content structure, while ',

281

'fbox adds the border.'

282

])

283

))

284

285

# Custom spacing and padding

286

with doc.create(Section('Padded Boxes')):

287

with doc.create(Center()):

288

# Custom padding using fboxsep

289

doc.append(Command('setlength', arguments=[NoEscape(r'\fboxsep'), '10pt']))

290

doc.append(Command('fbox',

291

MiniPage(width=NoEscape(r'0.6\textwidth'), data=[

292

'Padded Content',

293

NoEscape(r'\\[0.5em]'),

294

'Extra padding makes this more readable.'

295

])

296

))

297

```

298

299

#### Header and Footer Layouts

300

301

```python

302

from pylatex import Document, Section, NoEscape

303

from pylatex.position import MiniPage, FlushLeft, FlushRight, Center

304

305

doc = Document()

306

307

# Custom header layout

308

def create_header(title, author, date):

309

with doc.create(MiniPage(width=NoEscape(r'\textwidth'))) as header:

310

with header.create(FlushLeft()):

311

header.append(f'Title: {title}')

312

313

with header.create(Center()):

314

header.append(f'Author: {author}')

315

316

with header.create(FlushRight()):

317

header.append(f'Date: {date}')

318

319

doc.append(NoEscape(r'\hrule'))

320

doc.append(NoEscape(r'\vspace{1em}'))

321

322

create_header('Research Report', 'Dr. Jane Smith', '2024-01-15')

323

324

with doc.create(Section('Document Content')):

325

doc.append('Main document content follows the custom header.')

326

```

327

328

## Text Block Positioning

329

330

```python { .api }

331

class TextBlock(Environment):

332

def __init__(self, width, horizontal_pos, vertical_pos, *,

333

indent=False, data=None):

334

"""

335

Create positioned text block using textpos package.

336

337

Parameters:

338

- width: float, width of text block in TPHorizModule units

339

- horizontal_pos: float, horizontal position in TPHorizModule units

340

- vertical_pos: float, vertical position in TPVertModule units

341

- indent: bool, enable paragraph indentation (default False)

342

- data: initial content for the text block

343

344

Requires:

345

- textpos package (automatically added)

346

"""

347

```

348

349

Usage example:

350

351

```python

352

from pylatex import Document, Package

353

from pylatex.position import TextBlock

354

355

doc = Document()

356

doc.packages.append(Package('textpos'))

357

358

# Absolute positioning

359

with doc.create(TextBlock(width='5cm', horizontal_pos=2, vertical_pos=3)):

360

doc.append('This text block is positioned at specific coordinates.')

361

doc.append('Useful for overlays, annotations, or precise layouts.')

362

```

363

364

## Layout Utilities and Helpers

365

366

### Flexible Spacing

367

368

```python

369

from pylatex import Document, NoEscape

370

from pylatex.position import HorizontalSpace, VerticalSpace

371

372

doc = Document()

373

374

# Responsive spacing

375

doc.append('Text')

376

doc.append(HorizontalSpace(NoEscape(r'0.1\textwidth'))) # 10% of text width

377

doc.append('More text')

378

379

# Fill remaining space

380

doc.append('Left')

381

doc.append(NoEscape(r'\hfill')) # Fills all available space

382

doc.append('Right')

383

384

# Stretchable space

385

doc.append('Item 1')

386

doc.append(NoEscape(r'\hspace{\stretch{1}}'))

387

doc.append('Item 2')

388

doc.append(NoEscape(r'\hspace{\stretch{2}}')) # Twice as much space

389

doc.append('Item 3')

390

```

391

392

### Page Layout Control

393

394

```python

395

from pylatex import Document, Command, Package, NoEscape

396

from pylatex.position import VerticalSpace

397

398

doc = Document()

399

doc.packages.append(Package('geometry', options=['margin=1in']))

400

401

# Page-level spacing adjustments

402

doc.preamble.append(Command('setlength', arguments=[NoEscape(r'\parskip'), '1em']))

403

doc.preamble.append(Command('setlength', arguments=[NoEscape(r'\parindent'), '0pt']))

404

405

# Dynamic page breaks

406

doc.append('Content before page break')

407

doc.append(VerticalSpace(NoEscape(r'\fill'))) # Push to bottom

408

doc.append('Content at bottom of page')

409

doc.append(Command('newpage'))

410

doc.append('Content on next page')

411

```

412

413

## Advanced Layout Techniques

414

415

### Overlay Positioning

416

417

```python

418

from pylatex import Document, Package, NoEscape, Command

419

from pylatex.position import MiniPage

420

421

doc = Document()

422

doc.packages.append(Package('tikz'))

423

424

# TikZ overlay on minipage

425

with doc.create(MiniPage(width=NoEscape(r'0.8\textwidth'))) as container:

426

container.append('Base content that will have overlays.')

427

container.append(NoEscape(r'\\[2em]'))

428

container.append('More base content here.')

429

430

# Add TikZ overlay

431

container.append(NoEscape(r'''

432

\begin{tikzpicture}[remember picture, overlay]

433

\node[red, font=\Large] at (2, 0) {Overlay Text};

434

\draw[blue, thick] (0, -1) rectangle (4, 1);

435

\end{tikzpicture}

436

'''))

437

```

438

439

### Responsive Layouts

440

441

```python

442

from pylatex import Document, Command, NoEscape

443

from pylatex.position import MiniPage

444

445

doc = Document()

446

447

# Conditional layout based on text width

448

doc.preamble.append(Command('newlength', arguments=NoEscape(r'\columnwidth')))

449

doc.preamble.append(Command('setlength', arguments=[

450

NoEscape(r'\columnwidth'), NoEscape(r'0.45\textwidth')

451

]))

452

453

# Use calculated width

454

with doc.create(MiniPage(width=NoEscape(r'\columnwidth'))) as responsive:

455

responsive.append('This minipage uses a calculated width.')

456

responsive.append('It adapts to different document settings.')

457

```

458

459

## Package Dependencies

460

461

Layout functionality requires specific LaTeX packages:

462

463

- **Basic spacing**: No additional packages

464

- **Alignment environments**: `ragged2e` package (automatically added)

465

- **MiniPage**: `ragged2e` package (automatically added)

466

- **TextBlock**: `textpos` package (must be added manually)

467

- **Advanced positioning**: `tikz` package for overlays

468

469

```python

470

from pylatex import Document, Package

471

472

doc = Document()

473

474

# Layout packages

475

doc.packages.append(Package('ragged2e'))

476

doc.packages.append(Package('textpos'))

477

doc.packages.append(Package('tikz'))

478

doc.packages.append(Package('geometry', options=['margin=1in']))

479

```

480

481

## Layout Best Practices

482

483

### Consistent Spacing

484

485

```python

486

from pylatex import Document, Command, NoEscape

487

from pylatex.position import VerticalSpace

488

489

doc = Document()

490

491

# Define standard spacing units

492

doc.preamble.append(Command('newlength', arguments=NoEscape(r'\standardspace')))

493

doc.preamble.append(Command('setlength', arguments=[

494

NoEscape(r'\standardspace'), '1em'

495

]))

496

497

# Use consistent spacing throughout

498

doc.append('Section 1')

499

doc.append(VerticalSpace(NoEscape(r'\standardspace')))

500

doc.append('Section 2')

501

doc.append(VerticalSpace(NoEscape(r'\standardspace')))

502

doc.append('Section 3')

503

```

504

505

### Modular Layout Components

506

507

```python

508

from pylatex import Document, NoEscape

509

from pylatex.position import MiniPage, Center

510

511

def create_info_box(title, content, width=NoEscape(r'0.8\textwidth')):

512

"""Create a standardized information box."""

513

with doc.create(Center()):

514

with doc.create(MiniPage(width=width)) as box:

515

with box.create(Center()):

516

box.append(Command('textbf', title))

517

box.append(NoEscape(r'\\[0.5em]'))

518

box.append(content)

519

return box

520

521

doc = Document()

522

523

# Reusable layout components

524

create_info_box('Important Note', 'This is highlighted information.')

525

create_info_box('Warning', 'Please review this carefully.')

526

```

527

528

The layout system in PyLaTeX provides powerful tools for creating professional, precisely controlled document layouts while maintaining the flexibility to adapt to different content requirements.