How to remove glitchy color transitions? - html

I am in the process of designing an animated menu. I tried to get the text in the boxes to change color and they do so, but it's rather glitchy. The text flashes after the transition, and when you hover over it. Here's the JsFiddle with the glitch.
I also noticed it works fine without the hover transition, except of course the text doesn't change color. Here's that one: Less glitchy one.
Please suggest a fix.
Glitchy code [I removed webkit]
/* CSS */
#keyframes box {
0% {
left: 0px;
width: 30px;
}
50% {
left: 30px;
width: 0px;
}
100% {
left: 30px;
width: 70px;
color: #FFF;
}
}
h1 {
position: relative;
left: 30px;
color: cyan;
font-family: 'Agency FB';
}
div {
position: relative;
height: 30px;
width: 0px;
left: 0px;
background-color: cyan;
color: transparent;
animation: box 1.0s forwards;
transition: all 0.5s ease;
}
div:hover {
background-color: #FFF;
border: 1px solid cyan;
}
div:hover label {
color: cyan;
}
label {
position: absolute;
left: 5px;
font-family: 'Agency FB';
transition: all 0.5s ease;
}
<!-- HTML -->
<h1>
Test
</h1>
<div id="1">
<label>Hello</label>
</div>
<br>
<div id="1">
<label>World</label>
</div>
<br>
<div id="1">
<label>Foobar</label>
</div>

I can see the glitch, but probably is because of this:
transition: all 0.5s ease;
maybe you have other color fot the text in the parent, if you only want the transition on the background-color useit only there
transition: background-color 0.5s ease;
andto avoid the change of height you can use this
box-sizing: border-box;

I don't know what exactly you mean by "glitchy".
First of all I would change:
border: 1px solid cyan;
To:
outline: 1px solid cyan;
Border made this div move a little bit when hover works.

Related

Make nav underline animate based on class

I have a .nav-link
When .active is added to it, it gets text-decoration: underline. How do i make this text decoration animate by sliding in from the left?
You can create and animate custom underline like this. As you cannot animate the text-decordation: underline;
.nav-link:after{
content: '';
position: absolute;
width: 0; height: 3px;
display: block;
margin-top: 5px;
right: 0;
background: #fff;
transition: width .2s ease; // this will add animation from left to right.
-webkit-transition: width .2s ease;
}
.nav-link:active:after{
width: 100%;
left: 0;
background: #fff;
}

Why is the transition timing working on color, but not text-align?

I am trying to add transition timing when switching the text alignment via :hover. The transition is added to the color properly, but not the text alignment.
example: Codepen
div {
background-color: #ff4000;
height: 300px;
width: 600px;
}
div:hover>h1 {
color: #ddd;
text-align: right;
transition: .6s ease-in !important;
}
<div>
<h1>Lorem Ipsum</h1>
</div>
I guess it was just the CSS Working Group decided not to implement it for whatever reasons. But there are other ways around, see the following demo by using position and transform tricks.
div {
background-color: #ff4000;
height: 300px;
width: 600px;
position: relative;
}
h1 {
position: absolute;
left: 0;
top: 0;
white-space: nowrap;
margin: 0;
transition: 0.6s ease-in;
}
div:hover > h1 {
color: #ddd;
left: 100%;
transform: translateX(-100%);
}
<div>
<h1>Lorem Ipsum</h1>
</div>
Another approach is to animate width.
div {
background-color: #ff4000;
height: 300px;
width: 600px;
}
h1 {
width: 0;
text-align: right;
white-space: nowrap;
margin: 0;
transition: 0.6s ease-in;
}
div:hover > h1 {
color: #ddd;
width: 100%;
}
<div>
<h1>Lorem Ipsum</h1>
</div>
transform: translateX()
text-align is not animatable but position and transforms are -- the latter being the better choice because it's less GPU/CPU intensive than the former. The following is a what was added as the first leg of the animation in the demo.
transform:translateX(300px);
transition: transform .6s ease-in;
Demo
div {
background-color: #ff4000;
height: 300px;
width: 600px;
}
h1 {
transform: translateX(0px);
transition: transform .6s ease-out;
}
div:hover>h1 {
color: #ddd;
width: 200px;
transform: translateX(300px);
transition: transform .6s ease-in;
}
<div>
<h1>Lorem Ipsum</h1>
</div>

