Here is what you see on the screen. The left docked nav expands on hover the way it should. You open a Dropdown inside it, such as a language selector, and move the cursor onto an option. The dock snaps back to 55 px while the option list is still open. Sometimes the list closes too, or it floats beside a collapsed bar.
The stylesheet that produces this behavior usually looks like this:
.docked-view-left {
width: auto !important
}
.psc-nav {
width: 55px;
transition: width 0.3s ease-in-out;
}
.psc-nav:hover {
width: 300px;
}
The CSS has no syntax error, so editing it will not fix the collapse. The problem is where the Dropdown's option list sits in the page.
Skip the Fixes That Waste Time
These are the usual attempts. None of them solves the collapse.
-
Adding
!importantto the 300 px width. This is not a specificity problem. The:hoverrule is no longer matching, so its priority does not matter. - Lengthening the transition or adding a delay. This only slows the collapse. The dock still shrinks while the menu is open, just more slowly.
-
Changing
.docked-view-leftwidth values.width: auto !importantis what lets the inner container control the dock width. Leave it in place. - Resizing the Dropdown or moving it inside the container. The option list renders in the same place no matter where the Dropdown sits in the view tree.
-
Searching for a pure-CSS hover trick.
:hoverfollows DOM ancestry. No selector on the nav container can match a pointer over an element that is not its descendant. Stop there and use events instead.
Understand Why :hover Lets Go
Start here. The Perspective Dropdown (Selection component) option list opens as a modal. It is rendered outside your nav container in the DOM and is not a child of the element with psc-nav.
The browser applies :hover to an element only while the pointer is over that element or one of its DOM descendants. When the cursor leaves the Dropdown field and moves onto the floating option list, the pointer is over an element that belongs somewhere else in the document. .psc-nav:hover stops matching, and the width transitions back to 55 px.
A Perspective component mouse event such as onMouseLeave behaves differently. It fires once, when the cursor leaves the component bounds. In practice, moving onto the Dropdown modal does not trigger it. That is why the class-swap method below keeps the dock open.
| Symptom | Cause | Fix |
|---|---|---|
| Dock collapses when the cursor enters Dropdown options | Option list is a modal outside the nav DOM subtree, so :hover drops |
Replace :hover with onMouseEnter/onMouseLeave class swaps |
| Dock opens at minimum width on first load | No initial style class set on the container | Set props.style.classes to the reduced class in the Designer |
| Other styling disappears after first hover | Script assigns style.classes as a single string and overwrites existing classes |
Include every required class in the assigned string |
| Dock set to "pushed" overlays the main view instead of pushing it | Rule conflict in the style hierarchy, or push offset not following CSS width | Inspect the rendered element in browser DevTools |
| Expansion lags on remote clients | Mouse event scripts run on the Gateway and need a round trip | Expected behavior. Keep the transition short |
Replace :hover With Two Explicit Classes
Split the single hover rule into two named states. Keep the dock width override as it is.
.docked-view-left {
width: auto !important
}
.psc-navReduced {
width: 55px;
transition: width 0.3s ease-in-out;
}
.psc-navExpanded {
width: 300px;
transition: width 0.3s ease-in-out;
}
- Put the transition on both classes. Then expanding and collapsing both animate, whichever class is being applied.
- Perspective adds the
psc-prefix to style classes. In the stylesheet you write.psc-navExpanded. In the component property you writenavExpanded. - Delete the old
.psc-nav:hoverrule. If you leave it, it still fires on real hover and competes with the scripted state.
Wire the Mouse Events on the Nav Container
- Open the docked view in the Designer and select the container that carries the nav style class. This is the element whose width the stylesheet controls.
- Optional: add a custom property on the view, for example
docked_status(boolean). Bind icon visibility, label text, or other cosmetic changes to it so they follow the dock state. - Right-click the container, choose Configure Events, and add a Script action under
onMouseEnter:def runAction(self, event): self.props.style.classes = 'navExpanded' self.view.custom.docked_status = True - Add a Script action under
onMouseLeave:def runAction(self, event): self.props.style.classes = 'navReduced' self.view.custom.docked_status = False - Set the container's initial
props.style.classestonavReducedin the property editor. See the next section for why this step matters. - Save the project and open a fresh session. Designer preview does not always reproduce the Dropdown modal behavior exactly.
Avoid the Setup Pitfalls
-
Initial class missing. If
style.classesis empty at startup, neither width rule applies and the dock opens at its minimum width. It only corrects itself after the first mouse event. Set the starting class explicitly. -
Overwriting other classes. Assigning a string to
self.props.style.classesreplaces the whole value. If the container also uses classes such as a background theme class, write them all out, for example'navExpanded navTheme'. Otherwise the first hover removes them. -
Events on the wrong element. Put the events on the same container that receives the class. If you attach them to a child,
onMouseLeavefires when the cursor moves between children and the dock flickers. - Gateway round trip. Component event scripts run on the Gateway, not in the browser. Each hover sends a message to the Gateway and waits for a property update. On a slow link, expect a short delay before the 0.3 s transition starts. That is normal behavior.
-
Using the custom property as the source of truth.
docked_statusreports what the last event set. Bind cosmetic changes to it, but do not use it to decide which class to apply. Let the events set the class directly.
Fix a Pushed Dock That Covers the View
A second fault often shows up after the class swap works. The docked view's display is set to "pushed", but the expanded nav slides over the main content instead of moving it aside. Before you blame the dock configuration, check the style hierarchy.
Perspective applies styles in this order. Each later layer overrides the one before it:
Theming > Stylesheet > Named Styles > Inline Props
The stylesheet resource is inserted between the Gateway theme files and the project's Named Styles. A Named Style or an inline style property on the component beats your stylesheet rule. Your stylesheet beats the theme.
- Check the nav container and the docked view root. Remove any Named Style or inline
styleprops that set width, position, or overflow. - Open the page in a local browser session. Press
Ctrl+Shift+I, or right-click and choose Inspect. - In the Elements panel, select the docked view element and then the main view container next to it.
- Read the Styles pane. Rules that are overridden appear struck through. Note which rule wins and which source it comes from: theme file, stylesheet, Named Style, or inline.
- Expand the nav and watch the main view container's offset (margin, padding, or left position) while the dock width changes. If the offset stays at the dock's configured size while the rendered width grows to 300 px, push mode is working. The push is sized from the dock configuration, and your CSS-driven width is simply wider than that configured size.
- Decide from what you found. If a rule overrides you, remove it or move your rule to a higher layer. If the offset follows the configured size, either set the dock size to match the expanded width, or accept an overlay for the extra 245 px (300 minus 55).
width: auto !important on .docked-view-left is the first suspect here. It overrides the dock's own width handling, so the dock's rendered width and the width Perspective uses for pushing can differ.
Verify the Fix in a Live Session
- Load the page fresh. The dock should render at 55 px immediately, with no flash at an undefined width.
- Hover the nav. It should expand to 300 px over 0.3 s, and
docked_statusshould readTrue. Check any bound cosmetic elements. - Open the Dropdown and move across every option, including the far edge of the list. The dock must stay at 300 px the whole time.
- Select an option and move the cursor off both the list and the nav. The dock should collapse, and
docked_statusshould return toFalse. - In DevTools, confirm that the container's class toggles between
psc-navReducedandpsc-navExpanded, and that no struck-through width rule remains. - If the dock is set to pushed, confirm the main content moves by the amount you expect at both widths.
- Repeat the test from a remote client to see the delay users on slower links will get.
FAQ
Can I keep the dock open during Dropdown hover with pure CSS?
Not with :hover on the nav container. The Dropdown option list is a modal outside the container's DOM subtree, so the hover state drops as soon as the cursor enters it. Use onMouseEnter and onMouseLeave events to swap style classes instead.
Does onMouseLeave fire when the cursor moves onto the Dropdown menu?
In practice, no. The event fires when the cursor leaves the component's bounds, and moving onto the Dropdown modal does not count as leaving. Test it in a live session by watching docked_status while you move across the option list.
Do I include the psc- prefix when setting style.classes in a script?
No. Write self.props.style.classes = 'navExpanded'. Perspective renders it as psc-navExpanded, which is the selector you use in stylesheet.css.
Why does my docked view open at minimum width before I hover it?
The container has no initial style class, so neither width rule applies until the first mouse event. Set props.style.classes to navReduced in the Designer so the dock starts in a defined state.
Can a stylesheet rule override the docked view's pushed setting?
Yes, a stylesheet rule can change how the dock renders. Named Styles and inline props can also override your stylesheet, because the order is Theming > Stylesheet > Named Styles > Inline Props. Inspect the page with Ctrl+Shift+I and look for struck-through rules to see which one wins. If DevTools shows no conflicting rule and the pushed dock still overlays the view at its configured size, collect the Gateway version, the dock configuration, and a DevTools screenshot, then contact Inductive Automation support.