Note: For jQuery Users I have created a Ready to use Plugin Scrollable GridView with Fixed Headers jQuery Plugin
I have written articles in past on this topics.
But the issue was that these articles had some HTML and CSS arrangements need to be done which was not a piece of cake for many users. Hence I decided to find out an easy solution to the issue and here’s it.
In this article I will show you how you can easily make your GridView Scrollable with fixed headers using JavaScript. Don’t worry! you don’t need to do any scripting you simply need to use the script as it and it will make freeze your GridView headers and also make your GridView scrollable.
 
HTML Markup
The HTML markup has nothing but a simple ASP.Net GridView with 3 columns.
<form id="form1" runat="server">
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns = "false">
<Columns>
<asp:BoundField DataField = "ContactName" HeaderText = "Contact Name" />
<asp:BoundField DataField = "City" HeaderText = "City" />
<asp:BoundField DataField = "Country" HeaderText = "Country" />
Columns>
asp:GridView>
form>

 
Client Side Script to Freeze Headers
Below is the JavaScript function that will freeze the GridView headers and also make it scrollable. You only need to place the script anywhere on your page or content page where you have the ASP.Net GridView.
<script type = "text/javascript">
    var GridId = "<%=GridView1.ClientID %>";
    var ScrollHeight = 300;
    window.onload = function () {
        var grid = document.getElementById(GridId);
        var gridWidth = grid.offsetWidth;
        var gridHeight = grid.offsetHeight;
        var headerCellWidths = new Array();
        for (var i = 0; i < grid.getElementsByTagName("TH").length; i++) {
            headerCellWidths[i] = grid.getElementsByTagName("TH")[i].offsetWidth;
        }
        grid.parentNode.appendChild(document.createElement("div"));
        var parentDiv = grid.parentNode;
 
        var table = document.createElement("table");
        for (i = 0; i < grid.attributes.length; i++) {
            if (grid.attributes[i].specified && grid.attributes[i].name != "id") {
                table.setAttribute(grid.attributes[i].name, grid.attributes[i].value);
            }
        }
        table.style.cssText = grid.style.cssText;
        table.style.width = gridWidth + "px";
        table.appendChild(document.createElement("tbody"));
        table.getElementsByTagName("tbody")[0].appendChild(grid.getElementsByTagName("TR")[0]);
        var cells = table.getElementsByTagName("TH");
 
        var gridRow = grid.getElementsByTagName("TR")[0];
        for (var i = 0; i < cells.length; i++) {
            var width;
            if (headerCellWidths[i] > gridRow.getElementsByTagName("TD")[i].offsetWidth) {
                width = headerCellWidths[i];
            }
            else {
                width = gridRow.getElementsByTagName("TD")[i].offsetWidth;
            }
            cells[i].style.width = parseInt(width - 3) + "px";
            gridRow.getElementsByTagName("TD")[i].style.width = parseInt(width - 3) + "px";
        }
        parentDiv.removeChild(grid);
 
        var dummyHeader = document.createElement("div");
        dummyHeader.appendChild(table);
        parentDiv.appendChild(dummyHeader);
        var scrollableDiv = document.createElement("div");
        if(parseInt(gridHeight) > ScrollHeight){
             gridWidth = parseInt(gridWidth) + 17;
        }
        scrollableDiv.style.cssText = "overflow:auto;height:" + ScrollHeight + "px;width:" + gridWidth + "px";
        scrollableDiv.appendChild(grid);
        parentDiv.appendChild(scrollableDiv);
    }
script>

Here also you need to take two things into the two parameters.
1. GridId – Client ID of the GridView.
2. ScrollHeight - Height of the DIV with Scrollbars. Here I have specified it to 300 you can set it as per your needs.
That’s all you need to do for make Freeze your GridView headers or make your GridView a scrollable GridView with fixed headers.
 
