Portal Tabs
  • 15 Apr 2025
  • 9 minute read
  • Dark
    Light
  • PDF

Portal Tabs

  • Dark
    Light
  • PDF

Article summary

Adding tabs to a portal lets you divide information among interactive sections, which cuts down on scrolling and can improve the user experience.

Steps to creating a portal with tabs

You’ll make a portal with tabs by following these steps:

  1. Create a default view that holds the tab objects and any content that appears on all tabs, then a view for each tab.

  2. Create a method for each of these views.

  3. Create the tab framework in the default view using HTML (we provide the scaffolding).

  4. Add the JavaScript we provide below this HTML to asynchronously load tab content.

After these steps, we show you how to:

Step 1: Creating views

Portals use views to display content. On a portal with tabs, each tab is represented by a view.

There is also a default view, which contains the tab menu items and any content that should appear no matter what tab is selected.

➡️ Find steps for creating and configuring portal views in Creating a Custom Portal → Creating portal views.

Creating the default view

The default view contains code that creates selectable tag objects (which we’ll be adding later), plus any content you’d like to appear regardless of which tab is selected.

The default view is distinct from a Home tab (one that loads first before any selection is made).

Tab view layouts

Most tab views should use a one-column layout, particularly if the default view is a two-column or another partitioned layout. Avoid embedding a multi-column view in another a multi-column view.

Moving existing content into new views

If you’re adding tabs to an existing portal, you can move portal parts from one view to another with the Move button.

With a default view and a view for each tab created, we can make methods for each view.

Step 2: Creating methods

For each view, including the default view, we’ll create a corresponding method. We create a method to associate a tab object (which we create later) with a view.

When that tab is selected, it calls the method we’ve given it, which, with help from some JavaScript we provide later, loads the specified view.

Methods can also pull query results into the view, among other things.

➡️ Find steps for creating portal methods in Creating a Custom Portal → Adding portal methods.

Create a method called Default and configure the following settings:

  • Name: An internal name for the method, like Default.

  • Type: GET

  • Output Type: Default Branding

  • Action: Leave this field blank.

  • View: Select the default tab view.

For each tab view that you created in the previous section, create a corresponding method and configure the following settings:

  • Name: An internal name for the method. It’s often a good idea to give it the same name as the associated view.

  • Type: GET

  • Output Type: AJAX Popup/No Branding

  • Action: Enter a computer-friendly (lowercase letters and underscores only) name with a maximum of 32 characters. This value appear later, in the tab framework code, and also in the URL when the tab is selected.

  • View: Select the associated tab view you created in the previous step.

In this example, the Tab: Home view is associated with a method named Tab: Home and an Action of home.

Step 3: Creating the tab framework on the default view

In this step, we add an HTML scaffold using a subtabs list object that renders as the tabs at the top of the default view page.

Each item has a data-tab HTML attribute; for example, data-tab="home". This attribute values reference the Action of the Home method we created in the previous section.

We then replace the placeholder values with method actions and tab labels.

In the default view:

  1. Select a Static Content block from the palette.

  2. Configure the following settings:

    • Name: Enter an internal name for the block.

    • Status: Active

    • CSS Class Name: Enter a CSS class name for targeting by your institutional branding, if applicable.

  3. Select Source.

  4. Copy the following placeholder HTML and paste it in the source editor:

    <ul class="subtabs">
        <li>
            <a href="#" data-tab="method_action_1">Tab Label 1</a>
        </li>
        <li>
            <a href="#" data-tab="method_action_2">Tab Label 2</a>
        </li>
        <li>
            <a href="#" data-tab="method_action_3">Tab Label 3</a>
        </li>
    </ul>
    • This code creates an HTML unordered list <ul> with the class subtabs. Each list item <li> renders as a tab.

    • In each list item, there is an anchor <a> tag with the attribute data-tab. The value between the quotes references a method action.

    • The tab label is represented by the text inside the anchor tag.

  5. For each list item <li>, replace the placeholder value inside the quotes for data-tab (method_action_1, method_action_2, …) with the action of the method that corresponds with the view you want to appear when that tab is selected.

  6. Replace the placeholder tab label (Tab Label 1, Tab Label 2, …) with the name you want to appear on the tab.

Here’s an example of how your HTML list might look:

<ul class="subtabs">
    <li>
        <a href="#" data-tab="home">Home</a>
    </li>
    <li>
        <a href="#" data-tab="profile">Profile</a>
    </li>
    <li>
        <a href="#" data-tab="directory">Directory</a>
    </li>
</ul>      

Step 4: Adding JavaScript

When a user selects a tab, we don’t want that action to reload the entire page. Instead, we’ll use some JavaScript to load the tab content, render it on the page dynamically, and update the current URL.

Note that this code also contains some HTML: the div element with the ID content_body is a placeholder element which will contain the tab content once the JavaScript runs.

