0

I have tables which requires different styles for large and small displays. I dont want to set the breakpoint for the the different CSS with a media query as different tables will require the breakpoint to be at different widths, depending on the tables content.

Ive decided to use javascript to detect when the table is wider than its containing div, and at that point add a class so that the small display CSS is applied. In my code below ive used the window resize event for demonstrative purposes, on my site I will use the document ready and window size changes events.

This works fine however there will be a flash on the screen for small devices as the table will be too large on window load, at which point the javascript will trigger and the small CSS will 'fix' the layout. Is there a way to avoid this flash and have a mobile first approach?

Im making a mobile website (only for phones and tablets) and 90% of my traffic is smaller devices, so I would like to optimize the experience for them.

<div>
<table style="width:60%" class="reference">
    <tbody>
        <tr>
            <th>Firstname-Heading</th>
            <th>Lastname-Heading</th>
            <th class="mobile-hide">Points-Heading</th>
    </tr>
    <tr>
        <td>Jill</td>
        <td>Smith</td>      
        <td class="mobile-hide">50</td>
    </tr>
    <tr>
        <td>Eve</td>
        <td>Jackson</td>        
        <td>94</td>
    </tr>
    <tr>
        <td>John</td>
        <td>Doe</td>        
        <td>80</td>
    </tr>
    <tr>
        <td>Adam</td>
        <td>Johnson</td>        
        <td>67</td>
    </tr>
</tbody></table>
</div>
td, th {
  white-space: nowrap;
  word-wrap: normal;
}
div {
    width: 50%;
    overflow-x: auto;
}
table.small {
    font-size: 0.5em;
}
table.small .mobile-hide {
    display: none;
}
$(window).resize(function(){

  var tableWidth = $("table").width();
  console.log("tableWidth ", tableWidth);

  var divWidth = $("div").width();
  console.log("divWidth ", divWidth);

  if (tableWidth > divWidth) {
    $("table").addClass("small"); 
  } else {
    $("table").removeClass("small"); 
  }

});

http://jsfiddle.net/vw5CX/12/

Evanss
  • 23,390
  • 94
  • 282
  • 505
  • 1
    Have you considered using an industry standard responsive layout, such as Bootstrap, for your web site? – iCollect.it Ltd Jun 02 '14 at 10:24
  • Im not able to implement a framework at this stage. – Evanss Jun 02 '14 at 10:25
  • Just hide it with css and then show it with javascript after the resize. – Reinstate Monica Cellio Jun 02 '14 at 10:26
  • If I hide the table with CSS then presumably I cant measure it with JS to see if it escapes its containing div? – Evanss Jun 02 '14 at 10:28
  • Try `visibility:hidden` instead then. The element is still invisible, but the browser should be able to render and measure it. – roobeedeedada Jun 02 '14 at 10:41
  • 1
    The issue is that every time you resize you check if the table is too big for the div and if it is you make it smaller, this means that on the next resize the table will not be too big, so therefore it gets bigger (and too big for the next resize) which is causing the flickering. If the table has the small class then try and find out the size it would be if it were large before removing the small class. – Joe Taylor Jun 02 '14 at 10:45
  • Add the the class only if the table does not already have it. The same for removal, just do something if necessary and not already done before. – philipp Jun 02 '14 at 10:56
  • 1
    Bootstrap is NOT industry standard. – Ian Devlin Jun 02 '14 at 11:37

2 Answers2

0

You might want to check this question:
JavaScript/JQuery: $(window).resize how to fire AFTER the resize is completed?

It might not be the main problem ,but I guess the $(window).resize() fires multiple events while you ara resizing the window. To solve this, you might wait for the resizing (dragging) complete.

// Basic Concept is ...
$(window).resize(function () {

    if( ... event not fired ...  ){
       setTimeout(function(){
            // toggle your class
       },500);
    }
    ....
});

DEMO:http://jsfiddle.net/8nww6/3/

And, I guess that the default class for the talbe could be small.

   <table class="small">


Your code could go like this:
function applyLayout() {
  var tableWidth = $("table").width();
  console.log("tableWidth ", tableWidth);

  var divWidth = $("#wrapper").width();
  console.log("divWidth ", divWidth);

  if (tableWidth > divWidth) {
    $("table").addClass("small"); 
  } else {
    $("table").removeClass("small"); 
  }
}
var timer = 0;
var delayToCall = (function () {
    return function (callback, ms) {
        if (timer > 0) {
            clearTimeout (timer);
        }
        timer = setTimeout(callback, ms);
    };
})();
$(window).resize(function(){
    delayToCall(function(){
        applyLayout();
    }, 500);  
});

Hope this helps.

Community
  • 1
  • 1
naota
  • 4,695
  • 1
  • 18
  • 21
0

I agree with Amit's answer to use media queries but I wanted to give a reason why this will be better.

You stated that

90% of my traffic is smaller devices,

So, you need to consider that users on these devices can't resize their browser window. Thus, your code is not going to run anyway!

Make your fiddle window very narrow and click run. You'll see that the small size isn't applied. (You'd have to set it in the load event instead).

You also stated that

I dont want to set the breakpoint for the the different CSS with a media query as different tables will require the breakpoint to be at different widths, depending on the tables content.

But what is your alternative? Your current solution doesn't really make for a better user experience. It uniformly makes the content very small and difficult to read regardless of the actual content contained in the table. Assuming that a visitor has a very narrow viewport like my iPhone 5S, and the table content is very wide, I could still wind up have a scrollbar being applied AND the font-size would be super small. Conversely, if the table content was just one pixel too wide for the viewport, the small font would be applied and the content would just be tiny but not fill the viewport.

If you can't use a responsive framework, that's fine. Roll your own and use Bootstrap or Foundation as an example. Inspect how those frameworks handle tables and responsive UI behaviors and incorporate those concepts by copying elements of their css into your project. In the end, you need to solve the problem for the USER not the developer. Your proposed solution may seem better for you, but it's not better for your site visitors.

jme11
  • 17,134
  • 2
  • 38
  • 48