3

Footer is not displayed (actually, it is incorrectly displayed on top of the page), when fullPage is set to false in PrimeFaces template.

<p:layout fullPage="false">
    <p:layoutUnit position="north" size="135">
        <!--Put north content here, if any-->
    </p:layoutUnit>

    <p:layoutUnit position="west" size="225" header="Menu Item" collapsible="true">
        <!--Put west content here, if any-->
    </p:layoutUnit>

    <p:layoutUnit position="center" size="2500" maxSize="2500">
        <!--Put center content here, if any-->
    </p:layoutUnit>

    <p:layoutUnit position="east" size="175">
        <!--Put east content here, if any-->
    </p:layoutUnit>

    <p:layoutUnit position="south" size="90">
        <!--Put south/footer content here, if any-->
    </p:layoutUnit>
</p:layout>

How to display footer, when fullpage is set to false?


EDIT :

if <p:layout> is given a height like as follows,

<p:layout fullPage="false" style="height: 2000px;">

then the footer is displayed at the bottom of the page based on the value of the height CSS attribute but it is still not a sticky footer - it does not adjust according to the page contents.

So, Is there a way to make it sticky?


Update :

The behaviour remains stationary on PrimeFaces 5.3 final (community release), when fullPage is set to false as said previously throughout the question.

Tiny
  • 27,221
  • 105
  • 339
  • 599
  • seems to be a bug in primefaces, the footer is actually there but you may see lines going 'up above' the header. – VeenarM Mar 23 '14 at 07:29
  • Indeed, that's clearly a bug. That part is fixable by giving `html,body,.ui-layout-container` a height of 100%, but then there's some JavaScript going on which automatically re-adjusts the height based on that, causing it to behave almost exactly like `fullPage="true"`. If you want to keep using ``, the fix/workaround is going to be nasty. It would be better to report the bug to PF guys and re-check again once they fixed it. In the meanwhile, are you open to JS/jQuery based workarounds? – BalusC Apr 27 '14 at 19:54
  • The bug was already reported by VeenarM as linked in his answer but it has not yet had an initial review. Therefore, it should be safe to assume that it is not going to be fixed at least until PrimeFaces 5.0 release. Anyway, I'm looking for a workaround, if any, no matter, if it is nasty/clumsy/ugly/irritating. – Tiny Apr 27 '14 at 20:18
  • I had also the same [post](http://forum.primefaces.org/viewtopic.php?f=3&t=37007#p117775) on the PrimeFaces Community Forum but did not find a workaround. – Tiny Apr 27 '14 at 20:24
  • I made some pure CSS attempts, full of `!important` mess to override inline/JS-generated styles and an additional JS oneliner or two to change the HTML DOM structure. I came close, but the whole thing is very brittle and breaks as soon when I for example resize the window, or when I collapse/expand the "west" unit, all due to the `layout.js`. This is plain awful. I'm very tempted to say to just drop the whole PF layout thing and compose the layout yourself the "plain HTML" way using some divs (or p:panels) and a few lines of CSS. But then it's not collapsible/resizable/closable. – BalusC Apr 29 '14 at 16:54
  • I can post a "best bet" answer, but then the "west" unit shouldn't be collapsible. – BalusC Apr 29 '14 at 17:01
  • I don't need the west (including north and east) unit collapsible and/or closable, no worry. – Tiny Apr 29 '14 at 17:09

4 Answers4

7

To easily visualize what you ultimately need (and to confirm your needs for myself), here's in SSCCE flavor a pure HTML/CSS solution of what you're (apparently) asking for. The sticky footer solution is largely based on Ryan Fait's approach (a min-height:100% and a negative margin on the container element which covers everything but footer), it only doesn't support IE6/7 anymore (due to :after pseudoselector), hereby simplifying the HTML markup (no non-semantic clutter like <div id="pushfooter"> needed). Note: background colors are purely for visualization.

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Stack Overflow Question 22584920</title>
        <style>
            html, body {
                height: 100%;
                min-width: 800px;
                margin: 0;
            }
            #container {
                min-height: 100%;
                margin: 0 auto -90px; /* Negative of #footer.height */
            }
            #header {
                height: 135px;
                background: pink;
            }
            #menu {
                float: left;
                width: 225px;
                background: khaki;
            }
            #content {
                margin-left: 225px; /* Same as #menu.width */
                margin-right: 175px; /* Same as #side.width */
                background: lemonchiffon;
                padding: 1px 1em; /* Fixes collapsing margin of p's on div, feel free to remove it */
            }
            #side {
                float: right;
                width: 175px;
                background: palegreen;
            }
            #footer, #container:after {
                height: 90px;
            }
            #footer {
                background: orange;
            }
            .clearfix:after {
                display: block;
                content: " ";
                clear: both;
            }
        </style>
    </head>
    <body>
        <div id="container" class="clearfix">
            <div id="header">Header</div>
            <div id="menu">Menu</div>
            <div id="side">Side</div>
            <div id="content">
                <p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p>
            </div>
        </div>
        <div id="footer">Footer</div>
    </body>
