How can I set some text as subscript/superscript in FormattedText
in WPF?
8 Answers
You use Typography.Variants:
<TextBlock>
<Run>Normal Text</Run>
<Run Typography.Variants="Superscript">Superscript Text</Run>
<Run Typography.Variants="Subscript">Subscript Text</Run>
</TextBlock>

- 554,122
- 78
- 1,158
- 1,373
-
2There are some known bugs with this, at least as of .Net 4.0: http://social.msdn.microsoft.com/Forums/en/wpf/thread/f375a41b-2c36-4e51-8f6b-7ed828431412. Don't know if it is fixed in .Net 4.5. – skybluecodeflier Mar 20 '12 at 17:35
-
if some one get this bug with Win7 look at this link to fix it support.microsoft.com/kb/2670838 – WiiMaxx Mar 07 '13 at 15:09
-
6It should be noted that the default UI font for Windows (and WPF) supports neither subscripts nor superscripts prior to Windows 8. – Chris Kerekes Apr 05 '13 at 20:02
You can use something like <TextBlock>5x<Run BaselineAlignment="Superscript">4</Run> + 4</TextBlock>
.
However, as far as I know, you will have to reduce the font-size yourself.

- 12,053
- 4
- 49
- 91
-
1Is it normal that after each run a space is added? It works fine otherwise. – David Brunelle Aug 26 '14 at 13:49
-
-
the space is a known common problem https://stackoverflow.com/questions/11090084/how-to-get-rid-of-whitespace-between-runs-in-textblock – Eric Jan 05 '22 at 00:56
It's interesting to note that for some characters (m2, m3, etc) a superscript is not needed, but the unicode character can be used. For example:
<Run Text=" m³" />
This would show m3.

- 1,187
- 10
- 26
-
3See wikipedia for a complete overview: https://en.wikipedia.org/wiki/Unicode_subscripts_and_superscripts – Wouter Apr 20 '20 at 14:53
I used a layout transform, because Typography.Variants
often doesn't work:
<TextBlock Text="MyAmazingProduct"/>
<TextBlock Text="TM">
<TextBlock.LayoutTransform>
<!-- Typography.Variants="Superscript" didn't work -->
<TransformGroup>
<ScaleTransform ScaleX=".75" ScaleY=".75"/>
<TranslateTransform Y="-5"/>
</TransformGroup>
</TextBlock.LayoutTransform>
</TextBlock>
<TextBlock Text="{Binding Path=Version, StringFormat={} v{0}}"/>
The advantage of using a LayoutTransform
is that it is insensitive to the fontsize. If the fontsize is changed afterwards, this superscript works where explicit FontSize setting breaks.

- 5,172
- 2
- 41
- 64
Typography.Variants works only for open type fonts. If you dont like your superscripts/subscripts going outside the height of actual text then you can use something like the following:
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="10" Margin="0,5,0,0">1</TextBlock>
<TextBlock FontSize="30">H</TextBlock>
<TextBlock FontSize="10" Margin="0,20,0,0">2</TextBlock>
</StackPanel>

- 1,497
- 16
- 39
I don't know if you need this to work with FormattedText specifically, or you mean derivations of Inline, but the following will work on Inlines, even if Typography.Variants="Superscript" fails to work.
TextRange selection = new TextRange(document.ContentStart, document.ContentEnd);
selection.ApplyPropertyValue(Inline.BaselineAlignmentProperty, BaselineAlignment.Superscript);
Hope it helps!

- 9,605
- 6
- 67
- 94
-
This fails miserably in my tests, based on RichTextBox and otherwise successful with bold, italic, underline, font family/color/size. I use the same .ApplyPropertyValue() with all of those. I useToggleButton's so I verify the alignment is set and remembered, but without visual effect. – person27 Oct 02 '17 at 19:32
This is the only thing that worked for me. It also gives you more control over the alignment and font size.
<TextBlock Grid.Row="17">
3 x 3<Run FontSize="6pt" BaselineAlignment="TextTop">2</Run>)
</TextBlock>

- 8,149
- 3
- 35
- 31
Setting for superscript works fine with the following code:
<TextBlock Text="(cm" />
<TextBlock ><Span BaselineAlignment="Top" FontSize="8">2</Span></TextBlock>
<TextBlock Text=")" />
Setting the Baseallignment for subscript in the Span tag did not work for me. I tried the following code and it worked fine.
<TextBlock Text="H" />
<TextBlock Text="2" Margin="-2,0,-2,0" TextBlock.LineHeight="3" >
<TextBlock Text="O" />