Deep linking
Link directly to any panel state.
How it works
Both components determine the initial state on every page load from three sources, checked in order:
- URL param (
?panel=): Reading of the URL parameter will always be done, no config needed. See below. - localStorage: used when
persistis enabled and no URL param applied. See Persisting state. - HTML default: the markup state like
class="active"panel (PanelSet) orclass="is-open"(Panel / closable PanelSet).
On this page we delve a bit deeper into deep linking.
Reading the URL parameter
Reading is always on. Panel and PanelSet always check the ?panel= param on load. Any link with ?panel=id opens that panel. For example, a link like index.html?panel=demo-panel-4 opens the panel with ID demo-panel-4 on page load. Note that we do not use just a hash, because that is much more limited. The ?panel= param is designed to be purely for panel state.
The ?panel= query param is a comma-separated list of panel IDs.
<!-- Open or activate a single panel -->
<a href="?panel=pricing">Link to Pricing</a>
<!-- Open or activate multiple panels at once -->
<a href="?panel=pricing,sidebar">Pricing tab open, sidebar open</a>
Because HTML IDs are (or at least should be) unique per HTML page, a panel ID always points to exactly one element, whether it is a standalone [data-panel] collapse or a [role="tabpanel"] inside a PanelSet.
Writing the URL parameter
Writing is optional. By default the URL is never modified.
However, you can enable deepLink to keep the URL in sync as the user opens and closes panels, so the current state can be shared from the address bar. When any panel (Panel or PanelSet) opens, its ID is added to ?panel=. When it closes, the ID is removed. Multiple open panels accumulate naturally: ?panel=faq-1,faq-2.
Deep linking in Panel
Key Features
- This is our most important feature ever!
new Panel('#sidebar', { deepLink: true });
// or via init
Panel.init({ deepLink: true });
<div id="sidebar" data-panel data-panel-deeplink>...</div>
Deep linking in PanelSet
Key Features
- This is our most important feature ever!
Pricing Plans
- Starter Plan: Whenever you don’t want to pay a lot.
- Professional Plan: Ideal for managers who like to spend money!
Support Options
- If you send us an email, we will probably ignore it.
- We don’t even have a community forum.
- Opening an issue on GitHub is your next best option. Or even better: PR’s! You do the work!
new PanelSet('#example', { deepLink: true });
// or via init
PanelSet.init({ deepLink: true });
<div id="example" data-panelset data-panel-deeplink>...</div>
Note: a PanelSet uses data-panel-deeplink (the panel- prefix), not data-panelset-deeplink. The deep-link attributes are shared with Panel, so the prefix stays panel- on both.
Play around with the two examples above, and reload the page. Both come back in the same state you left them. You can also send the link to a friend and the same panels will be opened.
For accordion groups, set data-panel-deeplink on the [data-panel-group] element to cover all panels in the group at once.
Suppressing transitions on load
When a panel opens from a URL parameter, it snaps open instantly without an animation. Any CSS transitions on the surrounding elements (such as a chevron rotation or a border color change) would still play, which can look wrong on a cold page load.
Panel adds an is-restored class to the element for exactly one paint cycle when this happens. You can use it to suppress those transitions:
:has(> [data-panel].is-restored),
:has(> [data-panel].is-restored) * {
transition: none !important;
}
The direct-child combinator (>) keeps the selector scoped to the immediate parent of the panel, so only that container and its contents are affected. The class is removed after the first paint, so all subsequent opens and closes animate normally.