1

The main issue that is not treated in similar questions listed below is a FORM object that has a variable part and a non variable footer (submit buttons)

The aim is to display:

  • A header (a table (width:100%) with a logo and a text in second cell): size should be the smallest possible with all content displayed
  • A FORM (containing 2 parts):
    • Fields are in a div that will expand to all space remaining and will scroll if it lack space. (minimum size: 1 text line)
    • Submit / Rest buttons are in a table and should ALWAYS be visible and not resized in anyway. At worst the stick to bottom of browser window.(except if browser window becomes ridiculously small of course)
  • Nothing should go below bottom of browser window (except if user resize to a ridiculous size).

    • Hardcoded height is NOT an option (except the 100% for technical reasons - body or column parent for example). Header and footer height MUST be autocomputed by browser to use minimum space while displaying all content. If user reduce the width of the browser window increasing the header or footer text to wrap on more lines, the height must grow accordingly. Thus percentage or viewport heigh is not an option as it is arbitrary and can't take car of the user zoom, the browser width resize and such.

I've tried the following layout:

<div id="column">
<div id="header>
  <table><tbody>
    <tr><td>LOGO</td><td>Some intro text on a few lines</td></tr>
  </tbody></table>
  <!-- optionnel error line (arbitrary length) if previous form submission failed -->
</div>

<form>
  <div id="variable_scrollable_content">
  <!-- multiple field sets hosting some input (text, select, ...) -->
  </div>

  <div id="footer">
  <table><tbody>
    <tr><td>Save button</td><td>Reset button</td></tr>
  </tbody></table>
  <!-- A few lines of text -->
  </div>
</form>
</div>

After I gave a careful view to similar questions (see below), I was unable to find something that could handle the FORM object that has a variable size scrollable part and a fixed footer.

I also gave a careful look at https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox with no more success.

I tried the flex approach for classes header, variable_scrollable_content and footer with no success. I also tried to put the form object in flex class but that doesn't work.

As I can't separate the FORM submit/reset buttons from the fields they manage, I don't know how to solve this.

  • header should stick to top of browser windows
  • footer (containing form control buttons) should stick to bottom of browser window at worst or stick at the end of the last fields if browser windows is big enough.
  • fields should be in a variable size container that uses all the remaining space between header and footer and has overflow-y:scroll; so it can scroll if it can't display its whole content.

In case the above simplified code is not sufficient, the "real" code can be found here: https://github.com/finley/SystemImager/blob/initrd-from-imageserver-and-dont-package-initrd/webgui/edit_config.php The full css is here: https://github.com/finley/SystemImager/blob/initrd-from-imageserver-and-dont-package-initrd/webgui/css/screen.css

Similar questions

I have checked the following similar questions, and I believe my question is different as the main problem is the FORM object interfering with the layout:

Original question was here: variable height div between header and footer

2 Answers2

0

I've just found the solution. In this situation, the problem was the FORM object that would interfere with flex column children not at the same Dom level tree.

The simple solution was to move the FORM object so it includes the flex column it its whole content.

The above code becomes:

<form>
<div id="column">

  <div id="header>
    <table><tbody>
      <tr><td>LOGO</td><td>Some intro text on a few lines</td></tr>
    </tbody></table>
    <!-- optionnal error line (arbitrary length) if previous form submission failed -->
  </div>

  <div id="variable_scrollable_content">
  <!-- multiple field sets hosting some input (text, select, ...) -->
  </div>

  <div id="footer">
  <table><tbody>
    <tr><td>Save button</td><td>Reset button</td></tr>
  </tbody></table>
  <!-- A few lines of text -->
  </div>
</div>
</form>

But this was not sufficient because setting flex column height to 100% (when body is also set to 100%) won't work. maybe the form object doesn't propagate the height? The solution was to set height of column with vh (viewport height) unit.

So I set it to 100vh. Unfortunately, there are some glitches due to some border size and padding from parent objects and itself. So as a fallback I put it to 96vh, but this is ugly and I'll investigate and will remove the parasite border size padding that makes the body bigger than 100vh.

<body style="height: 100%">
  <form>
  <div style="display: flex; flex-flow: column; height: 100vh;">
    <div id="header" style="flex: 0 0 auto;">foo bar</div>
    <div id="content" style="flex: 1 1 auto; overflow-y: scroll;">Input fields</div>
    <div id="footer" style="flex: 0 0 auto;">Control buttons</div>
  </div>
  </form>
</body>

The above sump is bigger than 100vh in height. There are 2 solution to fix that:

  • Remove any border padding or such from parent object.
  • Set the column to an absolute position (0,0)
  • This looks like a partial answer, but it also includes some related questions. We do not permit that here. Could you edit this answer to ensure it is answer-only, and then create a fresh question to ask about the new things? Thanks. – halfer Oct 20 '19 at 20:29
  • Alternative solution is to move form submit and reset button outside the form and use the id and fortmmethod attributes of the button element. – Olivier LAHAYE Oct 21 '19 at 08:04
0

Alternative solution to scrollable FORM in flex content with fixed footer containing control buttons is to move FORM control buttons outside the form.

The code then looks like:

<body style="height: 100%">
  <div style="display: flex; flex-flow: column; height: 100%;">
    <div id="header" style="flex: 0 0 auto;">foo bar</div>
    <div id="content" style="flex: 1 1 auto; overflow-y: scroll;">
        <form id="foobar">
          Input fields
        </form>
    </div>
    <div id="footer" style="flex: 0 0 auto;">
      <button form="foobar" type="submit" formmethod="POST">Submit</button>
      <button form="foobar" type="reset">Reset</button>
    </div>
  </div>
</body>

The advantage is that it works with height 100% as it takes account of margin borders and padding of parent (while vh is an absolute viewport size).

halfer
  • 19,824
  • 17
  • 99
  • 186