After the font tables a WOFF file may carry two more blocks, both optional: extended metadata, an XML document about the font, its makers and its licence; and private data, which can hold anything. Neither is part of the font. They must not change how the font loads or looks, and a browser does not need to read them. A file without them, like the one in the header example, has zeros in all five of their offset and length fields.
Where the blocks go
The blocks of a WOFF file come in a fixed order: header, table directory, font tables, metadata, private data.
- The metadata block, when present, comes straight after the last font table, which
is padded to a four-byte boundary, so the block starts on one.
metaOffsetsays where it starts andmetaLengthhow long it is. If it is the last block in the file, no padding should follow it. - The private data block, when present, is always the last block and ends exactly at the end of the file. It starts on a four-byte boundary, with up to three zero bytes of padding after the metadata or the last table.
- A block that is absent has both its offset and its length set to 0. A block that overlaps a table or the other block, runs past the end of the file, or leaves bytes that are not padding makes the whole file invalid.
Extended metadata
The metadata is an XML document in UTF-8, compressed with zlib exactly as the font
tables are. Unlike them it is always compressed, even when that does not make it
smaller, so metaLength is the compressed length and
metaOrigLength the length of the XML.
The block is invalid if it does not uncompress, if it uncompresses to a length other
than metaOrigLength, or if the XML is not well-formed, not UTF-8 or does
not follow the schema below. That includes an element the schema does not list: the
extension element is the place for anything else. A user agent must
ignore an invalid metadata block, as if it were not there, and still load the font.
The elements are in no namespace. The root is metadata, and its children
may come in any order. Elements whose content is text can be given in
several languages, one text element per language.
Elements
Every element the specification defines. Required attributes are marked; the rest are optional.
| Element | Inside | How many | Attributes | Content and meaning |
|---|---|---|---|---|
metadata | root | 1 | version (required, 1.0) | The document. Its children, all optional, in any order: uniqueid, vendor, credits, description, license, copyright, trademark, licensee, extension. |
uniqueid | metadata | 0 or 1 (recommended) | id (required) | Empty. An identifier for this font, whose form the maker chooses; the specification recommends a reverse-DNS prefix, such as com.example.font.123. It is not an XML ID. |
vendor | metadata | 0 or 1 (recommended) | name (required), url, dir, class | Empty. The font’s vendor, and a link to its site. |
credits | metadata | 0 or 1 | none | One or more credit elements. |
credit | credits | 1 or more | name (required), url, role, dir, class | Empty. A person or company who worked on the font. role is free text, such as “Lead” or “Contributor”; no values are defined. |
description | metadata | 0 or 1 | url | One or more text: a description of the font. |
license | metadata | 0 or 1 | url, id | Zero or more text: the licence, or a summary of it. url links to the full licence; id is an identifier for it. The only element that may be empty. |
copyright | metadata | 0 or 1 | none | One or more text: the copyright notice. |
trademark | metadata | 0 or 1 | none | One or more text: the trademark notice. |
licensee | metadata | 0 or 1 | name (required), dir, class | Empty. Who the font was licensed to. |
extension | metadata | 0 or more | id | Zero or more name (a title for the group, one per language), then one or more item. Metadata the specification does not define. |
item | extension | 1 or more | id | One or more name and one or more value: a name and value pair, in as many languages as wanted. An item without a name or a value is invalid and should be ignored. |
name | extension, item | 0 or more in extension, 1 or more in item | xml:lang, dir, class | Text. |
value | item | 1 or more | xml:lang, dir, class | Text. |
text | description, license, copyright, trademark | 1 or more (0 or more in license) | xml:lang, dir, class | Text in one language, which may contain div and span. |
div | text, div | 0 or more | dir, class | A block of text, such as a paragraph; may contain text, div and span. |
span | text, div, span | 0 or more | dir, class | A run of text inside a line; may contain text and span. |
Common attributes
| Attribute | Values | Meaning |
|---|---|---|
xml:lang | a BCP 47 language tag, such as en or fr | The language of the text. Older files use a plain lang attribute instead, which readers should treat the same way; new files should use xml:lang. |
dir | ltr or rtl | The direction of the text, left to right or right to left. Left to right when it is missing. |
class | tokens separated by spaces | Names for styling or for software to use. No values are defined. |
url | a URL | A link for the element: the vendor’s or contributor’s site, more about the font, the full licence. |
id | text | An identifier, on uniqueid, license, extension and item. None of them is of the XML type ID. |
Example
A small metadata document in the shape of the specification’s examples, using every kind of element:
<?xml version="1.0" encoding="UTF-8"?>
<metadata version="1.0">
<uniqueid id="com.example.sans.regular.1-000"/>
<vendor name="Example Type" url="https://example.com/"/>
<credits>
<credit name="A. Designer" role="Lead"/>
<credit name="B. Engineer" role="Contributor"/>
</credits>
<description>
<text xml:lang="en">A plain sans serif for text.</text>
</description>
<license url="https://example.com/licence" id="example-web-1">
<text xml:lang="en"><div>For use on example.com only.</div></text>
<text xml:lang="fr"><div>Pour example.com uniquement.</div></text>
</license>
<copyright>
<text xml:lang="en">Copyright 2012 Example Type.</text>
</copyright>
<trademark>
<text xml:lang="en">Example Sans is a trademark of Example Type.</text>
</trademark>
<licensee name="Example Ltd"/>
<extension id="com.example.build">
<name xml:lang="en">Build</name>
<item id="tool">
<name xml:lang="en">Tool</name>
<value xml:lang="en">fontmake</value>
</item>
</extension>
</metadata>
Private data
The private data block holds whatever the font’s maker wants to put there, in any
format. The specification defines nothing about its contents, and a user agent must
make no assumptions about them and must not let them change how the font is used. It
is not compressed by WOFF; privLength is simply its length in bytes.
Its only rules are about where it goes: it starts on a four-byte boundary at
privOffset and is the last thing in the file, so privOffset
+ privLength equals the header’s length.