#+CAPTION: my-caption

I get a caption (with a number) both in LaTeX and in HTML. The same with tables and src blocks (which become listings in LaTeX)

But with a theorem, definition, ... and all other mathematical environments I cannot get a title and a number.

#+ATTR_LATEX: :options [my-theorem]

works for LaTeX, but in HTML I don't get the caption (and most importantly the number).

This instead breaks also LaTeX because inserts a \caption macro inside the environment:

#+CAPTION: my-theorem

How can I create a new special block which takes care of numbering also for HTML (like for figures, tables and listings)?

For the caption the solution is very simple:

#+ATTR_LATEX: :options [my-theorem]
@@html:<span class="theorem-title">my-theorem</span>@@

so the difficult part is taking care of the numbering.

With org-special-block-extras I achieved this:

(defvar special-block-definition-counter 0)
(defblock definition (title nil) (label nil unnumbered nil)
  "Definition special block."
  (unless unnumbered (cl-incf special-block-definition-counter))
    ((org-export-derived-backend-p org-export-current-backend 'latex)
     (concat "\\begin{definition" (when unnumbered "*") "}{%s}{%s}\n"
             "\\end{definition" (when unnumbered "*") "}"))
    ((org-export-derived-backend-p org-export-current-backend 'html)
     (concat "<p class=\"admonition-title definition\">Definizione" (unless unnumbered (format " %d" special-block-definition-counter)) (when title ": ") "%s</p>"
             "<div id=\"%s\" class=\"special-block definition\">%s</div>")))
   (or title "") (or label "") contents))


#+BEGIN_definition Definition title :label def:example

