I already had this problem in a different unanswered question here. I would expect different fonts at the same size to have the same heights, but this doesn't seem to be the case, so I will show my ad-hoc approach to fixing this.
Leaving aside accents, and focusing only on plain characters, different fonts are necessary to display all the different characters simply because some fonts omit entire blocks of characters that are present in other fonts. To make sure that uncommon characters (such as "𝚫") have at least one font for them, install a font such as Symbola, and see the list of fonts in the readme of the unicode-fonts package.
If you install the package
unicode-fonts and a number of good fonts, all characters should be supported, but some will have wrong displayed heights in emacs.
Suppose that Monaco has incorrect heights, but Symbola appears to have correct heights for mathematical symbols (such as SUBSET OF OR EQUAL TO ⊆; use C-x 8 RET or
insert-char to test different characters.). In my case, not using Monaco, Noto Sans Symbols and Apple Symbols was sufficient; one good font for me was DejaVu Sans Mono.
The first thing is that you can forbid
unicode-fonts from using Monaco by adding it to
unicode-fonts-skip-fonts; whatever font it selects next might have the right height. Alternatively, you can tell
unicode-fonts to use a specific font for a Unicode block (such as Mathematical Operators; here is a list of all blocks) by modifying an entry of
The second is that you can easily do this manually for a very precise set of characters by using
set-fontset-font. If Symbola is a good font for mathematical symbols (in this case the range
0x2100..0x23ff), the following should work:
(set-fontset-font t '(#x2100 . #x23ff)
;; this should throw an error if there is no such font
(font-xlfd-name (find-font (font-spec :family "Symbola"))))
Other ranges I needed to modify myself were
Finally, it is not necessary to search for misconfigured characters by hand. Assuming
unicode-fonts is installed, the following function will generate a list of all characters with incorrect heights:
(defun debug-unicode-heights (&optional block-name)
"Find all characters in a given block that have incorrect heights.
BLOCK-NAME can be anything that
`unicode-fonts-debug-insert-block' accepts, such as `'all-math',
or a string naming a Unicode block."
(interactive "sBlock name:")
(unless block-name (setq block-name 'all-math))
(let ((buffer (generate-new-buffer (format "debug-unicode-heights:%s" block-name)))
(setq expected-height (line-pixel-height))
;; (message "Expected height %d" expected-height)
(while (< (point) (point-max))
(if (or (= (line-pixel-height) expected-height)
;; Some characters are invalid, they have no name
;; (their name is just their hex code), and their
;; heights do not matter to us.
(push (char-after (line-beginning-position)) bad-characters)
;; (display-message-or-buffer buffer)
(apply #'string (reverse bad-characters))))
M-: (debug-unicode-heights 'all-math)
M-: (debug-unicode-heights 'all-greek)
would show all bad mathematical symbols. You can then examine which font they are displayed with, and change it.
I have OS X 10.9.5, so my font settings would likely be different from yours. It is not necessary to install
unicode-fonts; it is possible to manually specify your preferred font choices entirely through
set-fontset-font whenever you find that emacs's default choices don't work well.
P.S. There is an alternative: when a font is consistently too large/small, you can add an entry to
face-font-rescale-alist to tell emacs to always multiply that font's size by a factor of, say, 0.95, like so:
(add-to-list 'face-font-rescale-alist (cons (font-spec :family "STIXGeneral") 0.95) t)
When I tried this, it didn't quite work right (my bug report is here), but this is also a possible approach.