Not really a WordPress question, just a CSS question.
I am working with Twitter Bootstrap for the first time. I have been asked to implement a design that will adjust itself to both large screen desktop browsing, but also scale down for browsers on cell phones. I looked at the site http://builtwithbootstrap.com/ to get some ideas. I've success with some of the design given to me, but I've also stumbled on some issues, in particular the footer. Please look at the footer of this site, as an example:
[[LINK href="http://openlastminute.it/"]]http://openlastminute.it/[[/LINK]]
The footer remains at the bottom of the page. But everything above it is a float, and most of the content of the page is fetched via Ajax. And there is no "clear" set on the div "footer". So why does the footer remain at the bottom of the page? Why doesn't it float upwards? I am trying to implement a footer in a similar design, but my footer floats up to the top of the page, which is driving me crazy.
Dbranes answers:
Hi, this could be the reason:
.container::after {
clear: both;
display: table;
}
where the html is like:
<html>
...
<div class="container myapp" id="contentbody">...</div>
<footer>
<div class="container">...</div>
</footer>
...
</html>
::after is a css3 pseudo class, see more about it for example here:
http://www.w3.org/TR/selectors/#selectors
<blockquote>The ::before and ::after pseudo-elements can be used to describe generated content before or after an element's content. They are explained in CSS 2.1 [CSS21].</blockquote>
[[LINK href="http://www.w3.org/TR/css3-selectors/#gen-content"]]source [[/LINK]]
Lawrence Krubner comments:
Even when I apply "clear:both;" to the footer, it still slides up the page, covering the material beneath it. And I've added your styles, but I'm still have the same problem.
Dbranes comments:
ok, do you have this site live or is it local?
Lawrence Krubner comments:
This is not something that will ever go on the web. It is being embedded into a physical device. But it using HTML and CSS as the presentation layer.
Lawrence Krubner comments:
If I go to openlastminute in FireFox, and open it in FireBug, and delete all of this:
.container:after {
clear: both;
}
That does not break the design, therefore I suspect that is not important.
Christianto made the point that some Javascript is resizing some of the page elements, which might explain everything I'm seeing, though I can not figure out how the Javascript is triggered, or even where it lives.
Dbranes comments:
Christianto is right about the masonry calculations, the code seems to be minified here:
http://openlastminute.it/assets/application-0be3001f7a2b37860a676d77ae4d9bb6.js
Dbranes comments:
if you use the Chrome "pretty print" on this file, you can see this calculation function:
function t() {
w = e("#contentbody").width(), spacer = 17, border = 0, w >= 1170 ? col = 4 : w == 940 ? col = 3 : w == 724 ? col = 2 : col = 1, glutter = col - 1, item_width = (w - glutter * spacer) / col, li_width = item_width - border * 2, e("#itemlist li.item").width(li_width), e("#itemlist li.item").css("margin-bottom", spacer);
var t = e("#masonry");
t.masonry({itemSelector: ".item",columnWidth: item_width,gutterWidth: spacer})
}
Lawrence Krubner comments:
Huh. Okay, I did not know about "pretty print" in Chrome. I did try to look at the scripts in FireBug, but Firebug only showed me the minified version, from which I could not get any info. I'll try "pretty print".
Christianto answers:
Lawrence,
do you mean by float element is all <li> with class="item masonry-brick" that has absolute position?
sorry if I am misunderstanding, on jsquestions I should explain more clearly..
if you mean by float is absolute positioned element, the reason footer can be at the bottom while all above element is absolute positioned because by using [[LINK href="http://masonry.desandro.com/"]]jQuery masonry[[/LINK]], all element will be positioned and calculate its total height, and set the height to the parent element (id="masonry").
the parent element is set position to relative, so it work as container.
so even if all child element are absolute positioned, if the height is correct, the footer will stay at the bottom.
so for example, if contain only 3 element, it will calculate and set the height to 150px
<ul id="masonry" style="position: relative; height: 150px;" class="masonry">
<li class="item masonry-brick" style="height: 125px; width: 302px; margin-bottom: 17px; position: absolute; top: 0px; left: 0px; z-index: 1000;"></li>
<li class="item masonry-brick" style="width: 302px; margin-bottom: 17px; position: absolute; top: 0px; left: 319px; z-index: auto;"></li>
<li class="item masonry-brick" style="width: 302px; margin-bottom: 17px; position: absolute; top: 0px; left: 638px; z-index: auto;"></li>
</ul>
but if there are 5 element, it will calculate and set the height to 550px
<ul id="masonry" style="position: relative; height: 550px;" class="masonry">
<li class="item masonry-brick" style="height: 125px; width: 302px; margin-bottom: 17px; position: absolute; top: 0px; left: 0px; z-index: 1000;"></li>
<li class="item masonry-brick" style="width: 302px; margin-bottom: 17px; position: absolute; top: 0px; left: 319px; z-index: auto;"></li>
<li class="item masonry-brick" style="width: 302px; margin-bottom: 17px; position: absolute; top: 0px; left: 638px; z-index: auto;"></li>
<li class="item masonry-brick" style="width: 302px; margin-bottom: 17px; position: absolute; top: 142px; left: 0px; z-index: auto;"></li>
<li class="item masonry-brick" style="width: 302px; margin-bottom: 17px; position: absolute; top: 643px; left: 319px; z-index: auto;"></li>
</ul>
you can check by firebug/web inspector when the item is fetched and added, the height of <div id="masonry"> will increase.
on the site, by using infinite scroll, masonry will fire each time element added, so it will re-layout elements and set the height automatically.
$container.infinitescroll({
navSelector : '#page-nav', // selector for the paged navigation
nextSelector : '#page-nav a', // selector for the NEXT link (to page 2)
itemSelector : '.box', // selector for all items you'll retrieve
loading: {
finishedMsg: 'No more pages to load.',
img: 'http://i.imgur.com/6RMhx.gif'
}
},
// trigger Masonry as a callback
function( newElements ) {
// hide new items while they are loading
var $newElems = $( newElements ).css({ opacity: 0 });
// ensure that images load before adding to masonry layout
$newElems.imagesLoaded(function(){
// show elems now they're ready
$newElems.animate({ opacity: 1 });
// Masonry run here
$container.masonry( 'appended', $newElems, true );
});
}
);
hope this help.
Lawrence Krubner comments:
So, this is tied into the other problem, with Masonry? Interesting. I'll install that and see how much it helps.
Lawrence Krubner comments:
Why do you think Masonry is in use on the openlastminute site? I looked in the source code and did not see any mention of masonry. I looked it in the included files and still saw nothing.
Christianto comments:
sorry for the late reply, need to sleep..
As Dbranes mentioned, all js function is minified on as file "application-0be3001f7a2b37860a676d77ae4d9bb6.js"
I check this include masonry, infinite scroll, and bootstrap javascript function like carousel, dropdown etc.
Christianto comments:
and sorry for the typo, I hope its clear enough..
Lawrence Krubner comments:
Hmm, okay. I used to do a lot of front end work, but that was years ago. Now I work on the backend only. I suppose I am out-of-touch when it comes to the newest tools. I was unaware of a good way of "seeing into" the minified Javascript and figuring out what was there.
I will install masonry, infinite scroll, and bootstrap javascript function like carousel. I will see if that gets my own design to work.
Other than the one Javascript function that you posted in the other thread, is there any other initialization that I need I need to do? Anything that I need to put inside of:
$(document).ready(function() {
jQuery(window).bind("resize", function () {
onScreenResize();
});
});
Lawrence Krubner comments:
I guess we are talking about this version of infinite scroll? https://github.com/paulirish/infinite-scroll
It does an Ajax call to get more info when I reach the end of a page? Where do I set the URL for that Ajax call?
Christianto comments:
yes Lawrence, that's correct.
Basically there are 2 main function that I could see on the site, that is related to layout and fetch content through ajax,
inifine-scroll and masonry.
there are other script like [[LINK href="https://github.com/desandro/imagesloaded"]]imagesloaded plugin[[/LINK]] inside the callback but its not too necessary if you don't need to preload image before content added to dom.
<blockquote>It does an Ajax call to get more info when I reach the end of a page? Where do I set the URL for that Ajax call?</blockquote>
you can set a url to second page (next pagination) as a source, the option is "nextSelector" on infinite-scroll,
for example on openlastminute.it it use:
<div class="pagination" style="display: none;"><a rel="next" href="/?page=2">2</a></div>
and it will search for ".item" on that page to fetched and added,
we can change it on "itemSelector" option to search for other element to fetched.
this is the option parameter for infinite scroll on the site:
{
navSelector: ".pagination",
nextSelector: '.pagination a[rel="next"]',
itemSelector: ".item",
animate: !1,
loading: {finishedMsg: "Message if no other post found..",
img: "/images/ajax-loader.gif",
msgText: "<em>Caricamento</em>"}
}
and js code on the site similar with this:
<script type="text/javascript">
// jQuery imagesLoaded function
(function(c,q){var m="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";c.fn.imagesLoaded=function(f){function n(){var b=c(j),a=c(h);d&&(h.length?d.reject(e,b,a):d.resolve(e));c.isFunction(f)&&f.call(g,e,b,a)}function p(b){k(b.target,"error"===b.type)}function k(b,a){b.src===m||-1!==c.inArray(b,l)||(l.push(b),a?h.push(b):j.push(b),c.data(b,"imagesLoaded",{isBroken:a,src:b.src}),r&&d.notifyWith(c(b),[a,e,c(j),c(h)]),e.length===l.length&&(setTimeout(n),e.unbind(".imagesLoaded",
p)))}var g=this,d=c.isFunction(c.Deferred)?c.Deferred():0,r=c.isFunction(d.notify),e=g.find("img").add(g.filter("img")),l=[],j=[],h=[];c.isPlainObject(f)&&c.each(f,function(b,a){if("callback"===b)f=a;else if(d)d[b](a)});e.length?e.bind("load.imagesLoaded error.imagesLoaded",p).each(function(b,a){var d=a.src,e=c.data(a,"imagesLoaded");if(e&&e.src===d)k(a,e.isBroken);else if(a.complete&&a.naturalWidth!==q)k(a,0===a.naturalWidth||0===a.naturalHeight);else if(a.readyState||a.complete)a.src=m,a.src=d}):
n();return d?d.promise(g):g}})(jQuery);
function onScreenResize() {
var w = jQuery("#contentbody").width(),
spacer = 17,
border = 0,
w >= 1170 ? col = 4 : w == 940 ? col = 3 : w == 724 ? col = 2 : col = 1,
glutter = col - 1,
item_width = (w - glutter * spacer) / col,
li_width = item_width - border * 2,
jQuery("#itemlist li.item").width(li_width),
jQuery("#itemlist li.item").css("margin-bottom", spacer);
var t = jQuery("#masonry");
t.masonry({
itemSelector: ".item",
columnWidth: item_width,
gutterWidth: spacer
});
}
function init_infinite_scroll(n) {
n.infinitescroll(
{
navSelector: ".pagination",
nextSelector: '.pagination a[rel="next"]',
itemSelector: ".item",
animate: !1,
loading: {finishedMsg: "Message if no other post found..",
img: "/images/ajax-loader.gif",
msgText: "<em>Caricamento</em>"}
},
function(r) {
var s = jQuery(r).css({opacity: 0});
s.imagesLoaded(function() {
s.animate({opacity: 1});
n.masonry("appended", s, !0);
onScreenResize();
})
}
)
}
jQuery(window).bind("resize", function () {
onScreenResize();
});
jQuery(window).load(function() {
onScreenResize(),
init_infinite_scroll(jQuery("#masonry"));
})
</script>
Rowela Alzona answers:
Why do you want to make the footer float upwards?
Try on your html on the footer:
add a class (navbar-fixed-bottom) on the container inside the <footer> tag:
example:
<footer>
<div class="container navbar-fixed-bottom">
.............................
</div>
</footer>
Not sure if I got your problem correctly but Please kindly check if it works.
Lawrence Krubner comments:
Sorry if I was unclear. I do not want the footer to float upwards. I want it to stay at the bottom of the page. My problem is that, in my design, it is slides up to the top of the page. I was unable to figure out how openlastminute managed to keep it at the bottom of the page.
Rowela Alzona comments:
Hello Lawrence,
I am not sure but what I understand with your problem is you want to stick your footer on the bottom of the page
and it will not be scrolled like the content?
Try creating another stylesheet and try to add and play around with :
* {
margin: 0;
}
html, body {
height: 100%;
}
.wrapper {
min-height: 100%;
height: auto !important;
height: 100%;
margin: 0 auto -142px; /* the bottom margin is the negative value of the footer's height */
}
.footer, .push {
height: 142px; /* .push must be the same height as .footer */
}
The scripts above are originally from Ryan Fait.
On your HTML try to refer:
<div class='wrapper'>
body goes here
<div class='push'></div>
<div>
<div class='footer'>Footer!</div>
I hope this will give you an Idea or can help you with your problem.
Rowela Alzona comments:
Referrimg im my script above, try changing the "wrapper" with "container" class.