Setting Telerik’s HTML5 Kendo UI Grid’s Height to 100% when Binding to Remote Data

Update 06/24/2013 – Telerik, Kendo UI Team (Dimo Dimov) has reached out to me (see block quote below), and has taken the time to provide the best practice on how to handle the 100% height for the Kendo UI Web Grid http://jsfiddle.net/dimodi/SDFsz/, please use this approach vs. the approach in the blog post, thanks for visiting…!

I am Dimo Dimov from the Telerik / Kendo UI team. A client recently provided this page as an example of a 100% high Kendo UI Grid. I reviewed the code and the comments and it seems that a lot of people would benefit from some clarifications how percentage heights work.

First of all, please take a look at the following jsFiddle demo, which is similar to the jsFiddle demo above, but is better and simpler in a couple of ways:

http://jsfiddle.net/dimodi/SDFsz/

The example discussed in this blog post is also similar, but has one drawback – it uses hard-coded “magic numbers” in order to workaround the presumably disobeyed web standard requirement regarding percentage heights. Let me explain this requirement in more detail using the new jsFiddle demo as a starting point.

We have the following DOM tree:

First of all, the rule of thumb is that an element with a percentage height should have a parent with explicit height. The rule applies recursively until an element with a pixel height is reached, or until the HTML element is reached, which should have a height as well. This is because percentage heights are always calculated with regard to the set height of the parent element.

Now let’s get back to our example. The Grid should be 100% high and we set such a style. This implies that the parent element () should have an explicit pixel or percentage height. It has none of those, so we apply a 100% height to it. Now we go up and reach the element. It should also have an explicit height, otherwise the and Grid percentage heights will be ignored. So we apply a 100% height to the element as well. Now we have three nested elements that are 100% high and these heights start working. Since 100% high elements should not have vertical borders, margins or paddings, we remove those, as shown in the jsFiddle demo.

With more complex DOM trees the logic is the same – you start with the given element that needs to expand and go up the tree and apply 100% height styles (or any other values) until an element with a pixel height is reached, or until the element is reached. If you have a sequence of nested 100% high elements, removing just one of those heights will cause all the others to stop working. The most common reason for 100% heights to not work is that there is an element with no height, which breaks the sequence of 100% high nested elements.

One thing more to keep in mind is that 100% high elements cannot have siblings, otherwise they will overflow their parent.

This blog post uses the opposite approach compared to the one I describe – the height is calculated from “the outside to the inside”. The only case, in which such an approach makes sense is when the Grid or some of its parent elements have siblings, so 100% heights cannot be applied that easily. Also, this approach can work with parent elements with missing heights, because it relies on the height of the browser window, but I would not recommend this appoach.

Thank you.

I’ve been somewhat wresting with how to set the KendoUI Grid’s height to 100% so that it could fill a user’s screen as much as possible so that it would only show it’s vertical scrollbar only when absolutely needed e.g. when a user’s actual browser real estate is shorter in height than the grid’s content (rows). Those of us that have wired up the Grid binding to remote data e.g. OAuth, JSON, etc.. have been required to explicitly set the Grid’s height.

I’ve visited the Telerik’s forums and googled, unfortunately no working real solution, hence this blog post.

http://www.kendoui.com/forums/ui/grid/dynamic-grid-height.aspx
http://jsfiddle.net/dimodi/4eNu4/33/

If we don’t set the height, the Grid will render as follows:

Note: No height was set for the Grid configuration and it appears as if the Grid has no records when indeed our service is returning records it’s just the Grid’s content div’s height is 0px because we did not explicity set the height, and if we try to set it to a percent 100%, the Grid does not render at all.


    $(document).ready(function () {
        $("#grid").kendoGrid({
            dataSource: {
                type: "json",
                serverPaging: true,
                pageSize: 5,
                transport: { read: { url: "Products/GetAll", dataType: "json"} },
                schema: { data: "Products", total: "TotalCount" }
            },
            pageable: true,
            columns: [
                    { field: "ProductId", title: "ProductId" },
                    { field: "ProductType", title: "ProductType" },
                    { field: "Name", title: "Name" },
                    { field: "Created", title: "Created" }
                ],
            detailTemplate: kendo.template($("#template").html()), detailInit: detailInit,
            dataBound: function () {
                this.expandRow(this.tbody.find("tr.k-master-row").first());
            }
        });
    });

