35

I have a Text widget and not sure why it seems to just have padding at the top and bottom even though I didn't set any in the code. This is from the default Flutter app, I just modified the font size.

  body: Center(
    child: Column(
      children: <Widget>[
        Text(
          '0:00.00',
          style: TextStyle(fontSize: 76),
        ),
      ],
    ),
  ),

This is a screenshot of the highlighted Text widget in Android Studio. There's really nothing else adding any padding so I don't know why it's there.

enter image description here

Sometimes you get this in CSS where there is padding even though none was set but you can remove it simply with padding: 0 but I don't see how to do it here since I can't find a padding option for the Text widget.

EDIT: The amount of padding changes with the size of the font. It seems to always contain a certain amount of padding, like a html H1 tag.

Hasen
  • 11,710
  • 23
  • 77
  • 135
  • I think more code include some kind of container or whole code. – yaho cho Jul 12 '19 at 14:36
  • @yaho cho That's the whole code for the text widget which is the widget that is highlighted in the image from Android Studio. There's nothing else that that could be affecting it. It's just held in a `children: [` with no parameters at all and that is in a `Row` with no parameters either. – Hasen Jul 12 '19 at 15:19
  • have you tried negative padding? – dmarquina Jul 12 '19 at 15:21
  • @dmarquina I haven't tried any kind of padding since I wasn't aware the Text widget has a padding setting. How do you set it then? – Hasen Jul 12 '19 at 15:22
  • I modified my question to the default Flutter app for transparency. You can see the problem exists even there. You can surely re-create the problem yourself in Flutter with the default project. – Hasen Jul 12 '19 at 15:54

7 Answers7

37

The proper way you can get rid of the unwanted padding is by setting the height property in the TextStyle. With this you set the height for each line.

                  Text(
                    "Let's make\nsome pancakes",
                    style: TextStyle(
                      height: 1.2, //SETTING THIS CAN SOLVE YOUR PROBLEM
                      color: Colors.white,
                      fontSize: 20,
                      fontWeight: FontWeight.w300,
                    ),
                    textAlign: TextAlign.center,
                  ),

In fact, we can confirm from the docs that:

For most fonts, setting height to 1.0 is not the same as omitting or setting height to null because the fontSize sets the height of the EM-square, which is different than the font provided metrics for line height.

For more info: https://api.flutter.dev/flutter/painting/TextStyle/height.html

So give it a try. It worked for me.

Iván Yoed
  • 3,878
  • 31
  • 44
14

There are reasons why the Text widget has this "padding". Take in consideration the next example:

Text(
  '123 gyÓ',
  style: TextStyle(
    fontSize: 40.0,
  ),
),

enter image description here

As we can see, using another characters like the letters g and y and an uppercase O with an accent marker, shows us that there's no padding on the Text widget really.

Fonts have ascenders and descenders on some characters, and there's also en ascent line for special characters like the accent marker. That's why numbers are centered in the middle. That's not padding on Flutter side, but typography design(?). Maybe you could find a way to sort your issue, by looking for a font without ascenders and descenders.

More info about fonts on Wikipedia

Conclusion: if you want to select the Text widget with the Flutter inspector, and see no space around some characters, that is not possible.

