CSS animation moving and changing color - css

I am not that familiar with CSS animations. My client want to achieve the following result when hovering the contact button:
so to be clear:
the square's move from left to right and vice versa
when the square moves, the line underneath it changes color
the top image it the start state, the middle is during the effect (50%) and the bottom image is the end stage.
Is this achievable with only CSS or do I need JS as well?
How would I approach this?

I created a quick and dirty JSFiddle here: https://jsfiddle.net/x0b397pb/
As you can see, it is possible with just CSS. In this example I used pseudo elements (::before and ::after) to create most of the elements.
You mentioned "Im not that familiar with CSS animations". For this I used transitions.
transition: left 1000ms, right 1000ms, box-shadow 1000ms;
Each comma separated element is a value that will transition between 2 points. This transition happens on a change of the div, this can be on a hover, but also when applying another div (Through JS).
To created the effect of the lines gradually shifting in color I used another element that slides on top of the original two lines. The new lines originally have 0 width, but on hover they gain 100% width. With a transition transition: width 1000ms; this happens gradually.
Try not to use my code as your final example, as it is somewhat ugly. But I hope it gets the point across.

Here is a small demonstration of css transition:
Consider this HTML:
<div class="container">
<div class="box"></div>
</div>
With this CSS:
.container {
position: relative;
width: 400px;
height: 400px;
border: solid 1px black;
}
.box {
position: absolute;
width: 40px;
height: 40px;
top: 10px;
left: 10px;
background-color: red;
transition: all 1s;
}
.container:hover {
border-color: blue;
.box {
top: 200px;
left: 200px;
width: 160px;
height: 160px;
background-color: blue;
}
}
Or, check it on JsFiddle: https://jsfiddle.net/ronency/75ozjq3s/

.box {
background: linear-gradient(80deg, #f3efef, #90009f, #01060d);
background-size: 600% 600%;
animation: AnimationName 29s ease infinite;
}
#keyframes AnimationName {
0%{background-position:0% 51%}
50%{background-position:100% 50%}
100%{background-position:0% 51%}
}

Related

Is there any way to implement a box animation in CSS?

While doing a project, I need to draw a box which plays animation within 2 second and will move one corner to another.How can I do It in a easy way?
There are several ways of doing animations and it will be worth reading up on both CSS transition and CSS animation.
Just to start off here is a very simple example. A red square sits in a container whose dimensions are known. The square has a transition of 2s set on all - which means on any animatable CSS property.
When you click the button it has a class added or removed (using toggle) and in this the square is translated to the bottom of the container (or back to its initial position when the class is removed).
.container {
border: solid 1px;
width: 250px;
height: 100px;
}
.box {
width: 10px;
height: 10px;
background: red;
position: absolute;
transition: all 2s;
display: inline-block;
}
.box.move {
transform: translate(240px, 90px)
}
<div class="container">
<div class="box"></div>
</div>
<button onclick="document.querySelector('.box').classList.toggle('move');">click me</button>`enter code here`

Interruption of a CSS transition does not work for same attribute value

