5

The problem

The question

How should I style a form, so that I get my desired 3 column layout under the following constraints:
  • The layout works, even if the the html files are not static (dynamic number of checkboxes, ...)
  • Decent browser support (bonus points if edgeHTML 15 supports the solution)
  • The fieldsets stay in the DOM, because removing them would have side effects (radio buttons would not be grouped, checkboxes and radios would not be disabled anymore, ...)
  • Prefered: No changes in html files needed
  • Prefered: HTML and CSS only

If this is not possible with a 3 column design, a 2 column design would be a possible alternative.

The basics

So basically I have a form like this:

<form>
  <h2>A title</h2>
  <label>
    Some text input
    <input type="text">
  </label>
  <label>
    Some more text
    <textarea></textarea>
  </label>
  <fieldset>
    <legend>Some options</legend>
    <label>
      <input type="checkbox">
      1
    </label>
    <label>
      <input type="checkbox">
      2
    </label>
    <label>
      <input type="checkbox">
      3
    </label>
  </fieldset>
</form>

and would like to get a layout like this:

    +-----------------+------------------+------------------+
    | A title                                               |
    +-----------------+------------------+------------------+
    | Some text input | (                                 ) |
    +-----------------+------------------+------------------+
    | Some more text  | [                                 ] |
    +-----------------+------------------+------------------+
    | Some options    | [] 1             | [] 3             |
    +                 +------------------+------------------+
    |                 | [] 2             |                  |
    +-----------------+------------------+------------------+

The approaches

So I came up with two main approaches because I don't want to change my HTML files just for styling purposes:

Apply the grid on the form

If I style my form with display: grid; and my labels and fieldsets with display: contents;, I would have one grid for all elements in the grid and can be sure, that no individual grid styles different, but I will encounter a bug in most browsers, which renders the content inaccessible.

&plus;

  • Only 1 grid for all elements

  • Bug which renders the content inaccessible
  • Styling as margins of fieldsets and labels are lost
  • Need to take care of custom elements, because in this project, we have a lot of custom components, that could destroy the layout

So I would have something like

fieldset, 
fieldset legend,
fieldset label,
fieldset input{
  border: none;
  margin: 0;
  padding: 0;
}

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

form > h2 {
  grid-column: 1 / 4;
}

form > label,
form > fieldset {
  display: contents;
}

form > label > input[type="text"],
form > label > textarea {
  grid-column: 2 / 4;
}

form > fieldset label:nth-of-type(odd) {
  grid-column: 2;
}

form > fieldset label:nth-of-type(even) {
  grid-column: 3;
}
<form>
  <h2>A title</h2>
  <label>
    Some text input
    <input type="text">
  </label>
  <label>
    Some more text
    <textarea></textarea>
  </label>
  <fieldset>
    <legend>Some options</legend>
    <label>
      <input type="checkbox">
      1
    </label>
    <label>
      <input type="checkbox">
      2
    </label>
    <label>
      <input type="checkbox">
      3
    </label>
  </fieldset>
</form>

Apply the grid on the labels and fieldsets

On the other side, I tried to apply the grid on the labels and fieldsets directly, so that I don't have to care about elements, that span an entire column, but I encounter a bug in chrome and new edge browsers, that display: grid; doesn't work on fieldsets. As you can see, in the codepen above, I could get my desired layout working, with the mentioned workaround, but I had to change my HTML files.

&plus;

  • no need to care about nested elements
  • Decent support

  • Individual grids, which could potentially behave differently
  • Need to make changes in HTML files, just for styling reasons

So I have something like

fieldset, 
fieldset legend,
fieldset label,
fieldset input{
  border: none;
  margin: 0;
  padding: 0;
}

form > fieldset,
form > label {
  margin-top: 2 * $defaultSpacing;
}

form > fieldset,
form > label {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
}

form > fieldset legend {
  grid-column: 1;
}

form > fieldset label:nth-of-type(odd) {
  grid-column: 2;
}

form > fieldset label:nth-of-type(even) {
  grid-column: 3;
}

form > label input[type="text"],
form > label textarea,
form > label * {
  grid-column: 2 / 4;
}
<form>
  <h2>A title</h2>
  <label>
    Some text input
    <input type="text">
  </label>
  <label>
    Some more text
    <textarea></textarea>
  </label>
  <fieldset>
    <legend>Some options</legend>
    <label>
      <input type="checkbox">
      1
    </label>
    <label>
      <input type="checkbox">
      2
    </label>
    <label>
      <input type="checkbox">
      3
    </label>
  </fieldset>
</form>

Or the workaround:

fieldset, 
fieldset legend,
fieldset label,
fieldset input{
  border: none;
  margin: 0;
  padding: 0;
}

form > fieldset .fieldset,
form > label {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
}

form > fieldset legend {
  grid-column: 1;
}

form > fieldset label:nth-of-type(odd) {
  grid-column: 2;
}

form > fieldset label:nth-of-type(even) {
  grid-column: 3;
}

form > label input[type="text"],
form > label textarea,
form > label * {
  grid-column: 2 / 4;
}
<form>
  <h2>A title</h2>
  <label>
    Some text input
    <input type="text">
  </label>
  <label>
    Some more text
    <textarea></textarea>
  </label>
  <fieldset>
    <div class="fieldset">
      <legend>Some options</legend>
      <label>
        <input type="checkbox">
        1
      </label>
      <label>
        <input type="checkbox">
        2
      </label>
      <label>
        <input type="checkbox">
        3
      </label>
    </div>
  </fieldset>
</form>
m4n0
  • 29,823
  • 27
  • 76
  • 89
  • I don't normally say to have LESS information, but in this case, if there's any way to boil it down to a single issue, I think you might have more success getting an answer. Leave it like this for awhile, but if you don't get any bites, try focusing on a specific aspect. – Dave Aug 20 '20 at 14:14

0 Answers0