Run CSS transition in one direction but not the other

I'm using a CSS transition on my hyperlink elements to make their interaction appear smoother. But I also want immediate feedback when the user is waiting for it. Hence I want the new state to appear immediately, but let it fade out when the user moves away.
Here's some CSS that I'm currently using:
a
{
display: inline-block;
padding: 20px;
background: #eeeeee;
color: black;
text-decoration: none;
transition: background 1s;
}
a:hover
{
background: #bbbbbb;
transition: background 0s;
}
a:active
{
background: #888888;
transition: background 0s;
}
Test link
As you can see the colour fade is in effect when leaving the element with the mouse cursor, but not when entering it.
When pressing a mouse button on the hovered link, the colour again changes immediately.
Now comes the interesting part: When the mouse button is released, I'd like the colour to fade back to the hover state. But I can't manage to do so because the :hover state doesn't know from which state direction it's coming and always disables the transition.
Whatever is changed, there must be no transition when first hovering the link.
Again in a simple state diagram:
State: normal <----------> hover <----------> active
Transition: yes no yes? no
(currently no)
Is this possible with CSS? I know I could add custom JavaScript but that would need to go to a great number of elements.
An idea is tu use pseudo-element to create your backgrounds and you can easily create the effect you want. The drawbacks is that you will have more CSS and you have to add your content inside a span in order to correctly set z-index values.
Using 2 pseudo-elements:
a {
display: inline-block;
padding: 20px;
background: #eeeeee;
color: black;
text-decoration: none;
transition: background 1s;
position: relative;
}
a span {
position: relative;
z-index: 3;
}
a:before,
a:after {
content: "";
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: transparent;
z-index: 1;
transition: background 1s;
}
a:after {
z-index: 2;
}
a:hover::before {
background: red;
transition: background 0s;
}
a:active::after {
background: blue;
transition: background 0s;
}
<span>Test link</span>
Using only one pseudo element:
a {
display: inline-block;
padding: 20px;
background: #eeeeee;
color: black;
text-decoration: none;
transition: background 1s;
position: relative;
}
a span {
position: relative;
z-index: 1;
}
a:before {
content: "";
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: transparent;
z-index: 0;
transition: background 1s;
}
a:hover {
background: red;
transition: background 0s;
}
a:active::before {
background: blue;
transition: background 0s;
}
<span>Test link</span>
Here's what I did based on Temani Afif's answer. It doesn't need the additional <span> inside the link but instead an additional data-text attribute on it, and it only works for plain text content (no images etc.).
The example has two test links, one with and one without the attribute, to show the fallback behaviour that's basically what I have in the question.
Not sure which is "better". It probably depends on the circumstances. I just wanted to add this solution as well.
a
{
display: inline-block;
padding: 20px;
background: #eeeeee;
color: black;
text-decoration: none;
transition: background 1s;
position: relative;
}
a:hover
{
background: red;
transition: background 0s;
}
a[data-text]::before
{
content: attr(data-text);
color: transparent;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
padding: 20px;
background: transparent;
transition: background 1s, color 1s;
}
a[data-text]:active::before,
a:not([data-text]):active
{
color: white;
background: blue;
transition: background 0s;
}
Test link
Test link

Is there a more efficient way to make background position change from left to right on hover?

