ComicsML Writer's Guide

ComicsML Writer's Guide

1. Introduction

ComicsML is a XML-based markup langauge for digital comics. It is not intended as the main display medium or reader interface for comics, but rather as a standard way for online comics to describe themselves and their content, so that processing programs can easily extract and use this information for a rich variety of purposes.

This document describes the format of ComicsML documents. It does not try to sell you on why you'd want to write one, or what you can do with one once you've written it. Look to the ComicsML resource page to see these issues addressed.

This document assumes a basic familiarity with XML terms and concepts. If you're not so sure about that, allow me to direct you to a fine website, or perhaps a nice book you can buy.

1.1. Status of this document

At the time of this writing (March 2001), ComicsML is a very young and still theoretical concept, full of promise but yet to see application to any real purpose. It will almost certainly need to go through extensive changes before its developers feel confident enough to stick a "1.0" label on it. However, through careful version control, early versions of ComicsML -- including this one -- should prove safe for use by those willing to play the role of early adopters; subsequent versions of this standard will clearly mark themselves as such, and ComicsML processors worth their salt will check the version number-stamps of the documents they encounter before deciding how to treat them.

This documentation covers version 0.2 of ComicsML.

1.2. Terms used in this document

ComicsML tries to use as intutive names as possible for its various components, but it does have to make some compromises with some terms for the sake of consistency, even when the terms seem less applicable to certain kinds of comics.


The abstract notion of a work of comics, rather than any one specific instance or episode of it. Think of this as the whole comic's title, and constant information about it, such as its creative team and cast of characters.


A single instance of a comic. Can be an actual comic strip, or it could be a page, or a book-length series of pages, or whatever its creators consider a single, episodic "chunk" of the comic in question. Less abstractly, a collection of panels, published all at the same time.

2. The root element: <comic>

All of the content within a ComicsML document lives in a single root element, comic. A document must have exactly one of these elements, and no information (beyond the normal XML metadata) may exist outside of it.

The comic element must itself contain a single attribute, version, set to the version number of the ComicsML standard to which the document adheres.

Example 1. Example ComicsML document skeleton

<?xml version="1.0"?>
<!DOCTYPE comic SYSTEM "./comics_ml.dtd">
<comic version="0.2">
 <!-- All my content goes here... -->
<!-- And that's my whole document. -->

3. Comic-level Information

The first thing inside a ComicsML's root element is always a section holding information about the comic in general, names and other facts that don't chnage from strip to strip.


Required. This is simply the comic's title.


Required. There should be one person element for each person involved with the comic's creation. Many comics have only one person behind them, so that would be reflected here. Comics which come from the efforts of several people, though, should mention each of their regular contributors in a separate person element here.

Each person element contains the following elements:


This person's first name. If the person goes by multiple names or initials besides his or her surname, just pile them all into here. For instance, if I signed all my work 'Henry R. H. Peaseblossom', I'd have a firstnameelement of Henry R. H..


Required.The person's surname. If this person goes by only one name (or a one-word pseudonym!) this is where it goes.


The email address of this person.


The URL of this person's website.


What this person does to contribute to the strip's creation. Can be "writer", "artist", "key grip", what have you.


Required. This is a timestamp representing the most recent modification time of this ComicsML document. The format is: YYYY-MM-DD HH:MM:SS


A URL pointing to an icon image for this comic. Optimally a small 'button'-sized graphic


A prose description of this comic.


A URL pointing to this comic's homepage.


One of these elements exists for every specific instance of the comic we wish to represent. We'll cover it in detail in the next section. You can make a legal ComicsML document with no strips at all, if you want to publish only your comic's most general information as XML.

Example 1. Example

Let's look at an example for a notional strip. This excerpt would fit nicely right after the opening of a comic element.

<title>The Adventures of Foo and Bar</title>
 <name>Becky Leftovers</name>
 <name>Sam Handwich</name>
 <!-- Sam doesn't have an email address or URL; I guess he must snailmail his scripts to Becky -->
<last-built>2001-04-01 23:32:41</last-built>
<!-- This comic doesn't have a button graphic, so we'll skip the icon element -->
<description>A weekly comic chronicling the astounding planet-hopping travels of Spaceman Foo and his Martian buddy, Bar.</description>

4. Strip-level information

