/    Sign up×
Community /Pin to ProfileBookmark

Help with title bar controls animation

Hello,
I’ve created the following mockup of a title bar control animation I would like to implement in an Electron app:
Animated Title Bar Controls![Animated Title Bar Controls](https://i.ibb.co/sRfhKGn/Title-Bar-Controls.gif)

Then, I’ve [recreated the desired effect with CSS & JS](https://codepen.io/Looky1173/pen/WNOroVz). It works fine except for one thing: when you first move your mouse inside the wrapper and the highlight is not behind the hovered icon, you can see the highlight move from its previous position. Instead, it should be translated to the correct offset instantaneously and only the opacity should be animated. How can I address this issue?

Thank you for any help in advance!

to post a comment
CSSJavaScript

7 Comments(s)

Copy linkTweet thisAlerts:
@SempervivumAug 30.2021 — Try this javascript:
``<i>
</i> const defaultSelection = document.getElementById("minimize");
const highlight = document.getElementById("highlight");
const wrapper = document.getElementById("wrapper");
// after page load or when the mouse is entering
// the wrapper, transition-property is 'none'
wrapper.addEventListener("mouseenter", (event) =&gt; {
// shift the highligt to the current item
// without transition:
setStyles(highlight, event.target.closest('li'));
});

wrapper.addEventListener("mouseleave", (event) =&gt; {
highlight.style.opacity = 0;
// we set transition property to 'none'
// so that shifting the highlight
// is done immediately without animation
// when the mouse is entering again:
highlight.transitonProperty = 'none';
});

document.querySelectorAll("li").forEach((item) =&gt; {
item.addEventListener("mouseover", (event) =&gt; {
// wait a short moment, then switch on transition
// and move the highlight to the current item:
setTimeout(() =&gt; {
highlight.transitonProperty = 'all';
setStyles(highlight, event.target.closest('li'));
highlight.style.opacity = 1;
}, 10)
});
});

function setStyles(elementToStyle, eventTarget) {
elementToStyle.style.width = getStyles(eventTarget).w + "px";
elementToStyle.style.height = getStyles(eventTarget).h + "px";
elementToStyle.style.left = getStyles(eventTarget).pos + "px";
}

function getStyles(target) {
return {
w: target.scrollWidth,
h: target.scrollHeight,
pos: target.offsetLeft
};
}<i>
</i>
`</CODE>
and switch off transition initially:
<CODE>
`<i>
</i> #highlight {
transition-property: none;
transition-duration: 200ms;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
z-index: -10;
position: absolute;
min-height: 100%;
border-radius: 5px;
background-color: #BBBBBB;
opacity: 0;
}<i>
</i>
``
Copy linkTweet thisAlerts:
@looky1173authorAug 31.2021 — @Sempervivum#1636309 Unfortunately, that didn't work. The highlight moved to the correct position on the initial hover but it lost all transitions afterwards.
Copy linkTweet thisAlerts:
@SempervivumAug 31.2021 — Sorry, your are right, I didn't test this carefully. Gonna look into again ...
Copy linkTweet thisAlerts:
@SempervivumAug 31.2021 — Check if this javascript is working better:
``<i>
</i> const defaultSelection = document.getElementById("minimize");
const highlight = document.getElementById("highlight");
const wrapper = document.getElementById("wrapper");
wrapper.addEventListener("mouseleave", (event) =&gt; {
highlight.style.opacity = 0;
// we remove the class "transition-active"
// so that shifting the highlight
// is done immediately without animation
// when the mouse is entering again:
highlight.classList.remove('transition-active');
});

document.querySelectorAll("li").forEach((item) =&gt; {
item.addEventListener("mouseover", (event) =&gt; {
// after page load or when the mouse is entering
// the wrapper, transition is switched of,
// therefore shifting the highlight is done without transition
setStyles(highlight, event.target.closest('li'));
highlight.style.opacity = 1;
// subsequently shifting the highlight should be animated,
// therefore switch on transition
// after waiting for a short moment:
setTimeout(() =&gt; {
highlight.classList.add('transition-active');
}, 10)
});
});

function setStyles(elementToStyle, eventTarget) {
elementToStyle.style.width = getStyles(eventTarget).w + "px";
elementToStyle.style.height = getStyles(eventTarget).h + "px";
elementToStyle.style.left = getStyles(eventTarget).pos + "px";
}

function getStyles(target) {
return {
w: target.scrollWidth,
h: target.scrollHeight,
pos: target.offsetLeft
};
}<i>
</i>
`</CODE>
Animating the position is done by adding the class "transition-active":
<CODE>
`<i>
</i> #highlight {
/* initially only opacity is animated: */
transition-property: opacity;
transition-duration: 200ms;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
z-index: -10;
position: absolute;
min-height: 100%;
border-radius: 5px;
background-color: #BBBBBB;
opacity: 0;
}

/* animation of property "left" is switched on
when the class "transition-active" is set: */
#highlight.transition-active {
transition-property: all;
}<i>
</i>
``
Copy linkTweet thisAlerts:
@looky1173authorAug 31.2021 — @Sempervivum#1636323 It works great, thank you! 😃 It looks like you can set the setTimeout to 0 and it will still work.
Copy linkTweet thisAlerts:
@SempervivumAug 31.2021 — Yes, it even works when omitting the duration.
Copy linkTweet thisAlerts:
@yangkikuAug 31.2021 — A creative idea! I want to thank you!

[word unscrambler](https://word-unscrambler.io)
×

Success!

Help @looky1173 spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 BETA 4.26,
whats_new: community page,
up_next: more Davinci•003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinci•003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @Yussuf4331,
tipped: article
amount: 1000 SATS,

tipper: @darkwebsites540,
tipped: article
amount: 10 SATS,

tipper: @Samric24,
tipped: article
amount: 1000 SATS,
)...