This is the code I currently have to make it seem as though the left border expands on hover, even though it's just the background changing. Is there a more efficient way to write this code?
edit: Efficient meaning a better way to write it.
span {
padding: 5px;
text-align: center;
border-left: 5px solid black;
background: linear-gradient(to left, yellow 50%, black 50%);
background-size: 200%, 100%;
background-position: right;
transition: .5s ease;
}
span:hover {
background-position: left;
color: white;
}
<span>This is some example text.</span>
I prefer using pseudo elements for this stuff, as you can then add transforms and such to the pseudo element for better performance.
Only problem with this is that you need to wrap your span in another element, so that you can position the text over the pseudo element with z-index. Otherwise it will just cover your text.
span {
color: black;
transition: color .5s ease;
z-index: 2;
position: relative;
}
p {
padding: 5px;
text-align: center;
border-left: 5px solid black;
background-color: yellow;
position: relative;
overflow: hidden;
display: inline-block;
}
p::after {
content: '';
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: black;
transition: transform .5s ease;
transform: translateX(-100%);
will-change: transform;
z-index: 1;
}
p:hover::after {
transform: translateX(0);
}
p:hover span {
color: white;
}
<p><span>This is some example text.</span></p>

div button to slide in and off screen (depending user's mouse)

I have a div with class .side-buttons. This div will slide in and off when user's mouse hover over the div. I was wondering how can I hide the div completely and say when the user's mouse is in the area it would slide in?
I tried getting the off the screen but that wouldn't work as it would only work when my mouse on the div
This is my website - http://smati.ca/test/index.html (Don't click continue but instead click around the popup modal to get off the modal overlay. There you can see the div in action)
Here's my css code :
.side-buttons {
position: absolute;
right: -100px;
top: 55%;
-webkit-transition: all .4s ease-in-out;
-moz-transition: all .4s ease-in-out;
-ms-transition: all .4s ease-in-out;
-o-transition: all .4s ease-in-out;
transition: all .4s ease-in-out;
}
.side-buttons:hover {
right: 0px;
}
.side-buttons a {
display: block;
background: linear-gradient(to bottom, #33a9c3 15%, #b1ccbb 100%);
border-radius: 0;
box-shadow: none;
border: none;
color: #f5f5f5;
font-size: 22px;
font-family: "Lato", sans-serif;
}
.side-buttons a small {
font-size: 16px;
}
.side-buttons a:hover,
.side-buttons a:focus,
.side-buttons a:active {
background: linear-gradient(to bottom, #33a9c3 15%, #b1ccbb 100%);
color: #f5f5f5;
}
.side-buttons a:nth-child(2) {
background: linear-gradient(to left, #de3c88 15%, #f0a473 100%);
}
You could try something like this too i.e wrapping it by a div and performing that slide-in and slide-out effect on child div as below,
#bx{
width:210px;
height:120px;
position:absolute;
top:40%;
right:0;
overflow:hidden;
border:1px solid rgba(0,0,0,0.1);
}
#bx > .b{
position:absolute;
width:200px;
height:120px;
background:blue;
right:-200px;
transition:0.6s ease;
}
#bx:hover > .b{
right:0px;
}
<div id="bx">
<div class="b">
</div>
</div>
You can use a pseudo element, like this
html, body {
margin: 0;
}
div {
position: absolute;
width: 0;
right: 0;
height: 150px;
background: red;
transition: width 0.5s;
}
div::after {
content: '';
position: absolute;
width: 30px;
right: 100%;
height: 100%;
transition: width 0s 0.5s;
border: 1px dotted gray; /* added for demo purpose */
}
div:hover {
width: 100px;
transition: width 0.5s;
}
div:hover::after {
width: 0;
transition: width 0.5s;
}
<div>
</div>
Here is another option, that might be easier to add to your existing solution
html, body {
margin: 0;
}
.content {
width: 170px;
padding: 50px 30px;
background: lightgray;
}
.wrapper {
position: absolute;
right: 0;
width: 0;
padding-left: 30px;
overflow: hidden;
transition: width 0.5s, padding-left 0s 0.5s;
border: 1px dotted gray; /* added for demo purpose */
}
.wrapper:hover {
width: 200px;
padding-left: 0;
transition: width 0.5s, padding-left 0.5s;
}
<div class="wrapper">
<div class="content">
Some text and/or images<br>
or anything else needed
</div>
</div>