Class options & authoring

When the ready-made classes run out, you can write your own. This page is about authoring a class. First we cover the standard options a class usually accepts (font size, paper, columns, and so on), then we build up the contents of a .cls or .sty file — identifying it with \ProvidesClass, declaring options with \DeclareOption, executing them with \ProcessOptions, and building on an existing class with \LoadClass — finishing with a complete example that extends article. For using options from the document side, see “Document class & preamble.”

Class or package?

Before writing anything, decide whether you are making a class (.cls) or a package (.sty). A class defines the kind of document itself and is loaded exactly once, with \documentclass; it supplies the overall skeleton and default look of a paper, a book, or a set of slides. A package, by contrast, is loaded with \usepackageany number of them — and adds features independent of the document kind (amsmath for mathematics, graphicx for figures, and so on).

In the words of the official clsguide, the test is simple: if the feature could be used with any document class, make it a package; if not, make it a class. Want to define a whole look? A class. Want to add only a feature? A package. The authoring conventions are nearly identical either way — the commands just come in a Class flavour and a Package flavour (\ProvidesClass\ProvidesPackage, \LoadClass\RequirePackage, \PassOptionsToClass\PassOptionsToPackage).

The standard options your class accepts

Users will pass options to your class just as they would to a standard one, so at minimum you want to support the usual cast: 10pt / 11pt / 12pt for the base body size, a4paper / letterpaper for paper, onecolumn / twocolumn for columns, oneside / twoside for the printing side, and draft (which marks overfull lines with a black bar; its opposite is final). You need not implement these yourself — as we will see under “Hand options to a base class,” the standard move is simply to forward them to a base class such as article.

OptionMeaningDefault
10pt / 11pt / 12ptBase body font size10pt
a4paper / letterpaperPaper size (also b5paper, legalpaper, etc.)letterpaper
onecolumn / twocolumnOne column / two columnsonecolumn
oneside / twosideOne-sided / two-sided layoutoneside (but twoside for book)
draft / finalWhether to mark overfull lines with a black barfinal

For worked examples of specifying and using these options on the document’s \documentclass[...] side — and book-specific ones like openright — see the sibling page “Document class & preamble.” From here on we focus on how to write the class that receives them.

Identify the file up front

The first two lines of a class file (myclass.cls) are almost boilerplate. First, \NeedsTeXFormat{LaTeX2e} declares that the file is meant for LaTeX2e (loading it under an older format triggers a warning). Then \ProvidesClass{myclass}[2026/01/01 v1.0 ...] announces the class name, release date, version, and a short description. The bracketed part is optional, but supplying it lets users request a minimum version via the date (in YYYY/MM/DD form)\documentclass{...}[2026/01/01] — and records the identification in the log.

If you are writing a package, the counterpart is \ProvidesPackage{mypackage}[2026/01/01 v1.0 ...]; \NeedsTeXFormat is shared by both. As a firm rule, the name in \ProvidesClass / \ProvidesPackage must match the actual file name — inside myclass.cls, you always write \ProvidesClass{myclass}.

latex
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{myclass}[2026/01/01 v1.0 My example class]

Declaring options — \DeclareOption

You declare each option your class accepts with \DeclareOption{option}{code}. When the user specifies that option, its code runs at the moment \ProcessOptions is reached (described below). For instance, you might provide your own draft switch that sets a boolean flag.

The catch-all for options you did not declare is the starred form \DeclareOption*{code}. Inside it, \CurrentOption expands to the name of the option currently being processed. The single most common line in a custom class forwards any unknown option straight to the base class. Thanks to it, users can pass standard options like 10pt or a4paper as a matter of course, even though you never declared them yourself.

latex
% pass anything we do not handle ourselves on to article
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}}

In a package you use the equivalent \PassOptionsToPackage{\CurrentOption}{base}. If you want to apply defaults before \ProcessOptions, write \ExecuteOptions{a4paper,11pt} — that runs the code for those options first, so they take effect even when the user specifies nothing.

Process options, then hand off to a base class

Declaring options does nothing on its own; their code runs only when you call \ProcessOptions. In practice you almost always write \ProcessOptions\relax. Because a starred form \ProcessOptions* also exists, the trailing \relax is the idiom that reliably selects the unstarred one. Unstarred \ProcessOptions handles options in the order you declared them; the starred form handles them in the order the caller specified.

