How to Add Sticky Headers with ODS HTML

This blog demonstrates how to modify your ODS HTML code to make your column headers “sticky,” or fixed in position. Using sticky headers is most beneficial when you have long tables on your web page and you want the column headers to stay in view while scrolling through the rest of the page. The ability to add sticky headers was added with CSS 2.1, with the cascading style sheet (CSS) position property and its sticky value. You might have seen this capability before CSS 2.1 because it was supported by WebKit, which is a browser engine that Apple developed and is used primarily in the Safari browser (In Safari, you use the position property with the value -webkit-sticky.) The position: sticky style property is supported in the latest versions of the major browsers, except for Internet Explorer. The FROZEN_HEADERS= option can be used with the TableEditor tagset; see the TableEditor tagset method below.

Before you start

Here is a brief explanation about the task that this blog helps you accomplish. Since the position: sticky style property is supported with the HTML tags within tables, it is very easy for you to add the position: sticky style for HTML tables that ODS HTML generates. When this CSS style attribute is added for the headers, the headers are fixed within the viewport, which is the viewable area. The content in the viewport is scrollable, as seen in the example output below.

In the past, JavaScript was the main tool for generating fixed headers that are compatible across browsers and devices. However, the position: sticky property has also made it easier to fix various other elements, such as footers, within the viewport on the web page. This blog demonstrates how to make the tag or header class sticky but enable the rest of the web page to be scrolled. The techniques here work for both desktop and mobile applications. There are multiple ways to add this style. Choose the method that is most convenient for you.

Method 1: Use the HEADTEXT= option

This example uses the position: sticky style property for the header class, which is added to the HEADTEXT= option in the ODS HTML statement. The header class is added along with the position style property between the and tags, which is the header section of the web page. This method is very convenient. However, you are limited to 256 characters and you might want to add other CSS style properties. The position style property is added using the header class name, which is used by ODS HTML to add style attributes to the column headers. As the name suggests, cascading elements cascade and enable elements with like names to be combined. In the following code example, the HEADTEXT= option uses a CSS rule with the header class and the position: sticky property for the header section of the web page.

ods html path="c:\temp" file="sticky.html"
headtext=" .header {position: sticky;top:0} ";

proc print data=sashelp.cars;
run;

ods html close;

Here is what the output looks like:

Method 2: Use the STYLESHEET= option

You can also add the position: sticky property to the header class from an external CSS file, which can be referenced in ODS HTML code by using the STYLESHEET= option with the (URL=) suboption. This method uses a CSS file as a basis for the formatting, unlike the first method above, which had applied the default HTMLBLUE style for the destination.

Another item worth mentioning in this second example is the grouping of the CSS class selectors, which match the style element names used with ODS and the TEMPLATE procedure. For example, the body, systemtitle, header, rowheader, and data class selectors are added and grouped into the font-family style property. This method is also used for several of the other style properties below. The data class adds some additional functionality worth discussing, such as the use of a pseudo style selector, which applies a different background color for even alternating rows. In the example below, the class names and the template element names are the same. You should place the CSS style rules that are shown here in a file that is named sticky.css.

.table tbody tr:nth-child(even) td {
background-color: #e0e0e0;
color: black;
}

.body, .systemtitle, .header, .rowheader, .data {
font-family: arial, sans-serif;
}
.systemtitle, .header, .rowheader {
font-weight: bold
}
.table, .header, .rowheader, .data {
border-spacing: 0;
border-collapse: collapse;
border: 1px solid #606060;
}
.table tbody tr:nth-child(even) td {
background-color: #e0e0e0;
color: black;
}
.header {
background-color: #e0e0e0;
position: -webkit-sticky;
position: sticky;
top:0;
}
.header, .rowheader, .data {
padding: 5px 10px;
}

After you create that CSS file, you can use the ODS HTML statement with the STYLESHEET= option. In that option, the (URL=) suboption uses the sticky.css file as the basis for the formatting. Forgetting to add the (URL=) suboption re-creates a CSS file with the current template style that is being used.

ods html path="c:\temp" file="sticky.html"
stylesheet=(url="sticky.css");
proc print data=sashelp.cars;
run;
ods html close;

Here is what the output looks like:

The pseudo class selector in the CSS file indicated that even alternating rows for all tags would be colored with the background color gray. Also, the position: sticky property in the header class fixed the position of the header within the viewport.

Method 3: Use the TableEditor tagset

A third method uses the TableEditor tagset, which enables sticky headers to be added by using options. Options are also applied to modify the style for the alternating even and odd rows as well as to have sortable headers.

/* Reference the TableEditor tagset from support.sas.com. */
filename tpl url "http://support.sas.com/rnd/base/ods/odsmarkup/tableeditor/tableeditor.tpl";
/* Insert the tagset into the search path for ODS templates. */
ods path(Prepend) work.templat(update);
%include tpl;
ods tagsets.tableeditor file="c:\output\temp.html"
options(sticky_headers="yes"
sort="yes"
banner_color_even="#e0e0e0") style=htmlblue;

proc print data=sashelp.cars;
run;

ods tagsets.tableeditor close;

Here is what the output looks like:

In summary, this article describes how easy it is to add sticky headers to tables that are generated by using the ODS HTML destination. Adding fixed headers to any table allows the output to dynamically preserve the headers in the viewable area while scrolling through the table, allowing a much richer experience. Give it a try and let me know how it goes.

Learn More

Documentation: ODS HTML Statement

Article: Embed scalable graphics using the ODS HTML5 destination

Article: How to view or create ODS output without causing SAS® to stop responding or run slowly

How to Add Sticky Headers with ODS HTML was published on SAS Users.