</html>

Note: due to the way how floats work, the <div id="side"> (the "east unit") has in the HTML markup to be placed before all non-floating elements at the same "row", such as the <div id="content"> (the "center unit"), otherwise it will be aligned relative to the bottom of the last non-floating element.

Now, in order to achieve exactly the same with the <p:layout> thing, which basically renders almost the same HTML structure, only with the footer still inside the container and the east unit after the center unit, you need to make sure that no one of the layout units are collapsible/closable/resizable (those attributes all already default to false and can thus be omitted for brevity) and that you apply the PrimeFaces-builtin clearfix style class ui-helper-clearfix on the container unit to clear the floats (otherwise the menu, content and side would overlap the footer when the screen is shrunk vertically):

<p:layout styleClass="ui-helper-clearfix">
    <p:layoutUnit position="north" size="135">
        <p>Header</p>
    </p:layoutUnit>
    <p:layoutUnit position="west" size="225" header="Menu Item">
        <p>Menu</p>
    </p:layoutUnit>
    <p:layoutUnit position="center">
        <p>Content</p>
        <p>Content</p>
        <p>Content</p>
        <p>Content</p>
        <p>Content</p>
    </p:layoutUnit>
    <p:layoutUnit position="east" size="175">
        <p>Side</p>
    </p:layoutUnit>
    <p:layoutUnit position="south" size="90">
        <p>Footer</p>
    </p:layoutUnit>
</p:layout>

Then you can apply the following CSS in your PrimeFaces-override stylesheet to remove/override all "irrelevant" PrimeFaces-generated CSS properties on those layout units by setting the absolute positioning with fixed offsets/dimensions back to initial/default values (note: the exact purpose of !important is being able to override hardcoded/inline style properties from a true stylesheet on, there's in this particular case simply no other option as long as you don't want to rewrite PrimeFaces components and renderers). Key point is that you should end up with exactly the same HTML/CSS (defaults) as the SSCCE:

html, body {
    height: 100%;
    min-width: 800px;
    margin: 0;
}
.ui-layout-container {
    min-height: 100%;
    height: auto !important;
    margin: 5px;
    margin-bottom: -90px; /* Negative of footer height. */
}
.ui-layout-unit {
    position: static !important;
    top: auto !important;
    bottom: auto !important;
    left: auto !important;
    right: auto !important;
    height: auto !important;
}
.ui-layout-unit-content {
    display: block !important;
    height: auto !important;
}
.ui-layout-west {
    float: left;
    margin: 5px 0 !important;
}
.ui-layout-center {
    margin: 5px 0 !important;
    margin-left: 230px !important; /* Menu width plus margin between panels. */
    margin-right: 180px !important; /* Side width plus margin between panels. */
}
.ui-layout-east {
    float: right;
    margin: 5px 0 !important;
}
.ui-layout-container:after {
    height: 85px; /* Footer height minus margin between panels. */
}
.ui-layout-south {
    margin: 5px !important;
    visibility: visible !important;
}

And finally add the following script in order to move the side (east unit) before the content (center unit), so that the floats go as intented, and to move the footer to end of body, so that it's outside the container element:

$(function() { 
    $(".ui-layout-east").insertBefore(".ui-layout-center");
    $(".ui-layout-south").appendTo("body");
});

Make sure that this script is re-executed when you do an ajax update with @all on the same view for some reason (which is at its own a bad idea though).

