I am kinda new to web development, and I would like to create a graphic button with a highlight pulsed effect, let me explain :
The button is built with 2 layers, the first is the default state always displayed, and the second layer is the highlighted state (white) displayed only when the button is clicked or touched (opacity of this layer is 1 when displayed, 0 when hidden).
My problem is that I would like the opacity of the highlight to go from 0 to 1 regardless the duration of the click or the touch event. The transition back to opacity 0 value should occur only when value 1 has been reached, that means that release events (mouseup or touchend) shouldn't be triggered until the opacity of the hightlight layer has reached 1.
I am using Compass (scss) and jquery mobile with phonegap encapsulation.
I have coded a version which works, but doesn't meet my goal :
The transition to highlighted state is stopped as soon as I release the button (for instance, if I make a very quick touch, even with a 0.2s transition on opacity, the highlighted state is not visible, though the touchend event is triggered... (the transition returns to 0 before reaching 1)...
The whole code maybe not so clean, but I am trying to learn :)
Any clue or advice is welcome!
the HTML code looks like this :
<div class=btn-test>
<span>
<a class=btn-a href=#>
</a>
</span>
</div
the SCSS looks like this :
#import "compass/reset";
#import "compass/css3";
.btn-test {
span {
#include background-image(image-url("foo.png"));
background-position: 0px 0px;
width: 72px;
height: 70px;
display: inline-block;
}
a {
#include background-image(image-url("foo.png"));
background-position: 0 71px;
#include transition-property(opacity);
#include transition-duration(0.2s);
#include transition-timing-function(ease);
width: 72px;
height: 70px;
display: inline-block;
-webkit-touch-callout: none !important;
}
.btn-a {
opacity: 0;
}
.btn-a:active {
opacity: 1;
}
}
What you want is an animation, not a simple transition. You get cross browser animation in compass 0.13 alpha with gem install compass --pre
The solution would be to add keyframes for your different states :
#import "compass/css3/animation";
#include keyframes(flashButton){
0%{
opacity: 0;
}
50%{
opacity: 1;
}
100% {
opacity: 0;
}
}
.animate-button {
#include animate(flashButton 1s ease);
}
And then with a little bit of jQuery :
$('.btn-test').on('click', function(){
//reset state in case animation has already been played
$('.btn-test').removeClass('animate-button');
setTimeout(function(){$('.btn-test').addClass('animate-button')}, 1)
});
I didn't use it yet but you can also use https://github.com/ericam/compass-animate which is a compass port of the great css animations found here http://daneden.me/animate/
Related
TL;DR A css transition on opacity does not work immediately after display change, but works with setTimeout(.., 100). Why?
What do I want?
I want to flash a message for a couple of seconds and then fade it out. Seems pretty basic, right?
What do I have?
Well, here's a jsfiddle, but let me explain in detail.
Say I have a message block
<div id="message" class="message">
Here be dragons
</div>
Which starts hidden but opaque
.message {
opacity: 1;
display: none;
}
Once I've prepared my message I want to show it.
document.getElementById("message").style.display = "block"
Now I want the message to fade out so I added a simple transition on opacity.
.flash {
opacity: 0;
transition: opacity 2s ease-out 1s;
}
Which I apply with the following
document.getElementById("message").classList.add("flash")
What goes wrong?
The message div is shown but it stays invisible as the opacity: 0 immediately applies. Besides, the transitionend event is not firing, which makes me think the transition does not happen at all for some reason. Weird, right?
However, everything's fine once I add the timeout
document.getElementById("message").style.display = "block"
setTimeout(() => (document.getElementById("message").classList.add("flash")), 100)
That works but seems like a totally dirty hack. Why is it like this?
You can see this behaviour on jsfiddle with two buttons aptly named 'Working' and 'Not working';
There are two things that together cause this:
When items have display: none the opacity is ignored (as not relevant). And so when you apply display: block to them they render the provided opacity with the current value without any transition effect.
Changes you apply to the style attribute all apply together at the moment a paint (asynchronous) happens, and so the transition definition comes too late.
First, make sure to set the transition effect definition before the actual application of it, in the message CSS class.
I would then suggest using height instead of display to get the same effect. You would need to switch the border on and off also (through its width):
document.getElementById("working").addEventListener("click" , () => {
document.getElementById("message").classList.add("flash");
})
// reset
document.getElementById("message").addEventListener("transitionend" , () => {
document.getElementById("message").classList.remove("flash")
})
.message {
border: solid 0px;
background: grey;
opacity: 1;
transition: opacity 2s ease-out 1s;
overflow: hidden;
height: 0;
}
.flash {
height: 100%;
opacity: 0;
border-width: 1px
}
<div id="message" class="message">
Here be dragons
</div>
<button id="working"> Working </button>
Why it doesn't work is because you are applying display:block and opactiy: 0 at the same time. When you set the attribute display in css it ignores all transition, there has to be an event in between setting display and transitions. An alternative is using visibility:hidden and visibility:visible instead of display but note that this only hides the element and the element is still present in its position
I’m using SliceJack
FullPage.js fade effect code snippet (1st one) to get the transitions effects on my website, which works perfect and I’m happy with them on desktop (put them into my main css).
I want to disable the effects on smaller devices such as Ipad and mobile, so I can scroll default (normal) without transitions.
Only option for me to disable the effects is by removing the code snippet (1st one) but than I lose those effects on desktop aswell.
I have enabled responsivewidth at 976 pixels in jQuery.fullPage.js script.
Is it possible to empty those 3 classes I added in CSS (for transitions) on mobile and iPad?
/*Fade in effect & one pager*/
.fullpage-wrapper {
width: 100%!important;
transform: none!important;
}
.fp-section {
width: 100%!important;
position: absolute;
left: 0;
top: 0;
visibility: hidden;
opacity: 0;
z-index: 0;
transition: all .7s ease-in-out;
}
.fp-section.active {
visibility: visible;
opacity: 1;
z-index: 1;
}
/* Remove transition when website is still loading */
body {display:none}
body[class*="fp-viewing-"] {display:block}
If you are making use of fullPage.js and the fadingEffect extension, then you can make use of fullPage.js callbacks and functions to solve this in the proper way:
$('#fullpage').fullPage({
responsiveWidth: 976,
afterResponsive: function(isResponsive){
if(isResponsive){
$.fn.fullpage.fadingEffect.turnOff();
}
else{
$.fn.fullpage.fadingEffect.turnOn();
}
}
});
I have two elements, and the top one's visibility is controlled by a v-if on a simple boolean.
transition(name="fade")
#element1(v-if="showFirst")
p Foo
#element2
p Bar
The first element is wrapped in a <transition> tag, exactly as per the Vue documentation.
However, while this does create a fading animation, the rest of the content on the page still jumps very jarringly.
How can I create a transition that will also smoothly transform the position of any and all siblings that follow?
A fiddle demoing this issue.
You need to use a transition-group and key your dynamic div and static div
<transition-group name="fade">
<div v-if="switc" key="dynamic" class="animated">
...
</div>
<div key="main-content" class="animated">
...
</div>
</transition-group>
And use this css classes
.fade-enter,
.fade-leave-active {
opacity: 0;
transform: translateY(-10px);
}
.fade-leave-active {
position: absolute;
}
.animated {
transition: all 0.5s;
/*display: flex;*/
width: 100%;
}
The real trick is to change position to absolute when leaving, then any other content can take correct position.
To know more about how Vue animate things please see this FLIP explanation post
And please see this working fiddle
https://jsfiddle.net/bjfhth7c/4/
Edit
By mistake I did set display: flex; in .animated class, that was causing to every inner element to render in a strange way.
So now, I completely remove .animate class, and instead apply transition: all 0.5s and width:100% to every direct inner element of .wrapper
My final scss looks like this:
.wrapper {
display: flex;
flex-direction: column;
>* {
transition: all 0.5s;
width:100%;
};
}
.fade-enter,
.fade-leave-active {
opacity: 0;
transform: translateY(-10px);
}
.fade-leave-active {
position: absolute;
}
Flex layout is a extend subject, but in short for this particular case flex-direction: column is arranging elements one bellows previous one.
If one of those elements has absolute position will be ignored in flex layout so any other elements will be redistributed on available space.
Please see this guide about flexbox and last working fiddle hope it helps.
You can use a slideDown/slideUp animation instead. For achieve this you don't need to know a height of a sliding element, the principles of max-height transition explained there.
So, as a result it will cause animated moving of elements below target.
Check out my example based on your fiddle.
vue js provides different transition classes, you have to use those properly to smooth the transition, I have tried with your example in this fiddle with some CSS, have a look.
.fade-enter-active, .fade-leave-active {
transition: all .5s;
height: 100px;
opacity: 0.5;
}
.fade-enter, .fade-leave-to /* .fade-leave-active in <2.1.8 */ {
height: 0px;
opacity: 0;
}
Some details from documentation:
There are six classes applied for enter/leave transitions.
v-enter: Starting state for enter. Added before element is inserted, removed one frame after element is inserted.
v-enter-active: Active state for enter. Applied during the entire entering phase. Added before element is inserted, removed when transition/animation finishes. This class can be used to define the duration, delay and easing curve for the entering transition.
v-enter-to: Only available in versions >=2.1.8. Ending state for enter. Added one frame after element is inserted (at the same time v-enter is removed), removed when transition/animation finishes.
v-leave: Starting state for leave. Added immediately when a leaving transition is triggered, removed after one frame.
v-leave-active: Active state for leave. Applied during the entire leaving phase. Added immediately when leave transition is triggered, removed when the transition/animation finishes. This class can be used to define the duration, delay and easing curve for the leaving transition.
v-leave-to: Only available in versions >=2.1.8. Ending state for leave. Added one frame after a leaving transition is triggered (at the same time 7. v-leave is removed), removed when the transition/animation finishes.
You can as well use CSS animations where you can provide on different phases of transition what will be your css property to make your transitions more smooth, like following and demo fiddle:
.fade-enter-active {
animation: bounce-in .5s;
}
.fade-leave-active {
animation: bounce-out .5s;
}
#keyframes bounce-in {
0% {
height: 5px;
}
30% {
height: 30px;
}
50% {
height: 50px;
}
100% {
height: 100px;
}
}
#keyframes bounce-out {
0% {
height: 90px;
}
50% {
height: 50px;
}
100% {
height: 0px;
}
}
Before I say anything, I looked at about a dozen SO threads including this one which you'll see the code suggested in there in my JSBin as well: Why does this CSS transition event not fire when two classes are added?
The issue is that adding two classes back to back too fast results in no transition animation whatsoever.
I'm implementing this into a legacy JS custom right click menu and making it mobile friendly with just CSS by first applying the mobile styles with .mobile-menu then an animation class of .mobile-menu-show when they long press (since there's no right click mouse button).
The transitions don't work this way though. If I add .mobile-menu on page load it's fine, but I can't because I'm adding the mobile-menu class based on how the right click menu is triggered (long press == mobile styles, right click == normal styles)
Demo code: http://jsbin.com/maxuku/edit?html,css,output
==Edit==
Hopefully to clarify, I want the menu you see at the default to go hidden (translateY(100%)) then slide up from the bottom. If you use Slack, long press on a message. Or iPhone's had this same concept here where it would slide up:
please change css class as below
.context-menu {
position: fixed;
bottom: -100%;
left: 0;
right: 0;
z-index: 100;
-webkit-transition: all 0.25s; /* Safari */
transition: all 0.25s;
}
.mobile-menu {
background: #fff;
width: 100%;
box-sizing: border-box;
box-shadow: 0 0 5px rgba(0,0,0,0.5);
}
.mobile-menu-show {
bottom: 0;
}
You can refer to animation over here
https://plnkr.co/edit/t0EB5CiuwtbWHqWXvlvz?p=preview
I am not familiar with css or javascript and I am wondering how to have a notification highlight similar to the case when a person commented on a Facebook post, and upon clicking, you will be directed to the said comment with temporary highlight.
Thanks in advance
You can use the CSS3 animation property. Just make sure to add the -webkit- vendor prefix for it to work in all major browsers. The vendor prefixes you need for other CSS3 properties can be found at caniuse.com.
The trick is to add a special class to the element you want highlighted, and applying the animation to that class with CSS.
Try it:
.post{
padding: 1em;
margin: .2em;
background: #ffffff;
border: 1px solid #eceded;
}
.post.highlighted {
-webkit-animation: highlight 6s ease;
animation: highlight 6s ease;
}
#-webkit-keyframes highlight {
from { background: #ddddff }
to { background: #ffffff }
}
#keyframes highlight {
from { background: #ddddff }
to { background: #ffffff }
}
<p class="post">This is just a regular post</p>
<p class="post highlighted">But this one's new!</p>
It looks like you have a few problems you need to solve. I'll walk you through the logic behind each problem. Some of these problems already have solutions posted online, so in those cases I've linked you to the appropriate pages.
1) Respond to a click on an element
http://clubmate.fi/detect-click-with-pure-javascript/
2) Scroll to a specific part of the page
Smooth scroll to specific div on click
3) Highlight an element
This involves changing attributes of an html element, for example the background color. This can be done by changing the class with javascript, and using css to style the element differently when it has the right class
CSS:
.element {
background-color: #0000ff; /* A blue background by default */
}
.element.highlighted {
background-color: #ff0000; /* A red background when the element is highlighted */
}
JS:
document.getElementsByClassname('element')[0].setAttribute('class', 'element highlighted');
Now you just have to run that line of javascript at the appropriate time (after the scrolling has ended - step 2 should give insight on how to do this)
4) Remove the highlighting after a delay
Take advantage of javascript's setTimeout function to remove the highlight class after a delay:
JS:
setTimeout(function() {
document.getElementsByClassname('element')[0].setAttribute('class', 'element'); // Replace "element highlighted" with just "element"
}, 1000); // 1000 means a one-second delay