2

The Problem

I have a form with multiple fieldsets and a legend tag for accessibility reasons. I want the legend tag to be below the input field. Since I am using CSS Grid for the fieldset, the only way to get it working (on firefox) is to give the legend tag an absolute positioning.

In other browsers, such as Chrome and Edge this does not seem to render properly. What am I doing wrong? Why can't I seem to use CSS Grid to position a legend tag?

fieldset {
  display: grid;
  grid-template-columns: minmax(max-content, 12vw) auto;
  grid-template-rows: auto auto;
  
  position: relative;
  padding-bottom: 2em;
}

fieldset legend {
  position: absolute;
  margin: 0;
  padding: 0;
  
  /**
   * Suggested by user Kamel
   * AFAIK legend is styled a block element by default.
   * It definitely is for Firefox
   */
  display: block;
  
  grid-column: 2 / 3;
  grid-row: 2 / 3;
}
<fieldset>
<legend>An accessible description</legend>
<label>Field</label>
<input type="text">
</fieldset>

<fieldset>
<legend>An accessible description</legend>
<label>Field</label>
<input type="text">
</fieldset>

Screenshot in Firefox (this is what I want to achieve)

Screenshot in Chrome

My Research so far

MDN says:

The <legend> element is okay to style, but it can be a bit tricky to control placement of it. By default it is always positioned over the top border of its <fieldset> parent, near the top left corner. To position it somewhere else, for example inside the fieldset somewhere, or near the bottom left corner, you need to rely on positioning.

https://developer.mozilla.org/en-US/docs/Learn/Forms/Styling_web_forms

But it doesn't seem to mention CSS Grid anywhere saying that it wouldn't work. Why shouldn't it? It works with all other elements too.

grandel
  • 73
  • 5

3 Answers3

2

The problem is not with <legend> but with <fieldset> as grid which does not work in chrome.

Refer: Grid layout on <fieldset>... Bug on chrome?

So you need to add a grid wrapper inside the <fieldset>.

.grid-container {
  display: grid;
  grid-template-columns: minmax(max-content, 12vw) auto;
  grid-template-rows: auto auto;
  position: relative;
  padding-bottom: 2em;
}

fieldset legend {
  position: absolute;
  margin: 0;
  padding: 0;
  /**
   * Suggested by user Kamel
   * AFAIK legend is styled a block element by default.
   * It definitely is for Firefox
   */
  /* display: block; */
  grid-column: 2 / 3;
  grid-row: 2 / 3;
}
<fieldset>
  <div class="grid-container">
    <legend>An accessible description</legend>
    <label>Field</label>
    <input type="text">
  </div>
</fieldset>

<fieldset>
  <div class="grid-container">
    <legend>An accessible description</legend>
    <label>Field</label>
    <input type="text">
  </div>
</fieldset>
Sree.Bh
  • 1,751
  • 2
  • 19
  • 25
  • Thank you so much! – grandel Jul 02 '20 at 12:48
  • Happy to help :) – Sree.Bh Jul 02 '20 at 12:49
  • Just in case you are interested, I unfortunately noticed that this breaks accessibility since the fieldset must have a label but doesn't, now that it is nested in the div. T_T – grandel Jul 03 '20 at 07:41
  • 1
    @grandel: What about using label `for` attribute. I made a [jsfiddle](https://jsfiddle.net/srbh_ya16/dvefbgpx/)... – Sree.Bh Jul 03 '20 at 09:54
  • wow, this is great, thanks again for the help! This feels a bit hacky though and I am strict with myself about avoiding duplicate content so I will not implement it simply because I think it's W3 or Browsers job to allow a better design for developers. IMO it simply should be possible to use grid on fieldset and label. – grandel Jul 04 '20 at 11:08
  • Totally agree with you :) – Sree.Bh Jul 04 '20 at 13:52
2

⚠️ As mentioned in comments under @Sree.Bh solution, wrapping everything inside the <fieldset> with a div.grid-container will break A11Y ♿️ since the <label> is not a direct child anymore. This also produces a ❌ W3C error.

✅ My preferred solution is now W3C and A11Y acceptable

Wrapping the <fieldset> with a div.grid-container and then apply CSS display: contents; to the <fieldset> to inherit the grid-columns to all child elements of it like <legend> and so on

-1
  • The Tag use is only for fieldset caption.

  • The legened Display style must be block.

  • If you want to use a text below, must be in a label tag.

  • This is My Code working in both CHROME and FIREFOX

    fieldset { display: grid; grid-template-columns: minmax(max-content, 12vw) auto; grid-template-rows: auto auto;

    position: relative; padding-bottom: 2em; }

    fieldset legend { position: block; margin: 0; padding: 0;

    grid-column: 2 / 3; grid-row: 2 / 3; }

    Field An accessible description

    Field An accessible description
Kamel
  • 47
  • 4
  • Thanks for your suggestion, I've tried adding display: block; but unfortunately, It did not make a change :/ – grandel Jul 02 '20 at 10:09