With this "solution" (I'd rather call it a hack and just throw it all away and go for a sane and clean HTML/CSS solution, if necessary with <p:panel>s instead of <div>s), it's still somewhat brittle; the auto-included layout.js script auto-adjusts the layout units on every window resize. But so far they don't seem to break anything in all modern browsers I tried (IE>8).

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thank you very much for taking much time. Will give it a try! – Tiny Apr 29 '14 at 20:36
  • I have some components on the west and east units like `` displayed inside `` and a colour list displayed using `` inside ``. They all are messed up, their positions, appearance, height, width... considerably changed. It requires enhanced CSS/JS to display them properly. I lack that much knowledge of HTML/CSS/JS (someone with sufficient knowledge of HTML/CSS/JS can of course do this but certainly not me) I left with some of choices now are, exclude the footer from the template forever, use `fullPage="true"` or use plain vanilla HTML/CSS template ha ha :) – Tiny Apr 30 '14 at 19:15
  • I just quickly tried a `` in center unit, looks okay. – BalusC Apr 30 '14 at 19:29
  • Components on the center unit look fine but components on the west and east units shuffle. – Tiny Apr 30 '14 at 19:42
  • There's no east unit in the question/answer? If you keep it out, the answer should work, otherwise the question and answer has to be altered. – BalusC Apr 30 '14 at 19:53
  • The east unit was added long after this post. Therefore, it is not available in this question. – Tiny Apr 30 '14 at 19:57
  • OK, I will have to look carefully, if I'm doing something wrong somewhere. – Tiny Apr 30 '14 at 19:59
  • You can't use this CSS when you add the east unit. The CSS has to be altered for that. The answer is targeted on the question in its current form, nothing else. – BalusC Apr 30 '14 at 19:59
  • Sorry then, I should have changed the question to reflect that but I myself forgot it. I could not remember there was no east unit in the question. – Tiny Apr 30 '14 at 20:02
  • My application uses the east unit and there is no east unit in this question. Honestly, I could know only after you commented here. Apologize to this big mistake. – Tiny Apr 30 '14 at 20:17
  • Have you in first place checked the SSCCE of the layout? There's already no "east unit" in there. If the SSCCE already doesn't match your wish, the remainder of the answer would be unsuitable as well. In any way, I updated the answer to include the east unit. Please try to work with SSCCE's before applying on the existing codebase. This should give a much better understanding of the problem and solution as they are really minimalistic and don't contain "code noise" (except of background colors) – BalusC May 01 '14 at 06:48
2

This may or may not be a bug in PrimeFaces - you're best off asking there. The layout is actually on your page if you check the source, however its positioning is above the header, likely because it has no idea where it's to be. In a full page it knows its location generated by the page, but otherwise it could be anywhere you want it to be. Try using CSS to move it etc, refer to. and use styleClass etc to attach classes, my hack was just to use !important which you shouldn't really do.

.ui-layout-pane-south {
    top: 200px !important;
}

etc..

Although I am more inclined to think this is a bug as none of the CSS is applied properly to it.

I've created an issue report on PF and hopefully someone can give some more information on the problem.

Tiny
  • 27,221
  • 105
  • 339
  • 599
VeenarM
  • 1,263
  • 1
  • 10
  • 14
  • What CSS can we apply so that the footer positions automatically according to the contents (it should position immediately below the contents no matter how much contents we display/load on the page)? – Tiny Mar 23 '14 at 08:49
  • I don't know, I know enough CSS to get me by, that's someone elses job :) As I mentioned it seems like an oversight and likely you may prefer to use use fullPage="true" for now. I will reponsd back with what ever I get from the IssueTracker on Primefaces website. – VeenarM Mar 23 '14 at 08:52
  • obviously didn't read the whole comment saying ' which you shouldn't really do'... – VeenarM Apr 26 '14 at 00:14
  • The issue status on the tracker is NotMovedToGitHub : "*Marking as NotMovedToGitHub, if you'd like to provide further feedback please create a new issue ticket at GitHub with details to continue discussion over there.*" – Tiny Aug 01 '15 at 21:52
1

Apparently <p:layout> requires an appropriate height, when fullPage is set to false. The height is required to display the footer at appropriate position (it should position at the bottom of the browser window) like,

<p:layout fullPage="false" style="height: 2000px;">

Learnt from PrimeFaces Extensions <pe:layout> which fails to work with the following error in JavaScript alert box on page load,

/ UI Layout Initialization Warning The layout-container "DIV#mainForm:fullPage" has no height. Therefore the layout is 0-height and hence 'invisible'!

if fullPage of <pe:layout> is set to false and height is not defined. For it to work appropriately, it needs an appropriate height like as follows.

<pe:layout id="fullPage" 
           fullPage="false" 
           style="height: 2000px;" 
           stateCookie="true">

It is difficult to tell whether it is deliberate or intentional.


It would be delightful, if someone could expose how to adjust the footer according to the page contents, a sticky footer.

Tiny
  • 27,221
  • 105
  • 339
  • 599
1

To ensure that the layout DIV has a relative height :

1_ Every components between the BODY and the layout must have a relative height, witch should be 100%.

2_ Always use DIV instead of SPAN between the BODY and your layout (no inline elements).

exemple :

<body>
<h:panelGroup layout="block***important***" style="height:100%" >
    <pe:layout widgetVar="pageLayoutWV" fullPage="false" style="height:100%" > 
    </pe:layout>
</h:panelGroup>
</body>

