---
title: "Styling"
manual: "Academic Programs"
version: "main"
permalink: "https://docs.typo3.org/permalink/fgtclb/academic-programs:styling@main"
source: "Styling/Index.rst"
rendered: "2026-10-17T08:47:58+00:00"
---

# Styling {#styling}

The plugins and the program page of this extension render their markup with
the class system of the academic extensions and ship no styling for it. The
system, the classes of Bootstrap it keeps and how a site package styles the
markup are described once, in the chapter [Styling of academic_base](https://docs.typo3.org/p/fgtclb/academic-base/main/en-us/Styling/Index.html#styling).
This chapter shows how the markup of this extension is built up.

-   [The outermost elements](https://docs.typo3.org/permalink/fgtclb/academic-programs:the-outermost-elements@main)
-   [The program list](https://docs.typo3.org/permalink/fgtclb/academic-programs:the-program-list@main)
-   [The program details](https://docs.typo3.org/permalink/fgtclb/academic-programs:the-program-details@main)
-   [The program finder](https://docs.typo3.org/permalink/fgtclb/academic-programs:the-program-finder@main)
-   [The program page](https://docs.typo3.org/permalink/fgtclb/academic-programs:the-program-page@main)
-   [The scripts](https://docs.typo3.org/permalink/fgtclb/academic-programs:the-scripts@main)
-   [An example](https://docs.typo3.org/permalink/fgtclb/academic-programs:an-example@main)

## The outermost elements {#styling-outermost-element}

| Plugin or page | Content element or page type | Outermost element |
| --- | --- | --- |
| Program list | `academicprograms_programlist` | `academic-programs-list` |
| Program details | `academicprograms_programdetails` | `academic-programs-detail` |
| Program finder | `academicprograms_programfinder` | `academic-programs-finder` |
| Program page | the page type of a program | `academic-programs-page container` |

## The program list {#styling-list}

```html
<div class="academic-programs-list" data-academic-programs-list="…">
    <!-- the header of the content element, when the plugin renders it -->
    <div class="ace-content" data-academic-programs-list-content …>
        <form class="ace-form" data-academic-programs-list-form …>
            <div class="ace-filters">
                <div class="row">
                    <div class="col-12 col-md-6 col-lg-4 col-xl-3">
                        <div class="ace-filter ace-field ace-select-wrap">
                            <label class="ace-label" for="…">Degree</label>
                            <select class="ace-control ace-select" …>…</select>
                        </div>
                    </div>
                    <div class="col-12">
                        <details class="ace-more">…</details>
                    </div>
                    <div class="col-12 col-md-6 col-lg-4 col-xl-3" data-academic-programs-list-submit>
                        <button type="submit" class="btn btn-primary">Show programs</button>
                    </div>
                </div>
            </div>
        </form>
        <ul class="ace-list ace-active-filters" aria-label="…">…</ul>
        <a class="ace-link" href="…">Reset filters</a>
        <p class="ace-count">12 programs</p>
        <div class="ace-itemlist">
            <div class="row">
                <div class="col-12 col-md-6 col-lg-4 col-xl-3">
                    <article class="ace-item">…</article>
                </div>
            </div>
        </div>
    </div>
    <p class="ace-status visually-hidden" role="status" aria-live="polite" …></p>
</div>
```

-   The filter bar is built up like the one of the other list plugins: the
    sorting selects, one filter per category type, the further filters inside
    the `<details class="ace-more">` with its
    `<summary class="ace-toggle">`, and the submit button.
-   With JavaScript, the list script replaces the `ace-content` when a select
    changes, without a page load, and hides the column of the submit button
    with the attribute `hidden`. The `ace-status` is outside the replaced
    region and announces the new number of results to a screen reader. With
    the script switched off, see [The scripts](https://docs.typo3.org/permalink/fgtclb/academic-programs:styling-script-switch@main), the button stays
    and the form is sent as a request of its own.
-   The active filters, the reset link and the count are only rendered when the
    content element switches them on, see [Active filters, reset link and result count](https://docs.typo3.org/permalink/fgtclb/academic-programs:configuration-active-filters@main).
    An active filter is an `ace-list-item ace-active-filter` holding an
    `ace-link` with an `ace-icon`.
-   A list without programs renders the message in a
    `<span class="ace-empty">` in place of the item list.

### A program {#styling-item}

```html
<article class="ace-item">
    <div class="ace-item-content">
        <header class="ace-header">
            <h2 class="ace-title"><a href="…">Program title</a></h2>
        </header>
        <ul class="ace-list ace-attributes">
            <li class="ace-list-item ace-attribute" data-academic-programs-fact="degree">
                <span class="ace-icon">…</span>
                <b class="ace-label">Degree:</b>
                <span class="ace-value">Bachelor</span>
            </li>
        </ul>
    </div>
    <!-- the first image of the program, preset "card" -->
</article>
```

The attributes are the facts the content element shows on a card, see
[The facts of a program](https://docs.typo3.org/permalink/fgtclb/academic-programs:program-facts@main). A fact without an icon renders no `ace-icon`. The value
of a rich text fact is an `ace-value ce-bodytext`, so the content styles of the
site apply to it.

## The program details {#styling-detail}

```html
<div class="academic-programs-detail">
    <!-- the header of the content element, when the plugin renders it -->
    <ul class="ace-list ace-attributes">
        <li class="ace-list-item ace-attribute" data-academic-programs-fact="…">…</li>
    </ul>
</div>
```

The facts are built up like those of a program in the list.

## The program finder {#styling-finder}

```html
<!-- the header of the content element, when the plugin renders it -->
<div class="academic-programs-finder">
    <form class="ace-form" data-academic-programs-finder-programs="…" …>
        <div class="ace-filters">
            <div class="row">
                <div class="col-12 col-md">
                    <div class="ace-filter ace-field ace-select-wrap">
                        <label class="ace-label" for="…">Degree</label>
                        <select class="ace-control ace-select" data-academic-programs-finder-select …>…</select>
                    </div>
                </div>
                <div class="col-12 col-lg-4">
                    <button type="submit" class="btn btn-primary">
                        <span class="ace-count" data-academic-programs-finder-count>Show 12 programs</span>
                    </button>
                </div>
            </div>
        </div>
        <p class="ace-status visually-hidden" role="status" aria-live="polite" …></p>
    </form>
</div>
```

-   The header of the content element is rendered before the
    `academic-programs-finder`, not inside it.
-   The finder renders nothing without a list page or without a filter to
    show.
-   The finder script writes the number of matching programs into the
    `ace-count` of the button, and announces it in the `ace-status`. Without
    the script, the button keeps its label.
-   The submit button is a Bootstrap button, `btn btn-primary`, as the one of
    the list is.

## The program page {#styling-page}

```html
<div class="academic-programs-page container">
    <div class="ace-hero">
        <header class="ace-header">
            <h1 class="ace-title">Program title</h1>
            <p class="ace-subtitle">…</p>
        </header>
        <!-- the first image of the program, preset "detail" -->
    </div>
    <a class="ace-link" href="…">Back to the list</a>
    <a class="btn btn-primary ace-apply" href="…">Apply now</a>
    <ul class="ace-list ace-attributes">…</ul>
    <!-- the content elements of the page -->
</div>
```

-   The back link is only rendered when a list page is configured, the
    application link only when the program has one, see
    [The application link of a program page](https://docs.typo3.org/permalink/fgtclb/academic-programs:program-application-link@main).
-   The application link is a Bootstrap button, `ace-apply` tells it from other
    buttons of the site.
-   The facts are the facts of the page, built up like those of a program in
    the list.
-   The page renders inside the layout of the site, see
    [The layout of a program page](https://docs.typo3.org/permalink/fgtclb/academic-programs:program-page-layout@main).

## The scripts {#styling-script-switch}

The list and the finder each load a script, which the site setting or
TypoScript constant `plugin.tx_academicprograms.assets.js` switches off for
both, see [Load the script or bring your own](https://docs.typo3.org/permalink/fgtclb/academic-programs:configuration-javascript@main). The markup stays the same, so a
script of the project can drive it through the same `data-academic-programs-*`
attributes. No other plugin and not the program page load a script.

## An example {#styling-example}

Rules in the stylesheet of the site package, scoped by the outermost element:

```css
.academic-programs-list .ace-item {
    display: flex;
    flex-direction: column-reverse;
    height: 100%;
}

.academic-programs-list .ace-attributes,
.academic-programs-page .ace-attributes {
    list-style: none;
    padding-left: 0;
}

.academic-programs-page .ace-apply {
    margin-block: 1rem;
}
```

The development instances style the program list, the program finder, the
program details and the program page with the partial
[\_academic-programs.scss](https://github.com/fgtclb/academic-extensions/blob/main/packages-dev/dev-site/Resources/Private/Scss/frontend/_academic-programs.scss),
together with the shared rules of [\_academic-base.scss](https://github.com/fgtclb/academic-extensions/blob/main/packages-dev/dev-site/Resources/Private/Scss/frontend/_academic-base.scss),
both of the site package `academics_dev_site`, a complete example to copy
from.

To change the markup itself, override the partials of the extension, the page
partials as described in [The parts of a program page](https://docs.typo3.org/permalink/fgtclb/academic-programs:program-page-partials@main).