GaboBrandX
  • 2,380
  • 14
  • 25
  • 1
    Yes it does, see the overline decoration above. Also you can try using characters like h, d, etc. Those characters have ascenders as you can see on the Wikipedia link I've provided too. Don't think the downvote is fair. :( – GaboBrandX Jul 12 '19 at 17:27
  • Check the screenshot in my question. Zeroes are the tallest any character can be, but there is still a big space above them. There's no reason to have a gap *above* this level...no character ever goes that high. – Hasen Jul 12 '19 at 17:33
  • 1
    You're right. I'm sorry that's called Ascent Line. You can try it with an accent mark on an upeercase character, like Ó. I'll update my answer anyway. – GaboBrandX Jul 12 '19 at 17:37
  • @Hasen Please check my updated answer. Thanks for pointing out my omission. :) – GaboBrandX Jul 12 '19 at 17:41
  • You're right about the lower padding though, although there really does need to be a way around it. Like for example having a title in CAPITALS would have to have a big gap under it...it's very limiting. Is there no way around it? In React Native we can use anything from negative padding to absolute positioning to solve this...must be a ways in flutter? I'm very new to it so no idea. – Hasen Jul 12 '19 at 17:42
  • Well, you have something similar to absolute positioning. And it could be a solution for your specific case. In Flutter you have the `Stack` widget and inside you can use `Positioned` to place the text in an "absolute position". About this question in particular, there's no padding to remove from the Text widget. But you could make another question explaining what you want to achieve so we can help with that. – GaboBrandX Jul 12 '19 at 17:47
  • Oh that sounds interesting. Why don't you modify your answer to explain this then since that would answer my question? – Hasen Jul 12 '19 at 17:51
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/196390/discussion-between-gabobrandx-and-hasen). – GaboBrandX Jul 12 '19 at 17:52
  • But actually... there IS normally a bit of padding even above the ´ sign on the capital O. :) That's the line spacing. Because not even the upper part of `Ó` is supposed to touch on the lower part of `g` from the line above it... See the image in this documentation page: https://api.flutter.dev/flutter/painting/StrutStyle-class.html But as @Iván pointed out in his answer, the line space can be put to 0. – Karolina Hagegård Jun 14 '22 at 11:32
10

There are 2 potential reasons:

  • The fontFamily - try commenting it out and see if you still have the same problem. If this is the reason and you absolutely must/want to use this specific font, I'm not sure what the fix is, apart from some horrible logic to stack widgets accordingly so that it looks like there's no padding.

  • Layout constraints from the parent Widgets - you only included the code of the Text widget, but if for example it's wrapped in an Expanded widget within a Column, that would also explain the extra height (possibly wrong assumption here because the text wouldn't center itself vertically by default anyway, but then there might be a DefaultTextStyle widget up in the hierarchy somewhere so still possible....)

Edit: It seems like there is some default padding around the text.

I found that you can reduce the top padding by setting a TextStyle with a height lower than 1. The value required seems to depend on the font size and the text itself, as different characters have different heights.

You can also reduce the bottom padding by clipping the Text using a fixed size Container. This will also vary based on the font size and the text itself. Below is an example of using both of these to reduce the top and bottom padding to 0 for the text '0:00.00' of font size 72:

ClipRect(
  child: Container(
    height: 55,
    child: Text("0:00.00",
      style: TextStyle(
        fontSize: 72,
        height: 0.80,
      ),
    ),
  ),
),

I know this is a very poor solution, but I don't know of any better one. I tried using a custom StrutStyle on the Text widget, but that didn't help either.

Ovidiu
  • 8,204
  • 34
  • 45
  • I tried commenting out the font family but it didn't change anything. It's just held in a `children: [` with no parameters at all and that is in a `Row` also with no parameters either. Android Studio's inspector is showing that it's the text widget that has that padding as you can see in the screenshot above. – Hasen Jul 12 '19 at 15:24
  • There seem to be a few posts about this kind of 'default padding' in flutter but are not about the Text widget so I couldn't employ their solutions. Leastways it does seem to be a common issue in Flutter. – Hasen Jul 12 '19 at 15:25
  • I modified my question to the default Flutter app for transparency. You can see the problem exists even there. You can surely re-create the problem yourself in Flutter with the default project. – Hasen Jul 12 '19 at 15:54
  • 1
    That seems to only get rid of the padding at the top though. It's quite strange. There's just no way to have large text in CAPITALS without a huge gap underneath it. – Hasen Jul 12 '19 at 17:32
  • adding 'height: 1' to the TextStyle solved it for me. – Rony Tesler Mar 09 '20 at 22:16