I've answered a question on how to start an animation when hovering the child element and then preserve the applied style until un-hovering the parent. However, I discovered a behaviour in my proposed solution that I can't explain and that I would like to understand. Reading the relevant parts of the specification didn't help me.
Here is a minimal example showing the expected behaviour. It works but the properties with comments behind have to be different for some reasons. Otherwise (e.g. both having 10px as value) un-hovering of the parent won't do anything to the width of the child. JSFiddle.
.parent {
border: 1px solid orange;
padding: 20px;
width: 400px;
}
.parent .child {
display: inline-block;
height: 40px;
background: blue;
transition: width 0.5s ease 600s;
width: 10px; /* why does this value has to be different ... */
/* Hint:
If you hover the child until it reaches the 100px, then hover the
parent without leaving the parent and keeping that hover for the
transition-delay (600s) the width will become 10px as defined here.
And removing this width property here won't make the transition work
at all. */
}
.parent .child:hover {
transition-delay: 0s;
width: 100px;
}
.parent:not(:hover) .child {
transition: width 0.5s ease 0s;
width: 11px; /* ... from this value? */
/* Hint:
This is used as some kind of interruption of the 600s
transition-delay in order to achieve the parent un-hover effect.
I would like to set the width to 10px here as well but this will
result in having no effect on the width of the enlarged child when
un-hovering the parent. */
}
<div class="parent">
<div class="child">
</div>
</div>
A small observation
Relevant browsers are Firefox and Chrome. In Firefox the following works:
.parent .child {
/* ... */
transition: width 0.5s ease 600s;
width: calc(10px);
}
.parent:not(:hover) .child {
transition: width 0.5s ease 0s;
width: 10px;
}
Question
Why do the values of the width property have to differ in order to make the un-hover effect work like expected?
Sorry - I missunderstood what was happening in yopur question.
I have done a new snippet with a simplified case:
#a, #b {
width: 200px;
height: 100px;
border: solid 1px black;
display: inline-block;
background-color: lightgreen;
margin-top: 50px;
}
#a {
margin-right: -5px;
}
#container {
width: 400px;
height: 50px;
border: solid 1px black;
margin: 0px;
}
#child {
width: 0px;
height: 50px;
position: absolute;
background-color: blue;
}
#child {
transition: width 0.5s;
width: 400px;
}
#a:hover ~ #container #child {
transition: width 10s;
width: 0px;
}
#b:hover ~ #container #child {
transition: width 0.5s;
width: 0px;
}
<div id="a">A</div>
<div id="b">B</div>
<div id="container">
<div id="child"></div>
</div>
Hover on A, and then (before the transition ends) hover B. You will see the same behaviour: the transition goes on unchanged.
The reason is that when hovering a, the width (as a property of the element) is 0px. (Not the calculated width, that is being transitioned).
So, when you hover on B, and the new style of 0px will not trigger a property a change, and hende will not start a new transition.
Old answer
The key part of the specs is this one: (emphasis mine)
reversing transitions spec
To meet this expectation, when a transition is started for a property on an element (henceforth, the new transition) that has a currently-running transition whose reversing-adjusted start value is the same as the end value of the new transition (henceforth, the old transition), implementations must cancel the old transition [...] and adjust the new transition as follows (prior to following the rules for computing the combined duration, start time, and end time): [...]
So, when the new width is the same as the old one, it's not really that the un-hover has no effect, it's that the effect is very slow (600s) as the browser is reversing the transition that was running.
To prove this, I have set a snippet where the width in the last rule is the same (10px).
And the delay is set to 10 seconds.
Hover the child, and unhover it leaving the parent. You will see that 10 seconds later, the child width is modified.
.parent {
border: 1px solid orange;
padding: 20px;
width: 400px;
}
.parent .child {
display: inline-block;
height: 40px;
background: blue;
transition: width 0.5s ease 10s;
width: 10px;
}
.parent .child:hover {
transition-delay: 0s;
width: 100px;
}
.parent:not(:hover) .child {
transition: width 0.5s ease 0s;
width: 10px;
<div class="parent">
<div class="child">
</div>
</div>
Firstly, I change the transition-delay of .parent .child:
.parent .child{
transition: width 0.5s ease 6s;
}
It works and nothing is wrong. But wait a minute!
.parent:not(:hover) .child{
transition: width .5s ease 0s;
width: 10px;
}
Why doesn't the property work if the width property is 10px?
In fact, the code above is equivalent to:
.parent:not(:hover) .child{
transition: width .5s ease 0s;
}
According to the spec provided by W3,
when a transition is started for a property on an element (henceforth, the new transition) that has a currently-running transition whose reversing-adjusted start value is the same as the end value of the new transition (henceforth, the old transition), implementations must cancel the old transition link to definition above and adjust the new transition as follows (prior to following the rules for computing the combined duration, start time, and end time):
So it seems like that the transition-delay property should be reset to 0s. However, I think it's something mentioned by W3C called style change event:
Since this specification does not define when a style change event occurs, and thus what changes to computed values are considered simultaneous, authors should be aware that changing any of the transition properties a small amount of time after making a change that might transition can result in behavior that varies between implementations, since the changes might be considered simultaneous in some implementations but not others.
Since the end value of the "new" transition we define in .parent:not(:hover) .child is the same as that in .parent .child, the so-called "new" transition is not regarded as a new transition by the browser. In this case, the transition-delay property won't be reset of course.
However, if we change width of .parent:not(:hover) .child, that is, change the end value of the transition, we are thought to have defined a new transition and according to the spec mentioned above, the transition-delay property is reset to 0s.

triggering a transition of a element when hovered on another element

i have a div which is box and a 'p' element whose opacity is set to 0. when i hover over the div i want the 'p' elements opacity to change to 1. i have the following code . its looks proper to me but its not working. i could not figure out the problem with it. can some one help me. thanks in advance.
HTML:
<p class="se">Hover over the div element below</p>
<div class="box"></div>
css:
.se{
position: relative;
color:red;
opacity:0;
}
.se{
-webkit-transition: opacity 2s;
transition: opacity 2s;
}
.box{
position: relative;
left: 400px;
width: 100px;
height: 100px;
background: red;
}
box:hover + .se{
opacity:0;
}
jsFiddle http://jsfiddle.net/2f1k5yq4/
CSS selector +
Any element that is the next sibling of a previous element (that is: the
next child of the same parent)
.box {
position: relative;
left: 400px;
width: 100px;
height: 100px;
background: red;
}
.se {
color: red;
opacity: 0;
position: relative;
transition: 1s linear;
}
.box:hover + .se {
opacity: 1;
}
<div class="parent">
<div class="child">
<div class="box"></div>
<p class="se">Hover over the div element below</p>
</div>
</div>
This is actually a kind of annoying problem with just CSS. I'd prefer using Javascript, especially if you already have jQuery loaded into your site.
But, that said, this can sort of be done in CSS. I'm going to assume you just want to show/hide an element, so I'll use display for the example rather than opacity, so modify as needed to use a transition.
The first problem you have is that you box:hover rather than .box.hover. The second problem is a bit more annoying. Abhitalks is correct that +, the adjacent sibling selector, only selects the next sibling, so you can't have the text above the div that will show it. If, however, you switch the order, moving the div above the text, it works. You could use some clever positioning, floating, etc. in order to make the order of their appearance different than their order in the markup, if you wanted.
.se{
display: none
}
.box{
width: 100px;
height: 100px;
background: red;
}
.box:hover + .se{
display: block;
}
<div class="box"></div>
<p class="se">Hover over the div element below</p>

overflow:hidden ignored with border-radius and CSS transforms (webkit only)

I want to have a square image inside a circle.
When the user hovers over the image, the image should scale (zoom in).
The circle should remain the same size.
Only during the CSS transition, the square image overlaps the circle (as if overflow:hidden weren't there at all).
Here's a demo with the weird behavior in Chrome and Safari:
http://codepen.io/jshawl/full/flbau
Working ok in firefox.
You need to add this code to the parent of your img :
position:relative;
z-index:1;
Example here : http://codepen.io/DavidN/pen/dIzJK
I removed some superfluous markup (the circle and square containers... only needs one) and styled the img itself:
#wrapper {
width: 500px;
height: 500px;
border-radius: 50%;
overflow: hidden;
-webkit-mask-image: -webkit-radial-gradient(circle, white, black);
}
#test {
width: 100%;
height: 100%;
transition: all 2s linear;
}
#test:hover {
transform: scale(1.2);
}
<div id="wrapper">
<img src="http://rack.3.mshcdn.com/media/ZgkyMDEzLzA1LzA4L2JlL2JhYmllc193aXRoLjA5NGNjLnBuZwpwCXRodW1iCTg1MHg1OTA-CmUJanBn/8f195417/e44/babies_with_swagg.jpg" id="test">
</div>
Add this code to your parent div and solve problem :
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
It appears as though you were styling one too many elements! I've created a fork here
I edited some of your SASS code to utilize the compass library and make better use of the transition and transform properties which can be seen here:
body { padding: 3em; }
.circle {
height: 500px;
width: 500px;
border: 1px solid black;
#include border-radius(500px);
overflow: hidden;
}
.circle img {
height: 500px;
width: 500px;
#include transition(all 0.3s ease);
&:hover { #include transform(scale(1.1)); }
}
Hopefully this helps! Just think of the circle element as the parent container which has general information about the space (e.g. 500px wide and 500px tall). The image itself has a rounded border of 500px. This is the element you want to edit! You can scale and transform this element here without interacting with the parent circle container. Reference compass for additional information about using the library! Good luck!

Slide down div on click Pure CSS?

I found this post How to create sliding DIV on click?
But all the answers are Jquery methods. Is there any way to create this with PURE CSS?
I have a couple other things in mind as well...
What can I add to make the slide down div stay put when scrolling
Change the link that triggers the animation to "Close" in order to make the div slide back up
Here is a link to the example in that post//
http://shutterbugtheme.tumblr.com/
I've also tried googling but the only results are jquery methods...
It can be done, although it's a little bit of a hack. The two elements that retain state (referred to in CSS as :checked) are the checkbox and radio button element. So if you associate a checkbox with a label by using a for attribute and add a div, you can get a result by reading the status of the (hidden) button:
<div class=window>
<input type=checkbox class=toggle id=punch>
<label for=punch>Punch It, Chewie<label>
<div><p>Here’s my content. Beep Boop Blurp.</p></div>
</div>
And the CSS:
input.toggle { display: none; }
input.toggle ~ div { height: 0px; margin: .2rem; overflow: hidden; }
input.toggle:checked ~ div { height: 180px; }
This is impossible in pure CSS to recognise a click. You can do it with :hover and a transition, but that is as close as you're going to get without javascript.
.hover
{
cursor: pointer;
position: relative;
z-index: 1;
}
.slide
{
position: absolute;
top: 0;
z-index: -1;
-webkit-transition: top 1s;
-moz-transition: top 1s;
}
.hover:hover + .slide
{
top: 50px;
}
http://jsfiddle.net/Kyle_/MaMu9/1/
Be aware though that transitions are CSS3 and will not work in IE<9 and older versions of better browsers.
Edit: after another answer was posted using the :focus property in CSS: it is possible with one caveat: you have to click outside of the element that makes it slide down to make it slide up, otherwise it works fine.
Be aware that the element must have tabindex='1' (or any number that makes sense depending on where the element is in the document) for this to work.
.hover:focus + .slide
{
top: 50px;
-webkit-transition: top 1s;
}
http://jsfiddle.net/Kyle_Sevenoaks/MaMu9/1/
You can recognize a 'focus' event on an element and act upon it using a CSS transition.
Here's an example which will move a div 50px down when clicked
Markup
<div tabindex='1' id='box'></div>​
CSS
#box {
background-color:#3a6d90;
width:100px; height:100px;
transition: margin-top 2s;
-moz-transition: margin-top 2s; /* Firefox 4 */
-webkit-transition: margin-top 2s; /* Safari and Chrome */
-o-transition: margin-top 2s; /* Opera */
}
#box:focus {
margin-top:50px;
outline:0;
}
Working example: http://jsfiddle.net/NBHeJ/
This is a good example of how to get started. You can see at the bottom, they post the source for the animate function they use, although this is javascript.
sliding-js-generic
If you want pure css, I'd use ws3schools has been excellent resource for many years, though be aware that a lot depends on browser support as to whether the effect you want will work or not.
w3schools-css
Basic structure to make the effect they have, you just need to work along the lines of two divs within the body, at the top hidden and the container visible, and run the animation of the hidden div to display pushing the other div down, keeping them both inline.
<body>
<div id="hidden-div"></div>
<div id="main-content-div"></div>
</body>
This can be done using the target pseudo class to detect the click.
Set the button href to the id of the sliding div.
The slide down can then be done by setting the height of the sliding div on the slidingDiv :target class using a css3 transition on the height.
I don't think there's a way for the original button to change its href to close the sliding div using pure css, however you could always add a close button on the sliding div to close it.
This close button works by adding the same transition on the sliding div class.
Here is a WORKING DEMO.
Enjoy.
Run This Code.
input {
display: none;
}
label {
cursor: pointer;
display: inline-block;
padding: 10px 20px;
border: 1px solid;
border-radius: 4px;
background: tomato;
color: #FFF;
font-family: arial;
-webkit-transition: background-color 0.1s, color 0.1s;
}
label:hover {
background: #blue;
color: #blue;
}
.test {
-webkit-transition: height .3s ease;
height: 0;
overflow: hidden;
width: 200px;
background: tomato;
margin-top: 10px;
color: #FFF;
}
input:checked + .test {
height: 100px;
}
<label for="check">Click me</label>
<input id="check" type="checkbox">
<div class="test">
<p>I am some hidden text</p>
</div>
Easy:
.contents {
background: yellow;
color: rgba(0, 0, 0, .8);
padding: 20px;
margin:0;
}
.slide-up, .slide-down {
overflow:hidden
}
.slide-up > div, .slide-down > div {
margin-top: -25%;
transition: margin-top 0.4s ease-in-out;
}
.slide-down > div {
margin-top: 0;
}
Working example:
https://jsfiddle.net/webarthur/3ep33h5s/
Another way to do the same thing:
.contents {
background: yellow;
color: rgba(0, 0, 0, .8);
padding: 20px;
margin:0;
}
.slide-up, .slide-down {
overflow:hidden;
}
.slide-up > div, .slide-down > div {
transform: translateY(-100%);
transition: .4s ease-in-out;
}
.slide-down > div {
transform: translateY(0);
}
Working example: https://jsfiddle.net/webarthur/3ep33h5s/1/

Resources