3

I am trying to get text to sit flush against the top of a TextBlock with no success, I am always left with a gap of a few pixels above the text.

The larger the font, the larger the gap, so its not really that noticeable on a font size of say, 12, but a size of 50 makes it very obvious

Link to image [https://i.stack.imgur.com/dJFVY.png]

A code example to produce this is:

<TextBlock Background="LightCyan"
           VerticalAlignment="Top"
           FontSize="12"
           Text="The quick brown fox"/>

<TextBlock Background="Aqua"
           VerticalAlignment="Top"
           FontSize="50"
           Text="The quick brown fox"/>

<TextBlock Background="LightGray"
           VerticalAlignment="Top"
           FontSize="80"
           Text="The quick brown fox"/>

I also don't think its the Font itself that has the issue, as photoshop (for example) renders the same font correctly aligned with the top of the text area.

Does anybody have any ideas on what is causing the gap, and how to remove it?

Here are some things I've tried:

  1. Setting the VerticalAlignment to Top

  2. Setting LineStackingStrategy to "BlockLineHeight" and setting the LineHeight value to that of the Font size. (While this seems to help a lot, this will affects all lines of text (if its multilined). I was hoping a solution could be found that only affects the space at the top.)

  3. Rendering text in a custom class. (I would really like to avoid doing this, as I'd have to recreate ALL the functionality of the TextBlock.)

EDIT:

Just in case anyone else out there needs this, with BlueM's and NETscape's help and this very handy link: TextBlock as big as a capital letter (ignoring font ascender/descender) where G. Sofien had a very cool solution, I implemented this using all their ideas:

In my code-behind I already had an object representing my text (it's for a drag-and-drop sort of program). In it's constructor I added this code:

  Typeface typeface = new Typeface(Font_Family, Font_Style, Font_Weight, new FontStretch());
  GlyphTypeface glyphTypeface;

  typeface.TryGetGlyphTypeface( out glyphTypeface );

  double baseline = glyphTypeface.Baseline * Font_Size;
  double capsHeight = glyphTypeface.CapsHeight Font_Size;
  double glyphOffset = -1 * (baseline - capsHeight);

  GlyphOffset = new Thickness(0, glyphOffset, 0, 0);

(Pardon the lack of error checking)

Baseline: the line where the font "sits".

CapsHeight: the height of a capital letter.

The above code will basically find the distance from the top of the textblock to the top of capital glyph and then create a Thickness with that height to offset textblock in the view.

Note: I am making the assumption that capitals are the tallest characters (which is not always true, but good enough for my purposes. You could iterate through all the glyphs in your text and find the tallest one)

In my view, I then bind the margin of the TextBlock to the GlyphOffset property and it appropriately offsets the text! (Thanks NETscape, for that margin trick!)

Community
  • 1
  • 1
Bas
  • 113
  • 8
  • I'm pretty sure there's post processing involved with your photoshop example. In their natural state, all fonts have some level of margins in them. The fact that your spacing is dependent on font size supports this theory – Maverik Apr 23 '14 at 15:20
  • @Bas I edited my answer as I was suprised that a negative margin on the TextBlock was possible. – BlueM Apr 23 '14 at 17:04
  • @BlueM, I was more than a little surprised it was possible too, but worked like a charm! Thanks again for the cunning idea! – Bas Apr 24 '14 at 07:18

1 Answers1

5

This seems to be a property of the font. To prove that I tried to put two different fonts into Excel cells (to be WPF neutral) and see how margins are added.

This is the result:

enter image description here

As you can see, Segoe UI adds a larger top margin than Tahoma of the same font size.

Wikipedia describes this as ascender height:

enter image description here

Microsoft describes the OpenType™ height properties here.

enter image description here

So, yes its a builtin property of that specific font.

Edit: I tried different solutions and setting the margin to negative margin on a TextBlock simply works and preserves the line height as you requested.

<TextBlock 
  Text="This is a test with wrap" 
  TextWrapping="Wrap" 
  FontFamily="SegoeUI" 
  FontSize="70" 
  Margin="0, -12, 0, 0"/>

enter image description here

You could bind the Margin attribute to a calculation which uses the font metrics of the used font to make it work in different sizes.

BlueM
  • 6,523
  • 1
  • 25
  • 30
  • I was just saying the samething in [#WPF](http://chat.stackoverflow.com/rooms/18165/wpf). The fonts come with built-in margins indeed – Maverik Apr 23 '14 at 15:18
  • So, is your answer that its not possible to achieve what they want? Come on now, this is WPF :) – Kcvin Apr 23 '14 at 15:28
  • Just to be complete. This issue not only affects WPF :-) He can possibly tweak it with your approach of using negative margin but that highly depends on the font and fontsize used. – BlueM Apr 23 '14 at 15:31
  • A possible more generic approach is to retrieve the height properties from the current font used and backcalculate the negative margin to use to get rid of it. – BlueM Apr 23 '14 at 15:34
  • Right. But I'm not sure this is an answer. This is more of a Font wiki. As you said the trick is to calculate the margin that needs to be used (like my answer also says). I just think you should add some code or something to make this an actual answer. Telling OP that it depends on font, or to change the font isn't really helpful. They want to keep the fonts margins the way they were designed except for the first lines top margin... – Kcvin Apr 23 '14 at 15:41
  • Thanks, I didn't try putting it into Excel. I've been using photoshop (since I'm exporting text from it.) It definitely keeps the text flush with the top of the text box though. Perhaps as @Maverick suggests photoshop is doing some extra processing? – Bas Apr 23 '14 at 15:52
  • 1
    Thanks guys, your help has been really awesome, esp. BlueM and NETscape! I also managed to find this question: http://stackoverflow.com/questions/9785322/textblock-as-big-as-a-capital-letter-ignoring-font-ascender-descender So with your guys help, and that question's help I've implemented a fairly simple little solution that seems to work for different fonts and different sizes. I'll update the question with the what I landed up doing. Thanks again guys, you really saved my bacon! – Bas Apr 23 '14 at 17:09