Each comic contains some number (possibly zero) of strip elements, each of which represents a single instance of the comic, and contain information specific to that once instance.

We can further divide the contents of a strip element into two sections: the first lists general meta-information about the strip, and the second, optional section provides an XML desciption of the strip's content.

4.1. Strip meta-info

This information, along with the comic-level info we've already covered, will prove most interesting for digital comics maintainers who wish to take advantage of ComicsML's syndication possibilities, as you can use them to quickly distribute basic information about new strips as they appear, either just enough to announce their existence, or attaching some "teaser" information as well.

4.1.1. The id attribute

Each strip element must contain an id attribute, set to some alphanumric combination that is unique among all the other strip inside the root comic element.

4.1.2. Elements inside the strip element


Required. The date of this strip's publication, in YYYY-MM-DD format.


This strip's title. Take care not to confuse this concept with the title of the whole comic. (Many comics don't give titles to their individual strips.)


If people besides those listed in the root element's person elements helped create this particular strip, they get listed here, using as many elements as necessary to cover them all. The element's structure is identical to the person element covered earlier.


A URL pointing to a location where one might find this particular strip.


The teaser element contains information about this strip the creators are willing to distribute along with the more general meta-information, and can be useful to augment the comics' syndication. It may contain either or both of these elements:


A text description of this particular strip.


This container element can hold any number of panel elements, if you wish to distribute part of this strip as part of the teaser. We'll cover this particular element in more detail below.


This container element can hold any number of panel elements, which is where all the strip-by-strip content-descriptive part of ComicsML happens. Its use is optional, and online comics creators who wish only to use ComicsML for synidication and index purposes may wish to skip use of this element entirely. We'll cover all this in more detail below.

Example 1. Example of strip meta-info

<strip id="fb2031-b">
 <title>Foo tells a Joke</title>
  <!-- Let's say this strip is based on a reader's idea, 
       and the creators wish to give him credit... -->
   <name>Joey Carbuncle</name>
   <job>Thanks to</job>
  <!-- The creators want to use a teaser, but only a textual one. -->
  <description>Hilarity ensues when Foo tries to teach Bar about the uniquely human concept called "humor".</description>

4.1.3. Strip description

Each strip element in a ComicsML document can hold a panels element, which contains information about each panel in that strip, with one panel element for each distinct drawing in the strip's makeup. Each of these elements may in turn choose the level of description they wish to store; they be as simple as storage places for URLs pointing to their particular panels, or they can use highly detailed text sections that describe the characters, actions, and words that they depict.

It's important to note that, since hammering in the highly-descriptive stuff takes the most work of preparing a ComicsML document (indeed, it's the only part of one that's not automatable, since a computer program can analyze a comic to produce almost all the meta-information that the other elements contain, but it could never be expected to describe a picture in human language), all this information is completely optional. A ComicsML document holding only general information about a comic and its strips can serve quite well as a base for syndication, site construction, and other basic features. However, if present, it can empower a comic with far more features, including text indexing for search engines, character-appearance indexes, machine translatability into other languages, accessibility for the visually impaired, and other benefits. See the essay for more long-winded arguments.

Creators who do wish to use strip-description elements might not find themselves so eager to distribute detailed information about each strip if they also wish to announce its updates via Web syndication, particularly if they depend on revenue generated from visits to a central website. The solution here involves making two ComicsML documents: one holds only syndication-friendly information, and is visible to the world, while another, with detailed panel elements, resides where the general Internet public can't see, but the comic's main website can access and use for whatever it wishes.

With all that in mind, let's see what the <panels> element can contain. None of these elements are required, unless otherwise marked.


A URL where the current panel image might be found.


Text found outside the artwork composing this panel.


A container element for elements describing the visual contents of this panel. These can include any or all of the following, as many times and in whatever order is appropriate to properly simulate the order a reader would encounter them. See the example at the end of this section for an illustration of how this can work.

Quick note about my description of word balloons: I believe that the basic word balloon shapes I describe below are consistent among all comics-drawing cultures, not just Western ones. Please correct me if I'm wrong.


Text that appears in the panel's art, but isn't attributable to any particular character.


A character's thoughts, not spoken aloud. Most comics raditionally display this as text in a cloud-shaped balloon, connected to the thinking character by a trail of circles.

