4

I try to build a web application that will fit with almost all sizes of devices/browsers. To do so, my actual approach is to define,inside of my body, a div that will take the whole space of body:

#mydiv {
width: 100%;
height: 100%;
}

I calculate, then, width and height of my available space using:

var Width= $("#mydiv").width();
var Height= $("#mydiv").height();  

I do what I want after. I position my elements with jQuery/CSS (percentages, top property, absolute positionnong,...), I draw with Rapahael.js....

I discovered that this approach is not always efficient, especially for browsers that display their addons as HTML. For example in my Chrome, when I install a toolbar addon, this toolbar is rendered in the page code source as HTML elements with their own styles (top=0, fixed postion..). The consequence is that all my work with top position is shifted by the height of the toolbar.

How can I calculate the net height of body? What are alternative approaches to create webpage that adapts with the net browser size (I mean after any DOM injected elements outside of my control like ask.com toolbar... )?

Adib Aroui
  • 4,981
  • 5
  • 42
  • 94
  • 1
    possible duplicate of [Get the browser viewport dimensions with JavaScript](http://stackoverflow.com/questions/1248081/get-the-browser-viewport-dimensions-with-javascript) – Rory McCrossan May 06 '14 at 14:07
  • @RoryMcCrossan, thank you for the link I am reading it. I did my homework but not with the keyword 'viewport'. Thanks again – Adib Aroui May 06 '14 at 14:09

2 Answers2

1

Edit: so I gave this problem a little thought and I figure that if an add-on is going to draw to the DOM, it's most likely going to append itself to body. So, if you structured your document body in this manner:

<body>
  <div id="container">
    ... all your content here
  </div>
</body>

and the add-on inserted itself like this:

<body>
   <div id="toolbar" style="margin:0;padding:5px;position:fixed;top:0px;left:0px;width:100%;height:20px;background-color:#000;color:#fff">toolbar</div>
   <div id="container">
     ... all your content here
   </div>
</body>

You could overcome this by setting #container's position to relative and adding the following script to your page:

var shift_amount = 0; 
var children = document.body.children;
for(var i = 0; i < children.length; i++){ 
    if(children[i].style.position == 'fixed'){ 
        shift_amount += parseFloat(children[i].style.height); 
    }
}

var Height = $(window).height();
var Width =  $(window).width();

if(shift_amount > 0){
    // subtract fixed element height from available height
    Height -= shift_amount;
}

As I'm pretty sure the question @RoryMcCrossan linked answers the question you asked, I will add that the preferred approach to creating responsive websites is to use media queries to adapt your CSS at various widths (mobile, tablet, desktop). Here is an example of media queries in action using Twitter Bootstrap, open that page and resize your browser window.

<style>
/* target only browsers less than or equal to 600px; */
@media (max-width: 600px) {
  .sidebar {
    display: none;
  }
}
</style>

Regarding the issue of having toolbars and other components rendered in the HTML, this is going to be difficult to overcome as you can't know any and every element that will get injected into the DOM outside of your control. If you are targeting a specific use case, please point us to that add-on and there may be a solution to find.

Rob M.
  • 35,491
  • 6
  • 51
  • 50
  • @RoryMcCrossan answer tells you how to calculate the viewport size. (the browser's window). He is asking about the `body` size (its content). – Alvaro May 06 '14 at 14:23
  • One example of a site that adapts well: http://css-tricks.com/ . Try resizing your browser with it open. – Katana314 May 06 '14 at 14:24
  • 1
    @Katana314 he is not asking about how to make a responsive site. Just about how to calculate the body size after the DOM is externally modified. – Alvaro May 06 '14 at 14:25
  • Thank you Rob for your answer.+1. Especially the last paragraph which adress the real issue as I think. I am reading now Alvaro link about mutation observers, what do you think about it? – Adib Aroui May 06 '14 at 14:32
  • Thank you very much Rob for your Edit, and for all the time you gave to resolve the issue.The idea behind is awesome and I am trying to implement it. I will come back here to give the final feedback. thanks again – Adib Aroui May 06 '14 at 21:57
1

I would take a look at the "mutation observers" to detect changes in the DOM structure.

Then you can just get those values again.

MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

var observer = new MutationObserver(function(mutations, observer) {
    // fired when a mutation occurs
    Width= $("#mydiv").width();
    Height= $("#mydiv").height();  
});

// define what element should be observed by the observer
// and what types of mutations trigger the callback
observer.observe(document, {
  subtree: true,
  attributes: true
  //...
});
Community
  • 1
  • 1
Alvaro
  • 40,778
  • 30
  • 164
  • 336
  • The link you provided with is very important, it points to what I need... I will come back here for feedback, thanks again +1 – Adib Aroui May 06 '14 at 14:29
  • Isn't the performance overhead for current mutation observing implementations (`DOMNodeInserted`, `MutationObserver`) pretty high? Looks like DOMNodeInserted performs better (http://jsperf.com/mutationobserver-vs-css-animation-vs-mutation-events-2) – Rob M. May 06 '14 at 14:34
  • @RobM.the performance for `MutationEvents` is bad (`DOMNodeInserted` is a Mutation Event). `MutationObserver` was created as a highly performant replacement for `MutationEvent`. See https://dev.opera.com/articles/mutation-observers-tutorial/ for more details. – bluesmoon Dec 22 '14 at 17:43