Is it possible to add a custom CSS shake animation to a Material MatDialog (e.g. if you entered wrong infos in a Form-Dialog)?
Since the dialog is instantiated via the MatDialog service, I can not add a ngClass (with a condition to add and remove the shake style) directly to the template.
Dialog creation looks like this:
constructor(private dialog: MatDialog) {
this.dialog.open(MyDialogComponent, {});
}
The shake style (in the MyDialog Component) like this:
:host#my-dialog {
&.shake-dialog {
animation: shake 0.82s cubic-bezier(.36,.07,.19,.97) both !important;
transform: translate3d(0, 0, 0)!important;
backface-visibility: hidden!important;
perspective: 1000px!important;
overflow: hidden !important;
#keyframes shake {
10%, 90% {
transform: translate3d(-1px, 0, 0)!important;
}
20%, 80% {
transform: translate3d(2px, 0, 0)!important;
}
30%, 50%, 70% {
transform: translate3d(-4px, 0, 0)!important;
}
40%, 60% {
transform: translate3d(4px, 0, 0)!important;
}
}
}
}
As you can see I tried to add/remove the shake animation via HostBinding. I managed to dynamically add/remove the shake-class this way to my dialog component, however, it takes no effect since all webkit styles are kind of overridden. Inspect in Chrome:
Even though I added an ID to increase the specificity, the shaking styles are not applied. Is this due to the nature of a MatDialog?
Is there any way, I could get this to work? Or did I maybe choose the wrong approach in the beginning?
You should declare the dialog to be in a custom module, where NoopAnimations is used (it disables animations).
Once the animations are disabled, you can override the overlay. Selector is
mat-dialog-container.mat-dialog-container {}
Related
I'm doing an animation with CSS variables, where a CSS variable value changes based on the page scroll. That variable is then used on animation with keyframes.
Originally it's updating correctly only on Firefox. Meanwhile, I found a way to make it work on Chrome too, by forcing a repaint, in this case, animate the color from #000 to #001.
/* --scale is dynamic changed by JS */
#keyframes move {
0% {
transform: translateX(0) scale(var(--scale));
color: #000;
}
100% {
transform: translateX(33vw) scale(1.5);
color: #001;
}
}
You can see a demo at codepen
I also ran into this issue and solved it by setting the element.style.animation attribute in JavaScript after calling setProperty(). It seems like #keyframes doesn't update after setting the animation in CSS.
This is a WebKit bug. I discovered this issue today by reading Safari Technology Preview 149 changelog, which means it should be fixed in Safari 16, to be released later this year.
Added support for custom properties in #keyframes rules (251733#main)
An alternative for those (like myself) who are using Styled Component's keyframes`` function, you can exchange the css variable for a prop by defining a function much like the following:
import styled, { Keyframes, keyframes } from 'styled-components';
const move = (scale: number): Keyframes => keyframes`
0% {
transform: translateX(0) scale(${scale});
color: #000;
}
100% {
transform: translateX(33vw) scale(1.5);
color: #001;
}
`
const AnimatedElement = styled.div<{ scale: number }>`
animation: ${(props) => move(props.scale)} 2s linear infinite;
`
I'm trying to create a 100% width and 100vh height div which would slide from out of the screen from above to down of page. At the 70% of animation I would like to make it at the bottom then at 90% move it 30px up and on 100% make it at the bottom again so it would look like it slide from up then bounce at the bottom.
I want this happen after clicking some DOM element in a grand grandchild so basically, I'll use eventBus and my "sliding div" will be in root component (app.vue) and in the child I'll emit:
showObserved() {
eventBus.$emit('showObserved');
}
here I'm emitting my custom event and then I'm watching this event in root component and changing boolean variable:
eventBus.$on('showObserved', async() => {
this.showObserved = true;
});
eventBus.$on('hideObserved', async() => {
this.showObserved = false;
});
and basing on this boolean I'm displaying my sliding div using v-if directive:
<transition name="slide-up" mode="out-in">
<observed-offer v-if="showObserved"></observed-offer>
</transition>
and here finally I use transition vue built-in component in order to make it sliding and this are my styles which should make effect that I explained in first parahraph:
/* slide from up to down */
.slide-up-leave-active {
animation: slide-out-up .4s linear;
}
.slide-up-enter-active {
animation: slide-in-up .4s linear forwards;
}
.slide-up-in-leave-active {
animation: slide-out-up .4s linear;
}
.slide-up-leave {
opacity: 1;
transform: translateY(-100%);
}
#keyframes slide-out-up {
0% {
transform: translateY(0);
}
70% {
transform: translateY(0);
}
90% {
transform: translateY(10%);
}
100% {
transform: translateY(0);
}
}
#keyframes slide-in-up {
0% {
transform: translateY(-100%);
}
70% {
transform: translateY(0);
}
90% {
transform: translateY(10%);
}
100% {
transform: translateY(0);
}
}
and this are style's of my sliding div:
.observed {
width: 100%;
height: 100vh;
z-index: 999999999;
overflow: hidden;
background-color: white;
}
But this doesn't work behavior is that it instantly makes entire page white and slide only content of div. I'm pretty sure that I just made wrong CSS styles I tried various other styles and it didn't work. Also maybe it has also something to do with height: 100vh.
I add demo repository. In this demo sliding in is almost working but slide out doesn't work at all. Installation of this project is simple just clone it then cd path/to/project then npm install && npm run dev or something similiar depending on OS.
In demo it's also not hovering entire page but it leave space for button as you'll see if you clone it.
Well actually I handle to fix transitions in demo repo now the only issue is that it doesn't veil/cover entire page but it leave space for root content. Pull repo again to see that.
Issue was that I was using bad transition styles and that I didn't have fixed position with top: 0 left: 0 on my panel component. After fixing that it's working correctly as you can inspect in demo repository.
Sorry for wasting time for issue that I fixed myself but it was much harder to troubleshoot in origin big project. When I created this demo repo it became so easy.
This is how it was done in Bootstrap 3:
.modal.fade .modal-dialog {
-webkit-transform: translate3d(0, -25%, 0);
transform: translate3d(0, -25%, 0);
}
Or something like this would have worked as well:
.modal.fade .modal-dialog {
transform: translate3d(0, -25%, 0);
}
.modal.in .modal-dialog {
transform: translate3d(0, 0, 0);
}
The magic obviously happened in the modal classes with the transform property. But this does not work in Bootstrap 4. I am specifically using Bootstrap v4.0.0-alpha.5. What changes do I need to make to achieve the same effect?
Demo url - https://jsfiddle.net/qww47vfn/
Found it, apply the following CSS:
.modal.fade .modal-dialog {
-webkit-transform: translate(0,25%);
-ms-transform: translate(0,25%);
-o-transform: translate(0,25%);
transform: translate(0,25%);
}
I've inverted the transform origin, instead of -25%, it's now 25% (effectively making it fade in from below). Adjust the amount to adjust the initial fade in position.
What changed?
Instead of translate3d the property translate is now being used, so changing the original values won't matter since the model listens to the new properties now.
Side note:
This doesn't work when you implement it as a new rule for some reason, I don't have a local version of bootstrap, but changing it inside the DevTools solved it for me. I suppose you need to overwrite the initial code to change it.
I am attempting to make a type of CSS only slide transition from one content section to another. In order to do so in an interesting way, I use CSS's perspective and rotateX to in essence lay down the page content. I then am trying to slide the content out towards the bottom of the screen using translateY
Separately, both the translateY and the rotateX work perfectly, no matter what the perspective is. However, when combined, it only works with certain perspectives based on the window size and rotateY value
In this jsFiddle it works as I would like it to in the window sizes I have tried. The problem is that I would like the perspective value to be lower, around 250px, but I cannot do so without breaking the animation.
I tried using a higher rotateY degree instead of making the perspective lower but the same issue occurs
#keyframes slide {
0% { transform: perspective(450px); }
25% { transform: perspective(450px) rotateX(30deg); }
50%,100% { transform: perspective(450px) rotateX(30deg) translateY(100%); }
}
I have tested this on CSS Deck and jsFiddle both in FireFox and Chrome and it seems to be a consistent issue
Can anyone provide me with a reason why this is happening and offer a work around?
Try setting the perspective as a separate rule on a parent element (as opposed to being part of the transform in the animation).
.parent {
perspective: 250px;
}
#keyframes slide {
25% { transform: rotateX(30deg); }
50%, 100% { transform: rotateX(30deg) translateY(100%); }
}
Updated fiddle: http://jsfiddle.net/myajouri/DYpnU/
My reasoning:
The perspective does not change during the animation so there's no point in having it as part of the animation.
Since your elements occupy 100% of the parent's area, setting the perspective on the parent should produce the same result as setting it on the elements themselves (inside transform).
It seems to solve your problem (see fiddle above).
UPDATE: after more experimentation, I found that explicitly setting the translateY(0) initial value in the animation would solve the issue as well.
#keyframes slide {
0% { transform: perspective(150px); }
25% { transform: perspective(150px) rotateX(30deg) translateY(0); }
50%, 100% { transform: perspective(150px) rotateX(30deg) translateY(100%); }
}
Updated fiddle: http://jsfiddle.net/myajouri/YJS3v/
Only a slight improvement over myajouri answer.
At leats in Chrome, you can write
#-webkit-keyframes slide {
0% { -webkit-transform: perspective(50vh); }
10%,15% { -webkit-transform: perspective(50vh) rotateX(30deg) translateY(0%); }
50%,100% { -webkit-transform: perspective(50vh) rotateX(30deg) translateY(100%); }
}
Setting the perspective to the viewport height should make it more responsive that your current setting
demo
(Untested in other browsers)
Is it possible to turn off the animation for the modal directive in angular-ui? http://angular-ui.github.io/bootstrap/
Can't find any in the options. Should I modify the source? Or is there any best practice when you want to customize?
Currently, the bootstrap classes are embedded in the directive and need to be overridden. If you want to prevent that vertical 'drift' into position of the modal window, place the following 2 classes in your css :
.modal.fade {
opacity: 1;
}
.modal.fade .modal-dialog, .modal.in .modal-dialog {
-webkit-transform: translate(0, 0);
-ms-transform: translate(0, 0);
transform: translate(0, 0);
}
What you would be accomplishing here is the negation of the existing translations. Not ideal, however will do the trick.
animation (Type: boolean, Default: true) - Set to false to disable animations on new modal/backdrop. Does not toggle animations for modals/backdrops that are already displayed.
var modalInstance = $uibModal.open({
animation: false
An easy way to turn off the animation is to add !important styles to the modal.
For all Modals
You can do that globally for all the modals with this CSS class (put it anywhere in your css):
.modal {
top: 25% !important;
opacity: 1 !important;
}
It will eliminate the "slide from top" animation and also the opacity animation. Personally I prefer to only eliminate the first and use only top: 25% !important;
You can also eliminate the backdrop animation globally using this class (put it anywhere in your css):
.modal-backdrop {
opacity: 0.8 !important;
}
For a Specific modal
You can eliminate the animations of a specific modal using the windowClass param.
.no-animation-modal {
top: 25% !important;
opacity: 1 !important;
}
Using windowClass:
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: ModalInstanceCtrl,
windowClass: 'no-animation-modal'
});
Don't have a full answer, but I'm having a similar issue and thought I'd chime in. I know that this used to be possible in angular-ui/bootstrap 0.5. There might be breaking changes in 0.6, and I'm trying to find an answer, but the documentation is pretty lacking.
Here is the example given in 0.5. Notice you can set options like backdropFade but I can't find the equivalent in 0.6. Might have something to do with removing $dialogProvider.
The below is working well for me, whatever the animation: false or animation: true:
<style>
.modal.fade {
opacity: 1;
}
.modal.fade .modal-dialog, .modal.in .modal-dialog {
-webkit-transform: translate(0, 0);
-ms-transform: translate(0, 0);
transform: translate(0, 0);
}
.modal-backdrop {
opacity: 0.8 !important;
}
</style>