Building a layout from scratch is a lot of work, so most custom classes stand on an existing one. That is \LoadClass[options]{article}, which pulls in all of article.cls’s commands and styling (you may pass twocolumn and friends in the brackets). \LoadClass may be used only inside a class file. Order matters: so that the options the user gave on \documentclass[...] reach the base class, put \LoadClass after option processing (\ProcessOptions). Set up forwarding first, let \ProcessOptions dispatch the options, and only then load the base.

If you simply want to give the base class the very same options your class received, \LoadClassWithOptions{article} is handy (it forwards the class’s global options as-is). When writing a package, use \RequirePackage instead of \LoadClass (it is the author’s equivalent of \usepackage in the preamble), and \RequirePackageWithOptions for the pass-everything-through case.

Everything after \LoadClass is where the character of your class finally goes: redefine heading styles with \renewcommand, adjust margins with \setlength, define new commands and environments via \newcommand / \newenvironment — and load any extra packages you need with \RequirePackage from here.

A complete minimal class extending article

Putting it all together gives this minimal .cls. It builds on article, adds its own draft option, forwards unknown options to article, and finally tidies the margins and defines one command of its own. Save it as myclass.cls and use it from a document with \documentclass[11pt,a4paper]{myclass}.

latex
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{myclass}[2026/01/01 v1.0 My example class]

% --- declare options ---
\newif\ifmy@draft
\DeclareOption{draft}{\my@drafttrue}
% forward everything else to article
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}}

% --- execute and load the base class ---
\ExecuteOptions{a4paper}      % a default if the user gives none
\ProcessOptions\relax
\LoadClass{article}

% --- this class's own setup ---
\RequirePackage[margin=25mm]{geometry}
\setlength{\parindent}{0pt}
\newcommand{\version}{v1.0}
\ifmy@draft \RequirePackage{draftwatermark}\fi

\endinput

The closing \endinput tells LaTeX to read no further from this file; it is conventional to include it. To make a package instead, swap the opening for \ProvidesPackage and \LoadClass for \RequirePackage: the same skeleton becomes a .sty file.

The modern way: key–value options (expl3)

The \DeclareOption mechanism above remains perfectly valid, but it is built mainly around on/off switch-style options. For new code that wants natural key–value options like name=value, the current recommendation is the LaTeX kernel’s own interface: declare keys with \DeclareKeys and process them with \ProcessKeyOptions. Built on expl3 (LaTeX3)’s l3keys, it ships as part of recent LaTeX kernels.

This used to be done with the l3keys2e package, but the core of that functionality is now folded into the kernel, so new code can call \ProcessKeyOptions directly without loading the package. That said, existing tutorials and many packages still center on the \DeclareOption style, so understanding this page’s skeleton remains valuable. When you move to key–value options, consult the relevant section of the current clsguide (“LaTeX2e for class and package writers”).

A minimal test before sharing

A class affects the whole document as soon as it is loaded, so settle its behavior with a tiny test document before writing real content. First check that standard options such as 10pt, 11pt, a4paper, and draft reach the base class, while only your own options are handled by your own code. If this fails, the cause is usually the position of \ProcessOptions / \ProcessKeyOptions, forwarding of unknown options, or the order of \LoadClass.

latex
\documentclass[11pt,a4paper,draft]{myclass}
\begin{document}
\section{Smoke test}
本文の基準サイズ、用紙、下書き表示、見出し、余白を確認する。
\end{document}
  • Does the log identify the class? Confirm that the date and version from \ProvidesClass appear in the .log. A mismatch between file name and class name causes confusion later.
  • Did you preserve standard options? If 11pt or twocolumn is ignored, revisit the handler that forwards unknown options to the base class.
  • Do document macros behave in the preamble and body? Compile one heading, note, figure, and table, because those are the first things real users will touch.
  • Keep everything after \endinput inert. Leaving notes or samples after it can lead to unexpected text being read if the marker is missing or moved.

Think about the distribution shape

A custom class is tested not when it first works for you, but when someone else loads it in another environment. At minimum, keep the .cls, a short sample document, a README, and a changelog together, and make sure the sample compiles as-is. In the README, separate options forwarded to the base class from options handled by your class, so users can see where 11pt or a4paper takes effect. Put one heading, list, figure/table, and bibliography in the sample, so the elements a class most often breaks are checked together.

terminal
myclass/
  myclass.cls
  sample.tex
  README.md
  CHANGELOG.md

Before distribution, put \listfiles in the sample so the log records the files and versions that were loaded. That helps diagnose whether a user has an old local myclass.cls, or whether required packages are being loaded as expected. Because a class is the foundation of the whole document, careful loading order, option processing, and log information matter more over time than adding another body-text macro.