In case, it dosent work add this code to your page, (i fixed a long time ago but its probably has a relationship with your problem) :

function BaseWidgetInit(cpn, cfg) {
    cpn.cfg = cfg;
    cpn.id = cfg.id;
    cpn.jqId = PrimeFaces.escapeClientId(cpn.id),
    cpn.jq = $(cpn.jqId);           
    //remove script tag
    $(cpn.jqId + '_s').remove();
}   
if (PrimeFaces.widget.Layout)
PrimeFaces.widget.Layout = PrimeFaces.widget.Layout.extend({
    init: function(cfg) {
        BaseWidgetInit(this, cfg);        
        this.cfg = cfg;
        this.id = this.cfg.id;
        this.jqId = PrimeFaces.escapeClientId(this.id);
        if(this.cfg.full) {                                                 //full
            this.jq = $('body');
        } else if(this.cfg.parent) {                                        //nested
            this.jq = $(PrimeFaces.escapeClientId(this.cfg.parent));
        } else {                                                            //element
            this.jq = $(this.jqId);
            this.jq.css('height', $(window).height()-10);
        }        
        var _self = this;
        $(this.jq).data("layoutContainer", null);
        $(this.jq).data("layout", null);
        if(this.jq.is(':visible')) {
            this.render();
        } 
        else {
            var hiddenParent = this.jq.parents('.ui-hidden-container:first'),
            hiddenParentWidget = hiddenParent.data('widget');

            if(hiddenParentWidget && hiddenParentWidget.addOnshowHandler) {
                hiddenParentWidget.addOnshowHandler(function() {  
                    return _self.render();
                });
            }
        }
    }
});

i also suggest you, to use the layout of PF Extention library, its more stable, a working template can be found here erp.agitech.net admin/pass

Nassim MOUALEK
  • 4,702
  • 4
  • 25
  • 44
  • 1) is wrong (it should go up to with ``) and 2) isn't required at all (thus it's perfectly fine to have none) yet your answer implies that. That JavaScript snippet would be more helpful if you elaborate in detail what exactly you changed and why, instead of making it a seek&find game. – BalusC Apr 29 '14 at 06:22
  • 1) No its working to me without going until HTML, as i said all components between BODY and Layout, 2) i dont understand you my english is limited – Nassim MOUALEK Apr 29 '14 at 06:26
  • Uh, it's working for you because you used that script. That div/span around the layout is completely unnecessary. With that script you don't need to declare the heights at all. – BalusC Apr 29 '14 at 06:27
  • OK, now i understand u, as i said i modify it a long time ago, and now i am using the PF extension Layout not the default PF layout, but i think that i add this line this.jq.css('height', $(window).height()-10); – Nassim MOUALEK Apr 29 '14 at 06:29
  • The exemple show that no SPAN must be between the BODY and the Layout otherwise the Layout initialization will fail – Nassim MOUALEK Apr 29 '14 at 06:32
  • Of course there should be no inline elements in between block elements in order to achieve a full height. But the OP didn't have any and the div is also not required at all. Yet your answer implies that. You should just have *nothing* between body and layout. In any way, I just tried your script, it'll behave exactly like `fullPage="true"`. This isn't what the OP intented. – BalusC Apr 29 '14 at 06:36
  • We dont know, may be if BalusC respect the both rules (1 and 2) its should work fine – Nassim MOUALEK Apr 29 '14 at 06:41
  • In case it fail, he probably should give a try to the PF extention Layout, (last advice) – Nassim MOUALEK Apr 29 '14 at 06:44
  • The OP want a `fullPage="false"` with a sticky footer. Thus, when the content (center layout unit) is smaller than the screen height, then the footer should stay all at the bottom. But when the content is bigger than the screen height, then the footer should be pushed lower along with the content. The center layout unit should NEVER have a vertical scroll bar (otherwise you end up with exactly the same as `fullPage="true"`). Your answer definitely doesn't achieve that and I start to have the impression that you have genuinely no idea how HTML inline/block/layout elements work (as to 1 and 2). – BalusC Apr 29 '14 at 06:51
  • maybe i didnt understand your need, sorry – Nassim MOUALEK Apr 29 '14 at 06:54
  • To my experiments, PrimeFaces Extensions `` only works (when `fullPage` is set to false), when it is explicitly given a height. Otherwise, it fails with an error in an alert box like - `/ UI Layout Initialization Warning The layout-container "DIV#mainForm:fullPage" has no height. Therefore the layout is 0-height and hence 'invisible'!` I cannot see any concept of sticky footer in PrimeFaces Extensions `` too. Does it have a sticky footer? If yes then, I instantly avoid using PrimeFaces ``. – Tiny Apr 29 '14 at 20:33