To export correctly for ePub a patch is needed (for more info: https://github.com/alhassy/org-special-block-extras/issues/12):

(add-to-list 'org-export-filter-parse-tree-functions
             (lambda (tree backend info)
               (when (eq backend 'epub)
                 (org-element-map tree 'export-block
                   (lambda (el)
                     (when (string= (org-element-property :type el) "EPUB")
                       (org-element-put-property el :type "HTML")))))

Now I have only to manage the internal links (label/reference).

  • 1
    My knee-jerk reaction would be to derive a new exporter from the HTML exporter with the only difference being the handling of special blocks (in particular, the theorem block). But I don't know enough about HTML/CSS to say definitively that you have to do it this way: it might be possible to do something outside of the exporter. If you do decide to go with a derived exporter, examples can be found in the Org mode sources. See Appendix A.4 of the manual (C-h i g(org)adding export TAB will get you there) and the doc on Worg that ...
    – NickD
    Aug 26, 2021 at 1:37
  • 1
    ... is referenced therein. However, you do need to know some elisp for that.
    – NickD
    Aug 26, 2021 at 1:38

1 Answer 1


I finally solved using org-special-block-extras:

  1. Define a macro to define a new theorem type (calls defblock) and its link. This also takes count in a list of all the labels to get numbers and links.
(defmacro special-block-labels-push (name label)
  (let ((labels (format "special-block-%s-labels" name))
        (labels-cdr (format "special-block-%s-labels-cdr" name)))
    `(let ((label (list (format "%s" ,label))))
       (setq ,(intern labels-cdr)
             (if ,(intern labels-cdr)
                 (setcdr ,(intern labels-cdr) label)
               (setq ,(intern labels) label))))))

(defmacro defspeciallink (name prefix)
     (defvar ,(intern (format "special-block-%s-labels" name)) '()) ; to store this theroem labels
     (defvar ,(intern (format "special-block-%s-labels-cdr" name)) nil)

     (defblock ,prefix (ref nil) ()
       ,(format "Reference a %s special block." name)
         ((org-export-derived-backend-p org-export-current-backend 'latex)
          ,(format "\\ref{%s:%%s}" prefix)) ; use standard ref in LateX
         ((org-export-derived-backend-p org-export-current-backend 'html)
          ,(format "<a href=\"#%s:%%s\">%%d</a>" prefix))) ; in HTML the number has to be print manually, finding the position of the label in the list
        ref (1+ (cl-position (format "%s" ref) ,(intern (format "special-block-%s-labels" name)) :test 'equal)))))) ; sum one because lists are zero based

(defmacro deftheorem (name display-name prefix &optional tcb)
  "Defines a new theorem type called NAME (rendered as DISPLAY-NAME in HTML) which labels start with PREFIX. If TCB is not nil, in LaTeX the tcbtheorem syntax is used.
,#+BEGIN_name Title :label lbl
As can be seen in [[prefix:lbl]]
     (defspeciallink ,name ,prefix)

     (defblock ,name (title nil) (label nil unnumbered nil)
       ,(format "Define %s special block." name)
       (unless unnumbered (special-block-labels-push ,name label)) ; add label to list
         ((org-export-derived-backend-p org-export-current-backend 'latex)
          (concat ,(format "\\begin{%s" name) (when unnumbered "*") "}"
                  ,(if tcb "{%s}{%s}" (format "[%%s]\\label{%s:%%s}" prefix)) ; tcbtheorem or standard
                  ,(format "\\end{%s" name) (when unnumbered "*") "}"))
         ((org-export-derived-backend-p org-export-current-backend 'html)
          (concat ,(format "<p class=\"admonition-title %s\">%s" name display-name)
                  (unless unnumbered (format " %d" (length ,(intern (format "special-block-%s-labels" name)))))
                  (when title ": ") "%s</p>"
                  ,(format "<div id=\"%s:%%s\" class=\"special-block %s\">%%s</div>" prefix name))))
        (or title "") (or label "") contents))))

It works both with standard LaTeX theorems and tcbtheorems (using the last parameter.

  1. Add new theorems using the previous macro:
(deftheorem definition "Definizione" def)
(deftheorem theorem "Teorema" thm)
(deftheorem postulate "Postulato" pos)
(deftheorem axiom "Assioma" axi)
(deftheorem proposition "Proposizione" pro)
(deftheorem corollary "Corollario" cor)
(deftheorem lemma "Lemma" lem)
(deftheorem principia "Principio" pri t)
(deftheorem alg "Algoritmo" alg t)
  1. (OPT) add new LatTeX theorems:
\newtcbtheorem[auto counter,number within=chapter]{principia}{Principio}{propstyle}{pri}
\newtcbtheorem[auto counter,number within=chapter]{alg}{Algoritmo}{algstyle}{alg}
  1. Add CSS style (I based on ReadTheOrg):
/* BLOCKS */
#content .special-block {
  padding: 12px;
  line-height: 24px;
  margin-bottom: 24px;
#content .special-block p:last-child {
  margin-bottom: 0;
#content .admonition-title {
  color: #fff;
  font-weight: bold;
  display: block;
  padding: 6px 12px;
  margin-bottom: 0px;
/* Definition: green */
#content .definition {background-color: #dbfaf4;}
#content p.admonition-title.definition {background-color: #1abc9c;}
/* Theorem: orange */
#content .theorem, 
#content .postulate, 
#content .axiom, 
#content .corollary, 
#content .lemma {background-color: #ffedcc;}
#content p.admonition-title.theorem,
#content p.admonition-title.postulate,
#content p.admonition-title.axiom,
#content p.admonition-title.corollary,
#content p.admonition-title.lemma {background-color: #f0b37e;}
/* Proposition: blue*/
#content .proposition,
#content .principia {background-color: #e7f2fa;}
#content p.admonition-title.proposition,
#content p.admonition-title.principia{background-color: #6ab0de;}
/* Algorithm: gray */
#content .alg {background-color: #ddd;}
#content p.admonition-title.alg {background-color: #333;}
  1. Use it in Org mode:
#+BEGIN_theorem My theorem :label test
As said in theorem [[thm:test]]
  • Didn't work for me, could you please clarify? I get error 'Unable to resolve link "thm:test"' while exporting to html. Here's what I did: (i) added macros and links defined in steps 1 and 2 to my emacs-config.org file, (ii) created style.css file and added the style from step 4, (iii) skipped step 3, (iv) added this line at the top of my org file: "#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="style.css" />", and (v) in the body of my org file, I added the content from step 5. If I omit the last line from step 5, I get a html with theorem style but without caption and number.
    – vpk
    May 5, 2022 at 6:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.