9

I think I found a good solution/workaround for removing both top and bottom padding.

The trick is to put your Text in a Container and then change the height of your TextStyle inside the Text, as well as the height of your Container. It's a bit of going back and forth for the perfect measurements but it's worth it imo.

Here's an example from my own code.

enter image description here

Container(
  height: 24,
  child: Text(
    'Auto',
    style: TextStyle(
      height: 0.77,
      fontSize: 32,
      fontWeight: FontWeight.bold,
      color: Colors.white,
    ),
    textAlign: TextAlign.center,
),
Philippe Fanaro
  • 6,148
  • 6
  • 38
  • 76
Coda Veto
  • 896
  • 1
  • 8
  • 13
6

Try playing with line height of the text by setting height in style property. Height of the text is determined based on font size. It will multiply the font size and give you the space that will look like it has some padding. The line height of the text is also linked to the font itself, since every font has it own line height.

child: Text(
        'Some text goes here',
        style: TextStyle(
          fontSize: 25.0,
          height: 1,
       ),
      )
  • This was suggested in one of the other answers but like I commented there, it doesn't remove the padding at the bottom, only at the top. Imagine if you have a `Container` below this text widget, how would you narrow the gap between them? – Hasen Jul 13 '19 at 05:43
  • helps me to get rid of top padding – Vladyslav Ulianytskyi Mar 24 '21 at 13:47
0

I found the solution myself in the end. It can be positioned using Stack and Row widgets. I found Row works better than using Positioned as the text can be centred using the Row widgets.

  body: Stack(
    children: <Widget>[
      Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text(
            '0:00.00',
            style: TextStyle(fontSize: 76),
          ),
        ],
      ),
      Padding(
        padding: EdgeInsets.only(top: 56.0),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Coke',
              style: TextStyle(fontSize: 76),
            ),
          ],
        ),
      ),
    ],
  )

It kind of works like the negative padding in CSS but actually it's the padding that moves the bottom text down rather than up since otherwise they occupy the same space.

enter image description here

Hasen
  • 11,710
  • 23
  • 77
  • 135
  • 7
    With this solution, you didn't remove the extra padding which was asked in your question. You just overlapped two widgets. So this can not be the answer to your main question – Arash Apr 23 '21 at 10:19
  • 1
    This can't be a solution. – Mate Nov 27 '21 at 20:30
  • Don't mark this as the correct answer to the question... Stacks are certainly useful, yeah! But they are not the answer to the qn asked. The correct answer was given by @Iván Yoed. – Karolina Hagegård Jun 14 '22 at 11:25
-1

After googling a while, I've written this. What does it do? It's shifting down the position of the text (not shrinking)

import 'package:vector_math/vector_math_64.dart';
import 'package:flutter/material.dart';

class BaselineText extends StatefulWidget {
  final Widget child;
  BaselineText({this.child});

  @override
  _BaselineTextState createState() => _BaselineTextState();
}

class _BaselineTextState extends State<BaselineText> {
  GlobalKey _key = GlobalKey();

  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {}));
  }

  @override
  Widget build(BuildContext context) {
    final RenderBox renderBox = _key.currentContext?.findRenderObject();
    final height = renderBox?.size?.height ?? 0;
    return Baseline(
      baseline: 0,
      baselineType: TextBaseline.ideographic,
      key: _key,
      child: Transform(
        transform: Matrix4.translation(
          Vector3(0, height, 0),
        ),
        child: widget.child,
      ),
    );
  }
}

How to use:

BaselineText(
   child: Text("something"),
)

DONE!!!

kitta
  • 1,723
  • 3
  • 23
  • 33
  • Does not compile: `A value of type 'RenderObject?' can't be assigned to a variable of type 'RenderBox'. Try changing the type of the variable, or casting the right-hand type to 'RenderBox'.` – Heikkisorsa Dec 27 '21 at 14:10