How to use css transition correctly? - css

I'm trying to make a hidden div to be reavelead using transition but I mess things up and it doesn't work.
I got a div on top of another but I have it hidden using the visibility property. Now when I hover over the bottom div (.hexagon) I have the top div (.product-text) displayed. Everything works just fine. Although I want to make it a little bit smoother using a transition, but it just doesn't work.
The css (I'm using Sass) :
(the bottom div):
.hexagon {
position: relative;
background-color: black;
width: 240px;
height: 138.56px;
margin: 69.28px 0;
border-left: solid 5px $honey;
border-right: solid 5px $honey;
display:flex;
justify-content: center;
img{
height:100%;
z-index: 1;
}
&:hover{
background-color:white;
cursor: pointer;
.product-text{
visibility: visible;
transition: visibility 3s;
}
}
}
.....
(the top div):
.product-text{
text-align: center;
font-size:18px;
color: black;
text-shadow: 2px 2px 3px $honey;
border-radius: 7px;
font-weight:bold;
opacity: 0.8;
z-index:2;
position:absolute;
bottom:0;
left:0;
width: 100%;
height:100%;
visibility:hidden;
background-color: rgba(15, 1, 1, 0.555);
p{
margin:0em;
}
}

You can't transition visibility (nor any other binary property). What you can do is an opacity transition.
.hexagon {
&:hover {
.product-text {
opacity: 1;
}
}
}
.product-text {
opacity: 0;
transition: opacity 3s;
}
You probably want the transition property applied directly to the class and not to the hover state.
Example:
.parent {
width: 200px;
height: 200px;
background-color: red;
}
.child {
width: 100px;
height: 100px;
background-color: blue;
opacity: 0;
transition: opacity 2s;
}
.parent:hover .child {
opacity: 1;
}
<div class="parent">
<div class="child"></div>
</div>

Related

Continue Transition from where Animation Ended

See the following button animation:
html {
background: white;
font-family: Arial;
}
.button {
position: relative;
display: inline-block;
color: #000;
border: 2px solid #000;
padding: 10px 24px;
font-size: 20px;
font-weight: 600;
text-align: center;
text-decoration: none;
transition-property: color, background, border-color;
transition-duration: 0.3s;
}
.button:hover {
color: #fff;
}
.button:hover ._background:after {
transform: translateX(0);
animation: fill-horizontal 0.3s linear 0s 1;
}
.button ._background {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: -1;
overflow: hidden;
}
.button ._background:after {
content: "";
position: absolute;
display: block;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: #000;
transform: translateX(100%);
transition: transform .3s;
}
#keyframes fill-horizontal {
from {
transform: translateX(-100%);
}
to {
transform: translateX(0);
}
}
<a class="button" href="javascript:">
<div class="_background"></div>
Button
</a>
The intended animation is to sweep the ._background:after element in from the left, and then out to the right like so:
translateX(-100%)
translateX(0) - Hover
translateX(100%) - Remove Hover
Whilst the animation works as intended when the user hovers for the duration of the CSS animation (.3s), it looks terrible if the user 'unhovers' before the CSS animation completes.
I would like the transition to translateX(100%) to continue from where the animation finished. Is this even possible?
NOTE - I am aware that the div._background element is not necessary, this has additional functionality that is not relevant to this question.
You can consider the same effect differently in order to avoid this bad effect:
Here is an idea using background animation where the trick is to change the position only after the size has changed.
.button {
position: relative;
display: inline-block;
color: #000;
border: 2px solid #000;
padding: 10px 24px;
font-size: 20px;
font-weight: 600;
text-align: center;
text-decoration: none;
background-image:linear-gradient(#000,#000);
background-size:0% 100%;
background-position:left;
background-repeat:no-repeat;
background-origin:border-box;
transition:color 0.3s, background-size 0.3s, background-position 0s 0.3s;
}
.button:hover {
color:#fff;
background-size:100% 100%;
background-position:right;
}
<div class="button">Some text</div>
Using this method, you will have a transition back in case you unhover rapidly.
A hacky idea to force the animation to complete is to consider a pseudo element that will make the hover area bigger and be sure you will keep the hover until the end:
.button {
position: relative;
display: inline-block;
color: #000;
border: 2px solid #000;
padding: 10px 24px;
font-size: 20px;
font-weight: 600;
text-align: center;
text-decoration: none;
background-image:linear-gradient(#000,#000);
background-size:0% 100%;
background-position:left;
background-repeat:no-repeat;
background-origin:border-box;
transition:color 0.3s, background-size 0.3s, background-position 0s 0.3s;
}
.button:hover {
color:#fff;
background-size:100% 100%;
background-position:right;
}
.button:hover:before {
content:"";
position:fixed;
top:0;
left:0;
right:0;
bottom:0;
z-index:99;
animation:remove 0s 0.3s forwards;
}
#keyframes remove {
to {
top:100%;
}
}
<div class="button">Some text</div>

Is there a way to inherit CSS properties from the parent while modifing some?

For example, CSS properites with multiple inputs:
Is something like this possible?
.button:active {
background-color: rgba(inherit, inherit, inherit, 0.5);
}
Is the only way to do this with a scripted-css like LESS?
You can achieve an answer to the example given by tackling the problem slightly differently. By putting the background colour on a pseudo element with a z-index of -1 so that it sits behind the content (which is given a z-index of 1), and then changing just the opacity... you've achieved what you wanted above without any LESS.
See this fiddle: https://jsfiddle.net/3uopd059/
.button {
padding:1em;
position:relative;
float:left;
color:#000;
z-index:1;
}
.button::after {
content:"";
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
background-color: grey;
z-index:-1;
}
.button:active::after {
opacity:0.5;
}
Of course, if you wanted to change each of the colours independently then you'd need to use another method.
After giving it some thought, here's a workaround that would achieve what you want without anything else but what you gracefully called vanilla CSS. Passing opacity (along with background color) to a pseudo element, absolutely positioned:
#import url('https://fonts.googleapis.com/css?family=Shadows+Into+Light');
button {
font-family: 'Shadows Into Light', cursive;
position: relative;
font-size: 2rem;
color: white;
margin: 1rem;
min-width: 15rem;
background-color: transparent;
-webkit-appearance: none;
-moz-appearance: none;
border: none;
cursor: pointer;
}
button>span {
position: relative;
z-index: 1;
}
button::before {
content: '';
display: block;
position: absolute;
top: 0; left:0;
width: 100%;
height: 100%;
opacity: 1;
transition: opacity .3s cubic-bezier(.4,0,.2,1);
z-index: 0;
background-color: #bada55;
border-radius: .4rem;
}
button[orange]:before {
background-color: #f50;
}
button:hover::before {
opacity:.65; /* <-- the juice is here */
}
/* don't mind the below, i'm just playing */
body {
margin: 0; padding: 0;
}
center-me-please {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
background: transparent url(http://lorempixel.com/g/1200/800/fashion) no-repeat 50% 50% /cover;
}
<center-me-please>
<button><span>#bada55</span></button>
<button orange><span>not so #bada55</span></button>

Animation not working both on and off hover

My animation does not seem to want to go both on and off the hover. I have tried putting the animation line on the LI:before itself and swapping the 0% and 100% but then nothing happens at all. I've been messing around with it for hours to no avail.
EDIT: Updated link, code
JSFiddle
ul {
display: flex;
flex-direction: row;
align-items: center;
list-style-type: none;
background-color: $base-gray-t;
margin: 1em;
padding: .25em 0 0 0;
height: 3em;
border-bottom: 0.375em solid $secondary-color;
overflow: hidden;
box-shadow: .05em .05em 1em 0;
}
li {
position: relative;
color: $base-gray-light;
padding: 0.40em;
font-size: 1.5em;
font-family: 'Montserrat', sans-serif;
cursor: pointer;
z-index: 2;
}
li:not(.active):not(:first-child):before {
content: '';
display: block;
position: absolute;
bottom: .01em;
width: 100%;
height: 2em;
margin-left: -.4em;
border-radius: .25em .25em 0 0;
z-index: -1;
}
li:hover:before {
background: $primary-color;
animation: splash .3s ease;
bottom: .01em
}
#keyframes splash {
0% {
bottom: -2em;
border-radius: 100%;
}
100% {
bottom: .01em;
}
}
If you are trying to complete the animation which you created on hover then for that add forwards along-with your animation properties as below,
li:hover:before {
background: $primary-color;
animation: splash .3s ease forwards;
bottom: .01em
}
Check this working jsfiddle link.
The transition method is much less involved and has less scope for problems so i edited your fiddle to use that instead:
https://jsfiddle.net/6t8xLssv/1/
I simply transitioned the :before element on hover, except in the case of the active li.
li:before{
content:'';
display:inline-block;
position:absolute;
bottom:0;
right:0;
left:0;
height:0;
transition:height 0.2s linear;
background:pink;
border-radius:5px 5px 0 0;
z-index:-1;
}
li:hover:before{
transition:height 0.2s linear;
height: 2em;
}
li.active:before{
display:none;
}
I hope this helps

CSS animation keyframes with display none works to fade in, but not fade out

I have an element which has display none on start. When i add a class to it i want it to fade in, using CSS.
I found this tutorial to use keyframes which is working nice for fade in. But if i want to fade out the same way, the element gets hidden immediately with no animation.
Basically it looks like this:
.box {
display: none;
opacity: 0;
animation: FadeOut 1s ease-in-out;
&.active {
display: block;
opacity: 1;
animation: FadeIn 1s ease-in-out;
}
}
Here is an "working" example:
http://codepen.io/MickL/pen/NAopXN
Trying to animate the display:none is the root of your problem. The confusion for why the fade-in works and the fade-out doesn't comes from the combination of using both display and opacity.
The display property is only being dictated by whether .active is applied; the animations aren't actually changing it, whereas the opacity is animated as expected. On the fade-in, this means that you immediately show your element, which then transitions from transparent to opaque. On the fade-out, this means that you immediately hide your element, which then transitions from opaque to transparent while hidden.
There are a couple different ways you could solve this, but it sort of depends on the context. For example, you could leave it as a block element and use the height property to make it collapse:
$('button').on('click', function(e) {
e.preventDefault();
$(this).siblings('.box').toggleClass('active');
})
#import "bourbon";
* {
box-sizing: border-box;
text-align: center;
}
button {
margin: 30px 0;
border: 1px solid #ccc;
text-align: center;
padding: 1em;
background: none;
box-shadow: none;
}
.box {
margin: 0 auto;
width: 80%;
height: 0;
display: block;
line-height: 100px;
background: #ccc;
border: 1px solid #444;
text-align: center;
opacity: 0;
animation: FadeOut 1s ease-in-out;
}
.box.active {
display: block;
height: initial;
opacity: 1;
animation: FadeIn 1s ease-in-out;
}
#keyframes FadeIn {
0% {
opacity: 0;
height: initial;
}
100% {
opacity: 1;
height: initial;
}
}
#keyframes FadeOut {
0% {
opacity: 1;
height: initial;
}
99% {
opacity: 0;
height: initial;
}
100% {
height: 0;
opacity: 0;
height: 0;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col">
<button class="toggle-good">Toggle display</button>
<p class="box good">I move nicely!</p>
<p>Extra paragraph to show collapse</p>
</div>
You can't animate or transition the display property.
Note: That's not to say you can't use it in keyframe animation but that's not the same as actually animating it.
The reason why your Codepen demo doesn't work as intended is because the .active class is being removed instantly so the animation out has no time to fire and the default display:none is now applied immediately.
Since you are using Jquery anyway, there is a built in function fadeToggle which will do what you want.
$('button').on('click', function(e) {
e.preventDefault();
$(this).siblings('.box').fadeToggle(500);
})
* {
box-sizing: border-box;
text-align: center;
}
button {
margin: 30px 0;
border: 1px solid #ccc;
text-align: center;
padding: 1em;
background: none;
box-shadow: none;
}
.box {
margin: 0 auto;
width: 80%;
display: none;
line-height: 100px;
background: #ccc;
border: 1px solid #444;
text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col">
<button class="toggle-good">Toggle display</button>
<p class="box good">I move nicely!</p>
</div>

How to get text to appear cleanly after widening div through transition in CSS?

Here you can see my issue. I assume it has to do with the block and inline-block. I want to cleanly make the text appear when hovering over the area. Preferably all in CSS. If anyone can point me in the right direction, that'd be amazing. Thank you!
HTML
<div class="contact-icon icongrow" id="github">
<span class="fa fa-github icon"></span>
<span class="contact-icon-text">#username</span>
</div>
CSS
#github {
border-radius: 15px 10px;
padding: 8px 5px 5px 8px;
background: #000000;
color: #FFFFFF;
}
.icon {
float:none;
}
.icongrow {
font-size:24px;
width: 24px;
transition:width 1s;
display: block;
}
.icongrow:hover {
font-size: 28px;
width: 300px;
}
.icongrow:hover .contact-icon-text {
display: inline-block;
}
.contact-icon-text {
display: none;
}
https://jsfiddle.net/sfpfka64/
Add white-space: nowrap to .icongrow
.icongrow {
font-size:24px;
width: 24px;
transition:width 1s;
display: block;
white-space: nowrap;
}
and add an opacity transition to contact-icon-text :
.icongrow:hover .contact-icon-text {
opacity: 1;
}
.contact-icon-text {
opacity: 0;
display:inline-block;
transition: all 0.5s;
}
Also make the font-size on hover same as the initial font-size to provide more smoothness :
.icongrow:hover {
font-size: 24px;
width: 300px;
}
Snippet
#github {
border-radius: 15px 10px;
padding: 8px 5px 5px 8px;
background: #000000;
color: #FFFFFF;
}
.icon {
float:none;
}
.icongrow {
font-size:24px;
width: 24px;
transition:width 1s;
display: block;
white-space: nowrap;
}
.icongrow:hover {
font-size: 24px;
width: 300px;
}
.icongrow:hover .contact-icon-text {
opacity: 1;
}
.contact-icon-text {
opacity: 0;
display:inline-block;
transition: all 0.5s;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet"/>
<div class="contact-icon-container">
<div class="contact-icon icongrow" id="github">
<span class="fa fa-github icon"></span>
<span class="contact-icon-text">#username</span>
</div>
</div>
Just add the following rules to the .icongrow
white-space: nowrap;
overflow: hidden;
Working fiddle: https://jsfiddle.net/yvqga0ja/
An easy way would be to put your "contact-icon-text" as a position absolute, so that he would always be placed at the right place.
Demo
.contact-icon-container{
position:relative;
}
.contact-icon-text {
position: absolute;
top: 50%;
transform: translateY(-50%);
right: 10px;
opacity: 0;
}
.icongrow:hover .contact-icon-text {
opacity: 1;
transition: .3s ease-in;
You can add transition-delay in order to make your text appear a bit later, but you get the way I would do it :)

Resources