Tabs
Use tabs when users should switch between related panels without leaving the page.
Live demo
Tabs organize content on one page so people can move between related groups without leaving the screen. They work well when each group is enough on its own and people do not need to scan everything at once. Choose tabs when the mental model is “different slices of the same story,” not a long scroll of unrelated blocks.
Behaviour
The active tab shows its content; other panels stay out of the way until someone selects them. People should always be able to tell which tab is current through clear selection styling (for example emphasis and a clear boundary between the tab row and the content below).
On small screens, tab patterns often stack or use a compact pattern so labels stay readable and touch targets stay usable. Plan for short labels because horizontal space runs out quickly.
Keyboard: People typically move between tab headers with arrow keys, then use the Tab key to move into the active panel so they can read and use the content without stepping through every tab first. Design and content should not force people to hunt through every tab to find the main message.
Anatomy
- Tab list: one control per section, in a row on wide layouts.
- Selected tab: shows which section is active (for example stronger text and an underline or bar).
- Unselected tabs: visible but visually quieter than the selected tab.
- Divider: a light separation between the tab row and the content area.
- Panel: the body for the selected tab.

Replace with a Concordia screenshot of the tab strip and mobile behaviour.
Content guidelines
Labels should be short, plain language, and specific to what is inside the panel. Split content into categories that belong together and do not overlap.
On a university site, strong labels often name parallel audiences or facets (for example Undergraduate and Graduate for requirements, Fall and Winter for term-specific dates, or English and French when content truly splits by language). Weak labels hide the grouping (for example Section 1 and Section 2 only describe order, not what is inside). If a label is long, shorten the tab text and move detail into the panel, not into the tab strip.
Information hierarchy
Put anything that applies to all tabs above the tab row: the page or module title, a short intro, and any context everyone needs. If shared copy sits only under the first tab, it reads as if it belongs to that tab alone.
Example: For Student wellness, place the heading and one line of context above tabs such as Counselling, Health services, and Accessibility. Do not tuck the shared intro only under Counselling.
Views in the same context
Use tabs to switch views of one topic on the same page (for example Overview, Courses, and Faculty for one program, or Fees, Deadlines, and Forms for one task).
Do not use tabs to jump to unrelated destinations or to mix primary navigation with content slices. Actions such as Apply, Give, or Register belong in navigation, buttons, or calls to action, not as a peer tab beside Overview and Courses.
Order tabs by importance or how often people need them. Put Overview or the most-used slice first so the main entry point is easy to see. Do not push the primary About or Overview content to the far end of the row.
Grouping
Use tabs when groups are distinct and independent: people can work with one group at a time (for example Worked on, Assigned to me, Starred).
Do not use tabs when people must compare or use two panels at the same time (for example filters and results in one table, or two columns of data that belong together). In those cases, use a layout that keeps both in view.
Do not use tabs for a long list of similar items (for example every unit or department name). Prefer a shorter set of groups, a list, or another pattern.
Best practices
Do
- Use tabs for a small set of groups, or when people return to those groups often.
- Keep labels short; they need to work when space is tight.
- Test the full experience on mobile so you know how the tab row and panels behave when labels wrap or stack.
Don't
- Use tabs for a long strip of options that people rarely use.
- Rely on tabs when horizontal space is so tight that labels truncate or feel cramped.
- Nest tabs inside tabs; split the page or simplify the structure instead.
When to use
- Related chunks of content where one chunk at a time is enough (for example guidelines or optional detail grouped by theme).
- Parallel categories with clear labels (for example level of study, term, or language).
When not to use
- Linear multi-step journeys that live on separate pages (use step or page patterns suited to tasks).
- In-page links to sections on the same page when nothing is hidden (a lighter pattern may be enough).
- Content people must see together; use columns, stacked sections, or a single scroll instead.
Related
- Tabs CDS for the design pattern and Figma alignment.
CRXDE Lite query
Use this query in CRXDE Lite to find instances of this component.
/jcr:root/content//*[@sling:resourceType = 'concordia/components/tabs/tabs.jsp']
Technical behaviour
Authors define tab headers as a multifield; each entry is label|anchor (labelwithanchor widget). The anchor segment becomes the panel id (if omitted, tab-{index}). If an anchor starts with a digit, the implementation prefixes tab- so the id stays valid.
The JSP includes clientlib apps.concordia.tabs. It renders:
navwithrole="tablist"and buttons (nav-link) wired todata-bs-toggle="tab"anddata-bs-target="#anchor"when not in edit mode.tab-contentwithtab-panepanels; each panel contains a card header with a collapse trigger (accordion-style on small screens) and a card body with the parsys.
In edit mode, data-bs-toggle is suppressed on buttons, tabs show edit-mode, and a “Tab: {label}” heading helps authors see boundaries.
If tabs is null, nothing publishes; in edit mode a placeholder and “Tabs” heading appear.
Anatomy (implementation)
- Outer:
div.responsive-tabsplus optionaladditionalClass. - Tab bar:
div.nav.nav-tabs.nav-fill.nav-justifiedwithrole="tablist", uniqueidper instance. - Panels:
div.tab-pane.card.fadewithrole="tabpanel",aria-labelledbypointing at the matching button id,tabindex="0". - Responsive block: Inner collapse (
data-bs-parentper tab card) wrapping the parsys.
Authoring fields
| Field | Purpose |
|---|---|
| Tab header | Multifield: each row is label and optional id after ` |
| CSS class | Optional additionalClass on responsive-tabs. |
Instances in the codebase
| Location | Notes |
|---|---|
apps/concordia/components/tabs/tabs.jsp |
Implementation (resource type concordia/components/tabs, not tabs-cds). |
| Item | Location |
|---|---|
| Component | apps/concordia/components/tabs/tabs.jsp |
| Dialog | apps/concordia/components/tabs/dialog.xml |
| Clientlib | Category apps.concordia.tabs (included from the JSP). |
Instance ids: Derived from the resource path under jcr:content so multiple tab components on a page stay unique.