In the default view, in the source editor of the static content block we created in the previous step:

  1. Select Source.

  2. Copy the following code:

    <div id="content_body">
    </div>
    <script type="text/javascript">
    /*<![CDATA[*/
    var loadTab = function (tab, queryString, isBack) {
    if (queryString) {
    var qs = FW.decodeFormValues(queryString);
    delete qs["tab"];
    queryString = FW.encodeFormValues(qs);
    queryString = queryString ? "&" + queryString : "";
    }
    if (!isBack) history.pushState(tab, null, "?tab=" + tab + queryString);
    $("a[data-tab]").removeClass("active");
    $("a[data-tab='" + tab + "']").addClass("active");
    FW.Lazy.Fetch("?cmd=" + tab + queryString, $("#content_body"));
    };
    
    window.addEventListener("popstate", function (e) {
    if (e.state) loadTab(e.state, location.search.substring(1), true);
    else history.back();
    });
    
    $("a[data-tab]").on("click", function () {
    loadTab($(this).data("tab"), location.search.substring(1));
    return false;
    });
    
    var qs = FW.decodeFormValues(location.search.substring(1));
    if (qs["tab"]) loadTab(qs["tab"], location.search.substring(1));
    else {
    var default_tab = $("ul.subtabs").find("li > a").eq(0).data("tab");
    loadTab(default_tab, location.search.substring(1));
    }
    /*]]>*/</script>
  3. Paste the code below the <ul> list configured in the previous section.

  4. Select Save.

Test your portal: you should see the tabs rendering on the default view. If you don’t, double check the formatting of the HTML list you configured in the previous section.

Styling portal tabs with CSS

You can customize the presentation of portal tabs in Edit → Custom CSS Rules.

How Slate renders portal tabs

In the portal view, tabs are added to the source code as list items (<li>) in an unordered list (<ul>).

The <ul> element has a class attribute of subtabs. Each individual list item itself contains an anchor (<a>) element, which displays the name of the tab. Each anchor element also has data-tab attribute values that correspond to that particular tab method's action.

The active class is added to the anchor representing the current tab being viewed. For example, the Home tab by default upon first entering the portal, or the tab that’s currently selected.

The tabs (specifically, <ul> elements with a class of subtabs, and nested or child <li> and <a> elements) are styled by default CSS as part of Slate standard branding.

Targeting portal tabs with CSS rules

Set style for all content in portal tabs object:

#content ul.subtabs li a {height: auto; font-size: 14px; text-align: center;}

Set a margin-top of 0:

.part ul.subtabs {margin: 0 0 1em; width:100%;}

Adjust tab width:

.part ul.subtabs li {width:20%;}

Modify tab colors, padding, margin, and apply rounded corners:

.part ul.subtabs li a {background-color: #f5f5f5; color: #000000; padding: 5px 15px; border-radius: 3px; margin-right: 7px;}

Modify color of the selected (active) tab:

.part ul.subtabs li a.active {color: #fff !important; background-color: #00669e;}

Modify color of a tab upon mouse hover:

.part ul.subtabs li a:hover {background-color: #fafafa !important; color: #00669e !important;}

If a custom CSS rule doesn't appear to have any effect, you could try adding the !important keyword (e.g. { width: 20% !important; }), and/or change the CSS selector so that it becomes more specific to the element you're trying to update (e.g. #content ul.subtabs li a).

To see the changes on a more immediate basis, sometimes you might also need to do a hard refresh on your browser (Chrome PC: Ctrl + R/Chrome Mac: CMD + SHIFT + R).

✨ Tip: Use your browser’s inspect tool (Right click → Inspect) to see how ul.subtabs elements are rendered on the page.

Displaying tabs conditionally

You can configure a tab to appear only if the user meets certain criteria:

  1. Create a query in the portal.

  2. Add an existence subquery export that checks for your criteria.

  3. In the Default method, select Edit Linked Queries and select the query you created.

  4. In the default view, add Liquid markup in the source editor to the <li> tag you want to conditionally display.

  5. Prevent the tab from rendering if the tab URL is entered but the end-user doesn’t meet the criteria.

The following example provides a more detailed walkthrough.

📖 Further reading: Liquid markup

Example: Hide Assignments tab from non-captain alumni interviewers

In an alumni interview portal, you may only want to show an Assignments tab to users with an assigned role of Captain.

We create a new query in the portal. To it, we add an existence subquery export called captain with a filter for records with an alumni role IN Captain.

In the Default method, we associate this query with the default view.

In the default view, we edit the source code and place a Liquid markup if tag around the <li> tags that looks for the existence subquery export’s Value If Exists value:

<ul class="subtabs">
    <li>
        <a data-tab="home" href="#">Home</a>
    </li>
	{% if captain == 'Y' %}
    <li>
        <a data-tab="assignments" href="#">Assignments</a>
    </li>
	{% endif %}
</ul>

Finally, in the Tab: Assignments view, we wrap the everything in the source code with our Liquid markup if tag from earlier. If someone were to attempt to view this tab by editing the URL or using an old bookmark, nothing would render on the page.

📖 Further reading: Slate standard alumni interviewing portal

Alternative methods for conditional tab display

Another approach involves a portal redirect. If your tab view has multiple widgets or it would otherwise be impractical to wrap the entire tab in Liquid markup, a redirect can prevent the tab from ever loading in the first place.

📖 Further reading: Portal redirects

Analytics for tabbed portals

Portals that make use of tabs will not report navigation between tabs to analytics tools without additional configuration.

Activity is reported upon the first visit to a portal, but subsequent navigation between tabs does not count as a fresh page load and will not trigger analytics scripts placed in website branding.

One potential workaround involves placing tracking codes within the views for each tab. Tracking codes embedded within individual tabs or pages should be reported as unique visits to analytics scripts.

For example, adding a static content block to a portal’s Visit tab and embedding a tracking code within the source code may enable you to see the number of visits specific to this tab. However, different tracking codes may behave differently, so the process should be tested thoroughly.

It may not be possible in every case to return analytics for individual tab views.

📖 Further reading: External analytics scripts


Was this article helpful?