Build1 publisher3 min readPublished
The infinite transition: a two-line CSS latch that keeps hover state and stores nothing
A dev.to post shows how transition-duration: calc(infinity * 1s) makes a hover style stick without JavaScript. The paint changes; the DOM does not, and that is the whole tradeoff.
The Engineer · Build desk
Drafted by a language model from the sources cited here and checked against its claim ledger before publication. How we use AISend a correction

What happened
- A dev.to post from frontendfacile, titled in Italian as making a hover permanent with a single line of CSS and without JavaScript, describes a trick using transition-duration and calc() so that the element's return to its base state takes 'infinite' time.
- The post explains a transition has two moments: the forward change when the element enters :hover or :focus, and the return to the base style when it leaves; normally a single transition-duration applies in both directions.
- The technique sets an infinite duration in the base state, so the return never occurs (it requires infinite time), and a normal duration such as 0.5s in the :hover / :focus state to animate the forward change.
- The post's minimal example is: a, h1 { color: black; transition-property: color; transition-duration: calc(infinity * 1s); } and a:hover, a:focus, h1:hover, h1:focus { color: red; transition-duration: 0.5s; }
- The post states that transition-duration requires a time value (s or ms), that infinity is a valid numeric value in CSS but is not by itself a time, and that calc(infinity * 1s) converts it into a duration.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
A post from frontendfacile on dev.to documents a CSS trick for making a hover effect stick: give the base state an infinite transition duration and the interactive state a normal one, and the element never travels back [1][3]. That is the smallest available substitute for a very common JavaScript pattern, adding a class on pointer entry and never removing it, and it is worth knowing exactly what it gives up.
The mechanism depends on the fact that a transition runs in two directions: forward when the element enters `:hover` or `:focus`, and back to the base style when it leaves, with one `transition-duration` normally governing both [2]. The post splits them:
```css a, h1 { color: black; transition-property: color; transition-duration: calc(infinity * 1s); } a:hover, a:focus, h1:hover, h1:focus { color: red; transition-duration: 0.5s; } ```
The `calc()` is not decoration. According to the post, `transition-duration` requires a time in `s` or `ms`, and `infinity` is a valid CSS number but not a time on its own, so multiplying it by `1s` produces a duration [5]. Pointer in, the colour reaches red in 0.5s; pointer out, the return transition is scheduled for infinity, so in practice the element stays red [6].
Two notes on the framing. Despite the headline's "one line," the effect needs two declarations across two rules, one for the base duration and one for the hover duration [10]. And the post is explicit that this is not a toggle in the application sense: no state is stored, and the persistence is only the visual consequence of a return that is postponed indefinitely [7].
That second point is where the cost lands. The rules change nothing but `color` and `transition-duration` [4], so there is no attribute, no class, and no DOM change for anything else to read [12]. Nothing to submit with a form, nothing for a sibling selector to key off, nothing to restore after a re-render. The selector list also includes `:focus` [4], which means keyboard traversal latches too: tab across a page of links and every one you pass through stays in the hovered style, with no way back [11]. If you want a real persistent state that survives clicks, focus changes and keyboard navigation, the post itself points to `:checked` with input and label, `:target`, or JavaScript [8]. Its stated fit is narrower: demos, prototypes, playful microinteractions, and temporary highlights that do not need to be true at the state level [9].
What to watch: the post does not discuss browser support for `calc(infinity * 1s)`, nor what happens if the element's computed styles are recalculated while a nominally infinite transition is in flight [13]. Test the latch under a media query change, a class swap on an ancestor, and a framework re-render before you ship it anywhere the highlight is meant to mean something. If it has to mean something, use the checkbox.