31

From my decades-long experience of hand-coding HTMLs, I have learnt that <form>, <fieldset> are just block-level elements like <div>. CSS-wise, they behave just the same in terms of positioning and sizing. (Please bear with me, I am ignoring old browsers like IE6 here. ) .... or so I thought....

*Before I go on, I have to state that I use Firefox for development and testing most of the time.

I was on a project with a lot of <form> and <fieldset> all over the place. To simplify my question here, I have something like:

<form>
  <fieldset>
    <div class="gridChild">...</div>
    <div class="gridChild">...</div>
    <div class="gridChild">...</div>
  </fieldset>
</form>

I wanted to have the gridChild divs to be in layout of individual columns. So I had the CSS something like:

fieldset {
  display: grid;
  grid-template-columns: 50px 2fr 6fr 6fr auto ....;
} 

And it worked. It showed the columns perfectly on my screen... It works on Firefox, Android and even Edge. The deadline was overdue. I was in rush and I didn't test it on Chrome. I thought that if Firefox and Edge works fine, then Chrome should work too, right? Or so I thought... Later on, I discovered that that doesn't work on Chrome. The grid layout is completely ignored on Chrome. I spent days just to debug the problem.

After a few sleepless nights, I found out that display:grid doesn't work on <fieldset>. It has to be applied to <div> for Chrome to work. That was a surprise for me, because I have been doing so many CSS positioning, like floating, absolute-positioning, etc in a cross-browser fashion with <form> and <fieldset>, and they have been behaving just like <div> all the time. But why not the Grid layout? Is this a bug for Chrome, or is this behaviour designed to be like that? Because I see that this is not a problem for Firefox, Edge and Android.

An easy fix I can think of is to wrap a <div> inside <fieldset>, like this:

<form>
  <fieldset><div class="gridParent">
    <div class="gridChild">...</div>
    <div class="gridChild">...</div>
    <div class="gridChild">...</div>
  </div></fieldset>
</form>

But as I said before, I have <form> and <fieldset> all over the place. It would be best if I can avoid changing the HTML structures. I am writing here to seek for a CSS solution/hack, so I don't have to go through and rewrite hundreds of HTML lines.

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
user2526586
  • 972
  • 2
  • 12
  • 27
  • 1
    *From my decades-long experience of hand-coding HTMLs, I have learnt that `
    `, `
    ` are just block-level elements like `
    `.* ... Sorry to say, [that is not entirely correct](https://stackoverflow.com/q/35464067/3597276).
    – Michael Benjamin Jun 28 '18 at 11:09
  • 7
    This issue is raised on [gridbugs](https://github.com/rachelandrew/gridbugs#10-some-html-elements-cant-be-grid-containers) and like @Michael_B mentioned it's related to the same flexbox issue. The workaround - as you already worked out - is to add a wrapper element. – Danield Jun 28 '18 at 11:49
  • @Michael_B To me, flexbox and grid layout are similar breed of animal. If one doesn't work, I won't expect the other to work. But thanks for the info anyway. – user2526586 Jun 28 '18 at 15:08
  • @user2526586 AFAICT the workaround you yourself came up on should be the accepted answer. You might consider answering your own question and accepting it. – Benjamin White Dec 28 '19 at 19:10
  • same for
    i wonder if it's fixed too
    – Barbz_YHOOL Mar 12 '21 at 01:49
  • Just lost 2 days trying out to figure why my layout was completely broken in a plug in system. Turns out they're using QT which uses chrome expect that it's chrome 86 and we're at +100 so lagging a bit behind. This really killed me – maxime1992 Jul 05 '22 at 13:30

2 Answers2

7

Another workaround for this issue is to use the form as the grid object and use display: contents on the fieldset. This doesn't break semantic markup, though if there are multiple elements within the form they will all be included in the grid.

.some-form {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
}

.some-form__fields {
  display: contents;
}
<form class="some-form">
  <fieldset class="some-form__fields">

    <label>
      First Name
      <input type="text"/>
    </label>
    <label>
      Last Name
      <input type="text"/>
    </label>
    <label>
      Favourite snack
      <input type="text"/>
    </label>
    
    <label>
      Favourite color
      <input type="text"/>
    </label>

  </fieldset>
</form>
2matto
  • 87
  • 1
  • 2
  • 1
    When I run this snippet in FF I get expected result (https://imgur.com/a/oFJc4jO) but when I run in Chrome, I get the original bug (https://imgur.com/a/bUDN7ag). – Benjamin White Dec 28 '19 at 18:49
  • @BenjaminWhite Both of those screenshots show the expected behaviour (each label taking a grid cell in a 3 column grid). It just happens that in the FireFox screen shot the label text wraps the input onto the next line. The label text appearing above the input isn't what this snippet is intended to show though. – 2matto Dec 29 '19 at 19:50
2

Yeah this is a bug in Blink. fieldset has special cases rendering wise. https://bugs.chromium.org/p/chromium/issues/detail?id=262679

svandragt
  • 1,672
  • 20
  • 38
  • 1
    Was merged into a different bug and was fixed August 2020: https://bugs.chromium.org/p/chromium/issues/detail?id=375693#c90 – ADJenks Mar 04 '21 at 22:45
  • 1
    Is it safe to use in production, how likely is it that people are using outdated chrome browsers? (I can't figure out how to stop chrome updating) – run_the_race Aug 17 '21 at 12:38