Demo
Contact Name City Country
Adnaan Khan Mumbai India
Maria Berlin Germany
Ana Trujillo México D.F. Mexico
Antonio Moreno México D.F. Mexico
Thomas Hardy London Sweden
Christina Berglund Luleå Sweden
Hanna Moos Mannheim Germany
Frédérique Citeaux Strasbourg France
Martín Sommer Madrid Spain
Laurence Lebihan Marseille France
Elizabeth Lincoln Tsawassen Canada
Victoria Ashworth London UK
Patricio Simpson Buenos Aires Argentina
Francisco Chang México D.F. Mexico
Yang Wang Bern Switzerland
Pedro Afonso Sao Paulo Brazil
Elizabeth Brown London UK
Sven Ottlieb Aachen Germany
Janine Labrune Nantes France
Ann Devon London UK
Roland Mendel Graz Austria
Aria Cruz Sao Paulo Brazil
Diego Roel Madrid Spain
Martine Rancé Lille France
Maria Larsson Bräcke Sweden
Peter Franken München Germany
Carine Schmitt Nantes France
Paolo Accorti Torino Italy
Lino Rodriguez Lisboa Portugal
Eduardo Saavedra Barcelona Spain
José Pedro Freyre Sevilla Spain
André Fonseca Campinas Brazil
Howard Snyder Eugene USA
Manuel Pereira Caracas Venezuela
Mario Pontes Rio de Janeiro Brazil
Carlos Hernández San Cristóbal Venezuela
Yoshi Latimer Elgin USA
Patricia McKenna Cork Ireland
Helen Bennett Cowes UK
Philip Cramer Brandenburg Germany
Daniel Tonini Versailles France
Annette Roulet Toulouse France
Yoshi Tannamuri Vancouver Canada
John Steel Walla Walla USA
Renate Messner Frankfurt a.M. Germany
Jaime Yorres San Francisco USA
Carlos González Barquisimeto Venezuela
Felipe Izquierdo I. de Margarita Venezuela
Fran Wilson Portland USA
Giovanni Rovelli Bergamo Italy
Catherine Dewey Bruxelles Belgium
Jean Fresnière Montréal Canada
Alexander Feuer Leipzig Germany
Simon Crowther London UK
Yvonne Moncada Buenos Aires Argentina
Rene Phillips Anchorage USA
Henriette Pfalzheim Köln Germany
Marie Bertrand Paris France
Guillermo Fernández México D.F. Mexico
Georg Pipps Salzburg Austria
Isabel de Castro Lisboa Portugal
Bernardo Batista Rio de Janeiro Brazil
Lúcia Carvalho Sao Paulo Brazil
Horst Kloss Cunewalde Germany
Sergio Gutiérrez Buenos Aires Argentina
Paula Wilson Albuquerque USA
Maurizio Moroni Reggio Emilia Italy
Janete Limeira Rio de Janeiro Brazil
Michael Holz Genève Switzerland
Alejandra Camino Madrid Spain
Jonas Bergulfsen Stavern Norway
Jose Pavarotti Boise USA
Hari Kumar London UK
Jytte Petersen Kobenhavn Denmark
Dominique Perrier Paris France
Art Braunschweiger Lander USA
Pascale Cartrain Charleroi Belgium
Liz Nixon Portland USA
Liu Wong Butte USA
Karin Josephs Münster Germany
Miguel Angel Paolino México D.F. Mexico
Anabela Domingues Sao Paulo Brazil
Helvetius Nagy Kirkland USA
Palle Ibsen Århus Denmark
Mary Saveley Lyon France
Paul Henriot Reims France
Rita Müller Stuttgart Germany
Pirkko Koskitalo Oulu Finland
Paula Parente Resende Brazil
Karl Jablonski Seattle USA
Matti Karttunen Helsinki Finland
Zbyszek Piestrzeniewicz Warszawa Poland

Browser Compatibility

The above code has been tested in the following browsers only in versions that support HTML5.
Internet Explorer  FireFox  Chrome  Safari  Opera 

* All browser logos displayed above are property of their respective owners.

 
 

Note: There was bug of comumn header alignments if grid has more than 14 columns. The bug has been fixed and the article along with sample code has been updated.

Downloads
You can download the complete working source code using the download link provided below.
Download Code