This is actually a container; the content lives in two sub-elements:


Required.The name of a character who is generating this thought.

This element should be filled in, even if a 'character' in the usual sense isn't the one thinking the thought in question. If the telephone on the character's kitchen table is thinking in order to provide the strip's punchline, for example, then the value of this element would be 'telephone'.

If several characters are thinking this thought simultaneously, then there should be one separate character element for each one.


Required.The text of this thought.


A conatiner element like thought, except used for a character's spoken "line". Many comics will probably find this to be their most commonly used panel-desc sub-element.

The speech element can optionally contain one attribute, "tone", which denotes the general tone of voice the character is using. Comics usually represent unusual speaking tones through variously shaped word balloons. If no attribute is supplied, this attribute is assumed to be set to "normal", the ComicsML equivalent of a regular, round word balloon. Other values this attribute can contain run as follows:


Louder-than-normal speech, as represented by a spiky-bordered balloon


Whispered speech, often drawn in a balloon with a broken-line border.


A knife-edged utterance from a likely angry character, as found within a balloon with icicle outlines hanging from it.


Wavering, unsteady speech from an upset character (as during crying, vomiting, and other speech-hindering acts), usually shown inside a ballon with liquid, wavy-lined borders.

Also like the thought element, speech must contain the following sub-elements:


Required.The name of a character speaking this line.

If several characters are speaking this line simultaneously, then there should be one separate character element for each one.


Required.The text of the character's spoken line.


A prose description of the action occurring in this panel.

Stylistically, use of this element can be kept to a minumum by describing only relevent settings and actions, and not every last visual detail, while avoiding repetitiousness. For example, if two characters are walking down the street while talking, and keep this up for the length of the strip, only the first panel element need have an action element dedicated to describing this, much as an author wouldn't ordinarily bother to write "They continued walking, and..." at the start of every paragraph while rendering a similar dialogue into book form (which, incidentally, is pretty much what you're doing anyway. ;-) ). However, if one character suddenly seizes the other's arm to stop their walk, that should be noted in an action element within the appopriate panel.

The narration, action, and the text parts of the thought and speech elements can make use of a handful of inline elements representing speech variations and other common textual artifacts found in comics.


Ordinary spoken emphasis, which many comics make explicit by emboldening the appropriate words.


As above, but extra-strong emphasis, outside of normal conversational tones.


Speech that is distant or otherwise softer than normal conversation, usually depicted as smaller lettering.

Finally, since characters in comics sometimes have a tendency to speak in punctuation marks, such as when a character hears a strange noise and says "?", ComicsML provides some elements to cover for these pecular "vocal effects", usable in the same places the inlines listed above are.






"?!", or something similar.


An empty balloon, or '...' by itself; the character is emoting a palpable pause.

Note that you can combine these effects with the inlines to adjust their "volume". A character who is really surprised and says "!!!" might say "<strong>%lt;bang/></strong>" in ComicsML.

Example 1. Example of Panels element

   <action>Foo and Bar stand on the rocky, barren surface of Mars. Foo nudges Bar with his elbow and grins slyly.</action>
    <text>Hey, Bar, I got a good one: D'you know why the Jovian smoke-lizard crossed the road?</text>
   <action>Foo, laughing with tears streaming down his face, slaps Bar on the back.</action>
    <text>Because it was <emphasis>stapled</emphasis> to the <emphasis>Ganymede ice weasel</emphasis>! <strong>Bwa ha ha ha!</strong></text>

5. Internationalization

XML has plenty of built-in support for nearly every language humans speak today (and will cover the alien ones as soon as we learn them) through a combination of the Unicode standard for character encoding, and flags representing the planet's many countries and languages. To reflect the fact digital comics represent a truly global media, ComicsML documents should take care to specify the languages used by the comics they describe, and they should encode themselves as Unicode, so that they need not limit available language characters to the Latin alphabet.

5.1. Unicode Encoding

