6

I have a button that consists of an <i> and an <span> element (an icon and some text). Now both have different sizes so I'm applying a flexbox to my button that should center my items nicely. In Chrome everything works as I expected but using the page in a current FF results in wrapping my inner content of the button. The icon is displayed via a :before pseudoelement.

JSFiddle

Who is wrong here? Is it FF or is it Chrome (and me). What should I do to get the same result in either browser (icon before text, vertical center, no wrap)?

Fidel90
  • 1,828
  • 6
  • 27
  • 63
  • 1
    This is the same issue as https://stackoverflow.com/questions/27597870/using-display-flex-on-a-button-makes-it-wrap-in-firefox/27627318 -- see my answer over there: http://stackoverflow.com/a/27627318/329541 Basically, if you want a button to be a flex container, your best bet is to add a wrapper-
    inside of the button, and style *that* div as `display:flex`.
    – dholbert Jun 23 '15 at 05:45

3 Answers3

7

Weird. button elements have some special behavior which seems to conflict with flexbox.

Specifically, what happens is that the flex items are blockified, according to the spec:

The display value of a flex item is blockified: if the specified display of an in-flow child of an element generating a flex container is an inline-level value, it computes to its block-level equivalent.

Therefore, the i and the span, which would be inline, become blocks.

However, flex properties do not seem to apply neither to the flex container button nor to the flex items i and span.

So the flex items are displayed according to the block formatting context instead of the flex one, and since they are blocks, they appear at different lines.

One way to fix it is wrapping the contents in a container, and make it the flex container, instead of the button itself.

div {
  display: flex;
  align-items: center;
}
i {
  width: 12px;
  text-align: center;
  font-size: 22px;
}
i:before {
  content: "\2193";
}
span {
  font-size: 16px;
  margin-right: 10px;
}
<button>
  <div>
    <i></i>
    <span>Text</span>
  </div>
</button>

Also consider simplifying the markup.

span {
  display: flex;
  align-items: center;
  font-size: 16px;
  margin-right: 10px;
}
span:before {
  content: "\2193";
  width: 12px;
  text-align: center;
  font-size: 22px;
}
<button>
  <span>Text</span>
</button>
Oriol
  • 274,082
  • 63
  • 437
  • 513
  • Thank you. I thought about wrapping the `i` and the `span` into a `div` as well and it might work fine. Anyway I found a way not to use flexbox for this. I just gave the button a `display: table;` and the children `display: table-cell; vertical-align: middle;` This works fine. FYI: I'm using FontAwesome library for my icons so I have to use the `i` element :) – Fidel90 Jun 23 '15 at 06:46
4

You need to specify display: -moz-box; to works on FF. Check the updated Fiddle.

  • Hi. I'm using Sass with a mixin that should eveluate to `-moz-box` (or `-webkit-flex`, ...) but my FF uses just `flex`. Check out this fiddle that uses both (as my mixin does): https://jsfiddle.net/u5xp3bd8/3/ The problem still exists as FF choses `flex` over `-moz-box`. Btw it works fine when using `-moz-box` explicit. – Fidel90 Jun 22 '15 at 12:25
  • 1
    Change the order to makes `-moz-box` win: `display: flex; display: -moz-box;` – Nanang Mahdaen El-Agung Jun 22 '15 at 12:27
  • Well that works. But I always saw that one should use the standard property as last one after all the fallbacks?! – Fidel90 Jun 22 '15 at 12:36
  • Yes. But FF is different. As long I play with css, FF always beat me down and force me to do trick, trick and trick. :D – Nanang Mahdaen El-Agung Jun 22 '15 at 12:45
  • Crazy FF. But if that's the only way to go, I'll take it... :) Thanks for your help! – Fidel90 Jun 22 '15 at 12:47
  • 1
    `display:-moz-box` here actually has no effect -- all it's doing is suppressing the `display:flex` (and its blockification quirk); it doesn't actually get you a flexbox. The suggested `display:flex;display:-moz-box` ends up behaving (in Firefox) as `display` were simply not set. If you *actually* want the button to be a flexbox, you need to wrap its contents in a wrapper-div and give *that* `display:flex;flex-flow:...;align-items:...;`. As noted above, this is the same issue as https://stackoverflow.com/questions/27597870/using-display-flex-on-a-button-makes-it-wrap-in-firefox/27627318 – dholbert Jun 23 '15 at 05:49
  • @dholbert: Yes you are right. The `display` property just behaves like it's not set. So the solution by Oriol might be better (or just avoid using flexbox as I pointed out in the comments of the newly accepted answer). – Fidel90 Jun 23 '15 at 06:48
0

Applying flex-shrink: 0 Fixed this issue for me

MADJAR
  • 67
  • 10