If explicity set the height, the Grid will render as follows:

Note: Line 10, where we are explicitly setting the height, however notice that we have plenty of screen real estate under grid, and if we could get the Grid could take advantage of that empty space we wouldn’t need the scrollbar.


    $(document).ready(function () {
        $("#grid").kendoGrid({
            dataSource: {
                type: "json",
                serverPaging: true,
                pageSize: 5,
                transport: { read: { url: "Products/GetAll", dataType: "json"} },
                schema: { data: "Products", total: "TotalCount" }
            },
            height: 500,
            pageable: true,
            columns: [
                    { field: "ProductId", title: "ProductId" },
                    { field: "ProductType", title: "ProductType" },
                    { field: "Name", title: "Name" },
                    { field: "Created", title: "Created" }
                ],
            detailTemplate: kendo.template($("#template").html()), detailInit: detailInit,
            dataBound: function () {
                this.expandRow(this.tbody.find("tr.k-master-row").first());
            }
        });
    });

So a quick way we can remedy this is to calculate how much vertical space we have and set the maximum height of the Grid ourselves. By taking the Html document height and offsetting it factoring in our layout e.g. header and footer.


    $(document).ready(function () {
        $("#grid").kendoGrid({
            dataSource: {
                type: "json",
                serverPaging: true,
                pageSize: 5,
                transport: { read: { url: "Products/GetAll", dataType: "json"} },
                schema: { data: "Products", total: "TotalCount" }
            },
            height: $(document).height() - 350,
            pageable: true,
            columns: [
                    { field: "ProductId", title: "ProductId" },
                    { field: "ProductType", title: "ProductType" },
                    { field: "Name", title: "Name" },
                    { field: "Created", title: "Created" }
                ],
            detailTemplate: kendo.template($("#template").html()), detailInit: detailInit,
            dataBound: function () {
                this.expandRow(this.tbody.find("tr.k-master-row").first());
            }
        });
    });

Great! Our Grid now renders and takes up the full vertical real estate within the browser on the intial load

Last Problem, now when we resize the browswer, the Grid is NOT automatically resizing itself

No problem, we will add a method for resizing the grid and wire this up to the browser resize event with jQuery.


  $(document).ready(function () {
        $("#grid").kendoGrid({
            dataSource: {
                type: "json",
                serverPaging: true,
                pageSize: 5,
                transport: { read: { url: "Products/GetAll", dataType: "json"} },
                schema: { data: "Products", total: "TotalCount" }
            },
            height: 250,
            pageable: true,
            columns: [
                    { field: "ProductId", title: "ProductId" },
                    { field: "ProductType", title: "ProductType" },
                    { field: "Name", title: "Name" },
                    { field: "Created", title: "Created" }
                ],
            detailTemplate: kendo.template($("#template").html()), detailInit: detailInit,
            dataBound: function () {
                this.expandRow(this.tbody.find("tr.k-master-row").first());
            }
        });
    });
    
    function resizeGrid() {
        var gridElement = $("#grid");
        var dataArea = gridElement.find(".k-grid-content");

        var newGridHeight = $(document).height() - 350;
        var newDataAreaHeight = newGridHeight - 65;

        dataArea.height(newDataAreaHeight);
        gridElement.height(newGridHeight);

        $("#grid").data("kendoGrid").refresh();
    }
    
    $(window).resize(function () {
        resizeGrid();
    });

Now, when grid first loads

Note: Looks great, Grid occupies all the available vertical real estate it can

When user resizes Grid (maximizes browser vertically)

Note: Still Looks great, Grid automatically resizes itself to occupy the new vertical space within the browser after the resize.

Happy Coding…!

Download sample application:

https://skydrive.live.com/redir.aspx?cid=949a1c97c2a17906&resid=949A1C97C2A17906!375&parid=949A1C97C2A17906!361