Fortunately, a typical ComicsML document won't need a lot of markup to comply with the Unicode standards. Most XML processors parse a document as possessing the UTF-8 flavor of Unicode if it doesn't specify any particular encoding (and isn't something that puts warning-flag bits at the top of the file, like UCS-2 does), and UTF-8 is a superset of ASCII, the text encoding used by most Internet traffic nowadays, so most digital comics creators with prior Web experience can keep on creating documents as they always have.

The bonus you get, though, involves the fact that you can use a text editor or word processor capable of producing Unicode output to insert any sort of characters, be they Latin, Chinese, Cyrillic or Klingon, into your ComicsML documents, and if you can't do so directly (which is likely the case, given that there is so little really Unicode-embracing editor software at this time), you can feel free to make use of XML's entity codes for Unicode character insertion (such as the ubiquitous &#x263A; for a smiley face). Consult your local Unicode reference chart for more information.

5.2. Language

You'll need to be a little more specific about the langauges your comics use, but this actually shouldn't prove very difficult, either, involving just a little more markup, once again using attributes that the W3C has standardized for such things, through the xml:lang attribute, which one can set to the appropriate two-letter langauge code, based on the ISO 639-2 standard.

Most comics speak only one language. In their case, noting this language is easy. My comics are all in english, so at the top level of my document, I put:

     <comic xml:lang="en" version="0.2">

...where en is the ISO standard code for English. Were my comic in Spanish instead, I'd put es as that attribute's value instead (that code being derived from Español, the Spanish word for itself).

XML recognizes scope with language attributes; if you declare another language as the presiding one for a given sub-element, then it overrides the language declared for its parent element, and remains true until that element closes. (And this element in turn can have child elements that contain their own languages, and so on. So, if I had one strip of my comic that was, for some reason, completely in Japanese, I could keep my comic-level language attribute as I've already described but modify the element of that one particular strip like this:

<strip xml:lang="ja">
  <!-- this strip's content here... -->
<!-- My next strip is in English again, so I won't specify a language,
        which will mean the parent "comic" element's langauge will preside,
        as usual
  <!-- And so on... -->

You may apply the xml:lang attribute to any comic, strip, panel, or panel-desc element, as well as any of the block elements within a panel-desc.

Note that you're free to get creative with this markup via the "x-" prefix the W3C makes available for this attribute, which lets you invoke languages that the ISO codes don't handle, whether they are real or fictional. Should a visitor from another world visit your strip's characters (or perhaps exist among its regular cast), and then proceed to address them in its native tongue, we might see something like this:

 <text xml:lang="x-Martian">Wibble wibble wibble wibble?</text>

5.3. Embedded translation

Because it allows for multiple human languages to exist in harmony within that same document, XML opens up the door for embedded translation. ComicsML takes advantage of this by allowing multiple panel-desc elements to coexist within a single panel element -- one for the document's default language, and another for each additional language the document wishes to support, demarcated from the default through application of the xml:lang attribute to each such section beyond the first.

It may seem redundant to provide separate translation for an entire panel-desc, but this has the advantage of clearly separating translations of the panel's description from the purposeful appearance of other languages in the panel's text. If my English-speaking characters receive a phone call from someone speaking Arabic, I'd like the option of tagging the telephone's speech element as xml:lang="ar" without worrying about a ComicsML processing programming misinterpreting this as a translation.


Boy, ComicsML has a lot of territory still to cover. Does it ever! Here's some stuff off the top of my head, all up for discussion and possible addition or modification in near-future revisions of this standard.


ComicsML makes no account for panel layout, mostly because I couldn't think of a way to do this myself without adding frustrating and frightening levels of complexity to the language. I've since seen some encouraging example from other XML-based languages, though, so this is far from a dead issue.

Copyright/Fair Use elements

ComicsML contains no elements explicitly for creators' ownership assertions, and this is likely a necessity for widespread and confident adoption.

Semantic markup

Comics aren't just words and pictures taking up space in panels -- they tell stories, often of significant length, extending over many of what ComicsML would consider "strips", and with distinct beginning and end points. It would be nice to identify a chunk of strip elements as belonging to a common storyline. With some added sophistication, we could add some storyline management features, keeping track of several story-threads as they alternate and interweave.


Should individual strips, or pieces thereof, have ways to link to other places on the Web? People have suggested this to me as a way to let comics subtly let readers learn about the real-world events that the characters in the comic might refer to, or acknowledge the presence of other online comics during character crossovers.

Written by:
Jason McIntosh

All content of this website is copyright © 1999-2023 by Jason McIntosh except where noted.

This particular page was last modified: Thu Nov 17 00:18:42 2005