Vue js: how to load a css animation only on the first page load - vue.js

In the Home Page component, I've a <div> element with an animation, like this:
<div class="square">
//content
</div>
and in the CSS:
.square
height: 200px
width: 200px
margin: 0 auto
z-index: 0
position: absolute
top: 38vh
left: 43vw
margin-left:auto
margin-right:auto
animation-name: stretch
animation-duration: 0.3s
animation-timing-function: ease-out
animation-delay: 0
animation-direction: alternate
animation-fill-mode: forwards
animation-play-state: running
#keyframes stretch
from
transform: scale (1)
to
transform: scale(1.8)
It is a simple square that grows, with some other <div> elements inside.
Now, I would like to play the animation only on initial login and opening of app, not each time the view appears (like is working now).
Could you help me? Please, don't take anything for granted, because I am a beginner. Thank you in advance.

its simple. create a flag in the data of the vue property. you can call it animate. add a function that will turn it off after the login, somthing like:
data:{
animate:true
},
methods:{
turnOffAnimate:{
this.animate=false;
}
}
call this.turnOffAnimate when you want to turn off your animation. now, in your html div, bind the class in this way:
<div :class="{square : animate}">
//content
</div>
this condition means that your div will own square class only while animate flag is true. you can read more about class binding in vue.

Related

Append child to $slot.default

I have a component that I need display some custom modal on screen. I don't know where I should put this dialog content, so I did something like that:
<template>
<div class="ComponentItself">
<div v-show="false" ref="ModalContent">
Hello!
</div>
<button v-on:click="showModal">Show modal</button>
</div>
</template>
[...]
Note: I could not set the tag name of [ref=ModalContent] to template because the vue reserves this tag to another feature.
My idea is when I click on "show modal" it open creates an instance of another component (v-dialog) that I have created with the [ref=ModalContent] content (it should be compiled to support nested vue components).
import Dialog from './Dialog';
const DialogCtor = Vue.extend(Dialog);
const dialog = new DialogCtor({ propsData: {...} });
dialog['$slots'].default = [ this.$refs['templateNewFolder'].innerHTML ];
{something like document.body.appendChild(dialog.$el)}
This another component have a slot that could receives the HTML content to be displayed inside of that. And it just not works. The modal is displayed, but the slot content is undefined or the HTML content not parsed.
<div class="Dialog">
[...]
<slot></slot>
[...]
</div>
The current result is something like:
What I need:
I need to know if I am on the right way. I have about the component feature, but I could not identify or understand if it is/could resolve my problem;
What I could do to make it work;
Some similar project could help it, but I could not found anyone;
Maybe I could resolve my problem if is possible I just .appendChild() directly to $slot.default, but it is not possible;
It seems to me this might be a case of an XY problem.
What probably happens is that you do not need to manually fill $slot.default, but use your Dialog component a more standard way. Since there is little detail about the latter in your question, that component might also need some refactoring to fit this "standard way".
So a more standard approach would be to directly use your <custom-dialog> component in the template of your parent, instead of using a placeholder (the one you reference as ModalContent) that you have to hide. That way, whatever HTML you pass within that <custom-dialog> will be fed into your Dialog's <slot> (designed beaviour of slot).
That way you also save the hassle of having to manually instantiate your Dialog component.
Then you can toggle your <custom-dialog> visibility (with v-if or v-show) or even manipulate its position in the DOM as you mention in your code; you can access its DOM node as $el: this.$refs.ModalContent.$el when ModalContent is a Vue instance.
You could also factorize the showModal method by delegating it to the Dialog component.
Code example:
Vue.component('modal-dialog', {
template: '#modal-dialog',
data() {
return {
modalShown: false,
};
},
methods: {
showModal() {
this.modalShown = true;
},
hideModal() {
this.modalShown = false;
},
},
});
new Vue({
el: '#app',
methods: {
showModal() {
this.$refs.ModalContent.showModal();
},
},
});
/*
https://sabe.io/tutorials/how-to-create-modal-popup-box
MIT License https://sabe.io/terms#Licensing
*/
.modal {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
opacity: 0;
visibility: hidden;
transform: scale(1.1);
transition: visibility 0s linear 0.25s, opacity 0.25s 0s, transform 0.25s;
}
.modal-content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: white;
padding: 1rem 1.5rem;
width: 24rem;
border-radius: 0.5rem;
}
.close-button {
float: right;
width: 1.5rem;
line-height: 1.5rem;
text-align: center;
cursor: pointer;
border-radius: 0.25rem;
background-color: lightgray;
}
.close-button:hover {
background-color: darkgray;
}
.show-modal {
opacity: 1;
visibility: visible;
transform: scale(1.0);
transition: visibility 0s linear 0s, opacity 0.25s 0s, transform 0.25s;
}
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<modal-dialog ref="ModalContent">
Hello!
</modal-dialog>
<h1>Hello World</h1>
<button v-on:click="showModal">Show modal</button>
</div>
<template id="modal-dialog">
<div class="modal" :class="{'show-modal': modalShown}" #click="hideModal">
<div class="modal-content">
<span class="close-button" ref="closeButton" #click="hideModal">×</span>
<slot></slot>
</div>
</div>
</template>
Now if you really want to fiddle with $slot, #Sphinx's linked answer in the question comments is an acceptable approach. Note that the accepted answer there also favours the standard usage. It seems to me this is also what #Sphinx implies in their 2nd comment.

Vue transition - transform translate not working

So I have the following code:
HTML:
<transition name="slide-left-centered">
<div v-if="test" style="position: fixed; transform: translate(0, 100%)">
test code
</div>
</transition>
CSS:
.slide-left-centered-enter,
.slide-left-centered-leave-to {
transform: translateX(-100%);
opacity: 0;
}
.slide-left-centered-enter-active {
transition: all .3s ease;
}
.slide-left-centered-leave-active {
transition: all .5s ease;
}
If I were to toggle it on and off, it only fades with the opacity but does not move. This works once I remove transform from the HTML.
https://codesandbox.io/s/92mv6ov6xy
I have figured out the problem
This won't work as inline styling takes precedent.
In my real problem, it is using a class which is a child of another class. The reason why it didn't work was because of specificity. I have added !important to the transition class and now it works e.g.
transform: translateX(-100%) !important;

Scroll bar below fixed header with Vuetify + Electron

I am using Vuetify and Electron to make an app to help me with certain tasks at my job. I have disable the browserWindow frame and made my header the draggable area with a button to close the window. I am using the electron vuetify template
vue init vuetifyjs/electron
My problem is the scrollbar reaches all the way to the top but I would like it below my fixed header.
I have tried playing with overflow properties on the html, body, app div, and content div tags but i have not been successful.
How would I accomplish this?
This is purely a CSS question really as you can see this behaviour in the browser too with similar layouts. The easiest way to fix this is using a flex layout:
HTML:
<div class="container">
<div class="titlebar"></div>
<div class="content">
<h1>So much content we scroll</h1>
<h1>So much content we scroll</h1>
<!-- etc -->
</div>
</div>
CSS:
body {
margin: 0;
padding: 0;
overflow: hidden;
}
.container {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
}
.titlebar {
background-color: blue;
height: 35px;
flex-shrink: 0;
}
.content {
flex-grow: 1;
overflow-x: auto;
}
Check out this out in this CodePen
I'd like to offer a Vuetify specific answer for this question, this should apply whether or not Electron is involved.
Vuetify's default styles make this a bit more difficult than a simple CSS solution can give you, especially when the layout gets more complex.
For this example I'm using the complex layout from Vuetify's pre-defined themes here
Vuetify ships with an overflow-y: scroll on the html element so the first step is adding an override for this.
html {
overflow: hidden;
}
This will get rid of the bar on the right side that spans the whole height of the app.
Next you will want to set your v-content area as the scrollable area. There are a few gotchas to watch out for when you're setting this area:
Display flex is already declared
Vuetify sets padding in the style attribute so you'll need to override depending on your case
You'll need a margin the height of your header(only matters if you're changing header height from 64px)
You'll need to remove the header height from the height of the content container using calc(Same as above)
If you have a nav drawer on the right side you'll need to bind a class to take care of this.
My CSS for v-content looks like this, you will need an important to override the padding since it is set by Vuetify through style binding:
main.v-content {
width: 100vw;
height: calc(100vh - 64px);
flex-direction: column;
overflow: scroll;
margin-top: 64px;
padding-top: 0 !important;
}
I also have a class bound to the state of the temporary right drawer on the v-content tag in the template, this makes sure that the scroll bar doesn't disappear underneath the right nav drawer when it's open:
<v-content :class="{ draweropen: drawerRight }">
And the CSS for that bound class, once again you'll need an important to remove the default right padding Vuetify puts on v-content when the drawer is open:
.draweropen {
width: calc(100vw - 300px) !important;
padding-right: 0 !important;
}
You can optionally set the flex-direction to column-reverse if your content is bottom loaded like a chat which is what I'm doing in this CodePen Example
I built a little component that wraps the v-main and moves the scrollbar to the main container instead of the default (the entire html).
Simply replace v-main with this and you're done.
<template>
<v-main class="my-main">
<div class="my-main__scroll-container">
<slot />
</div>
</v-main>
</template>
<script>
export default {
mounted: function() {
let elHtml = document.getElementsByTagName('html')[0]
elHtml.style.overflowY = 'hidden'
},
destroyed: function() {
let elHtml = document.getElementsByTagName('html')[0]
elHtml.style.overflowY = null
},
}
</script>
<style>
.my-main
height: 100vh
.my-main__scroll-container
height: 100%
overflow: auto
</style>

Fixed attachment background image flicker/disappear in chrome when coupled with a css transform

I am currently doing a parallax website theme. The background images need to be attached as fixed for certain 'div's and 'section's to avoid jquery indulging in everything. The problem was the background images of the tags below any animated item disappeared while the transformation is being done, only on Google Chrome. Remedy?
This has been a very common unsolved mystery. Recently I had the same problem, and '-webkit-backface-visibility: hidden', proved to be less than useless (on my 'fixed' attached background), since the background just disappeared when it was set. (Additional Info: the reason is that when the background is set as fixed, it is almost similar to putting a fixed 'div' in the background and setting the original div background to be transparent. Hidden backface does the obvious).
To solve the current problem, try setting the 'position' propery of the element as 'static', or if you have given it some other value, namely 'relative', 'fixed' or 'absolute', just remove those.
If you don't remember setting the position property, and the problem still persist, my suggestion is that you use a debugging tool on chrome or firefox, to
make sure there are no manually set values to the 'position' property other than
'static'.
Just spent half an hour searching... Thought this could make it easier for you... regards. :)
Same problem here. I had a sticky header using position:fixed; that flickered in PC Chrome 34. I tried the solutions in this thread, position:static; in the parent broke other parts. But I know adding -webkit-transform: translate3d(0,0,0); basically makes Chrome turn that html into a layer so that it won't get repainted. That worked for me.
element {
position:fixed;
top:0;
left:50%;
width:960px;
height:50px;
margin-left:-480px;
-webkit-transform: translate3d(0,0,0);
/* ...all other CSS... */
}
UPDATE
future-friendly answer is to use the will-change property to create a layer!
W3 specs
CanIUse
MDN definition
element {
position:fixed;
top:0;
left:50%;
width:960px;
height:50px;
margin-left:-480px;
will-change:top;
/* ...all other CSS... */
}
And I'll be honest, this seems like a weird solution to fix the flicker, but in essence it makes the element a layer, same as translate3d().
Maybe a little late to answer, but it seems that the bug comes with the background-attachment: fixed property in chrome. I found a solution changin its value to "scroll". It will cause a jitterin effect on firefox but you can avoid it using a media-browser query in your CSS, something like this:
.yourstellarlayer{
background-attachment: fixed;
}
/*only for webkit browsers*/
#media screen and (-webkit-min-device-pixel-ratio:0) {
.yourstellarlayer{
background-attachment: scroll;
}
}
Hope it helps!
I was having the same issue with Chrome, it seems to be a bug that occurs when there is too much going on inside the page, I was able to fix it by adding the following transform code to the fixed position element, (transform: translateZ(0);-webkit-transform: translateZ(0);) that forces the browser to use hardware acceleration to access the device’s graphical processing unit (GPU) to make pixels fly. Web applications, on the other hand, run in the context of the browser, which lets the software do most (if not all) of the rendering, resulting in less horsepower for transitions. But the Web has been catching up, and most browser vendors now provide graphical hardware acceleration by means of particular CSS rules.
Using -webkit-transform: translate3d(0,0,0); will kick the GPU into action for the CSS transitions, making them smoother (higher FPS).
Note: translate3d(0,0,0) does nothing in terms of what you see. it moves the object by 0px in x,y and z axis. It's only a technique to force the hardware acceleration.
#element {
position: fixed;
/* MAGIC HAPPENS HERE */
transform: translateZ(0);
-moz-transform: translatez(0);
-ms-transform: translatez(0);
-o-transform: translatez(0);
-webkit-transform: translateZ(0);
-webkit-font-smoothing: antialiased; /* seems to do the same in Safari Family of Browsers*/
}
This really bugged me and it almost ruined my night. My fix is to set
background-attachment: scroll;
It worked on my project.
Before this, I had it on fixed. Hope this helps.
For me the issue was the styles attach to the parent elements of the div who has the fixed background, I put -webkit-backface-visibility: inherit; to the two main parents of my fixed div.
in my case I was using foundation off-canvas so it goes like this
.off-canvas-wrap{
-webkit-backface-visibility:inherit;
}
.inner-wrap{
-webkit-backface-visibility:inherit;
}
We had a similar problem with a position: fixed; element. This element contained a relatively positioned container, containing an absolutely positioned image. On CSS transition the image disappeared, when the transition was done is re-appeared.
We tried solving the problem by setting the -webkit-backface-visibility to hidden on several elements, including the body element, but this did not help. With the help of this thread we used Chrome's web inspector to fiddle around with elments' position properties and luckily were able to solve the problem without having to alter the site that much. (all we had to do was change the position of the parent of the fixed element to static)
An update almost 5 years in the future... This still seems to be a problem with chrome. I've tried most of the solutions mentioned including adding:
transform: translate3d(0,0,0);
-webkit-transform: translate3d(0,0,0);
and it is not fixing the stuttering issue. adding background-attachment: scroll takes away the parallax effect which is crucial to the UX of the site. The solution above that mentions adding a parent element is not changing anything for me. Any other ideas from people that have had this issue recently? I'm using Gatsby(React) on the front end.
Here is a solution that works (2014.7.11) at firefox 30.0, chrome 35.0, opera 22.0, ie 11.0:
STEP 1: add these lines at .htaccess:
# cache for images
<FilesMatch "\.(png)$">
Header set Cache-Control "max-age=10000, public"
</FilesMatch>
detailed description of this problem and how to fix it:
https://code.google.com/p/chromium/issues/detail?id=102706
STEP 2: add images preloading, for example:
var pics = []; // CREATE PICS ARRAY
$(document).ready(function(){
...
preload(
'/public/images/stars.red.1.star.png',
'/public/images/stars.red.2.star.png',
'/public/images/stars.red.3.star.png',
'/public/images/stars.red.4.star.png',
'/public/images/stars.red.5.star.png',
'/public/images/stars.empty.png'
);
...
$('.rating').on('mousemove', function(event){
var x = event.pageX - this.offsetLeft;
var id = getIdByCoord(x); //
if ($(this).data('current-image') != id) {
$(this).css('background-image', 'url(' + pics[id].src + ')');
$(this).data('current-image', id);
}
})
...
})
...
// PRELOAD FUNCTION TO SET UP PICS ARRAY IN MEMORY USING IMAGE OBJECT
function preload() {
for (i = 0; i < arguments.length; i++) {
pics[i] = new Image();
pics[i].src = arguments[i];
// alert("preload " + arguments[i]);
}
}
P.S. thanks Shawn Altman
My task was to create a page with a parallax effect.
After attempts to fix this by means of CSS I came up with the following solution.
JavaScript:
var isChrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
if (isChrome)
{
var itemArr = $('.slider-title');
$(window).scroll(function()
{
var pos = $(window).scrollTop();
var wh = window.innerHeight;
$(itemArr).each(function(i, item){
var p = $(item).position();
var h = $(item).height();
if (p.top + h > pos && p.top < pos+wh)
{
// items ir redzams
var prc = (p.top - pos +h)/wh ;
//console.log(prc);
$(item).css({'background-position':'center '+prc+'%'});
}
});
});
}
CSS:
/*only for webkit browsers*/
#media screen and (-webkit-min-device-pixel-ratio:0) {
.slider-title{
background-size:auto;
background-position: center 0%;
}
}
.slider-title would be the item with background-attachment fixed.
So I am on Chrome version 40 and still seeing this issue. The workaround which is working for me at the moment is by creating a inner div setting position relative on that div and making it fit the height of its parent and setting the background on the parent div with a background attachment of fixed:
<section style="background-attachment: fixed;">
<div style="position: relative;">
// Code goes here including absolute posiioned elements
</div>
</section>
The problem seems to occur when you have a position relative and background attachment fixed on the same element in my case.
Hope this helps.
This one is late to party but an amazing discovery,
as I can see mostly css framework users, Bootstrap, Foundation (others) , have issues, and I am sure many of you also have scroll to top js functions that show scroll to top button as user starts scrolling down ,
if you have anything like this ( Bootstrap has it built in )
.fade {
opacity: 0;
-webkit-transition: opacity .35s linear;
-o-transition: opacity .35s linear;
transition: opacity .35s linear;
}
.fade.in {
opacity: 1;
}
or you are showing some element via ,
-webkit-transition: opacity .35s linear;
-o-transition: opacity .35s linear;
transition: opacity .35s linear;
or you are adding any kind of element or element class with transition , on scroll down, via js ( animation.css, waypoints.js, velocity.js )
remove transition/class if possible from that element or recheck when that element appears in order to fix the choppy Chrome issue.
Add the transform property to your element with fixed background image. You can have any set position.
#thediv {
width: 100%;
height: 600px;
position: relative;
display: block;
background-image: url(https://cdn.shopify.com/s/files/1/1231/8576/files/hockeyjacket1.jpg);
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-attachment: fixed;
border: 10px solid black;
transform: translate3d(0,0,0);
-webkit-transform: translate3d(0,0,0);
}
https://jsfiddle.net/rkwpxh0n/2/
I've had this problem on overlay div below popup window (randomly disappearing in opera 20) - both animated, and activated by script.
<div class="popupwrapper">
<div id="popupdownload" class="popup">
<h1>Test</h1>
</div>
<div class="popupoverlay"></div>
</div>
.popupwrapper {
display: none;
z-index: 9100;
}
.popupwrapper.active {
display: block;
}
.popupwrapper > div {
-webkit-transition: opacity 150ms ease-in-out, -webkit-transform 150ms ease-in-out;
-moz-transition: opacity 150ms ease-in-out, -moz-transform 150ms ease-in-out;
-ie-transition: opacity 150ms ease-in-out, -ie-transform 150ms ease-in-out;
transition: opacity 150ms ease-in-out, transform 150ms ease-in-out;
}
.popupoverlay {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(26,26,26,.9);
opacity: 0;
}
.popup {
position: fixed;
top: 30%;
left: 40%;
padding: 48px;
background: #e6e6e6;
z-index: 9101;
-webkit-transform: scale(1.6);
transform: scale(1.6);
opacity: 0;
}
.popupoverlay.active {
opacity: 1;
}
.popup.active {
-webkit-transform: scale(1);
transform: scale(1);
opacity: 1;
}
Overlay was positioned absolutely (.popupoverlay), but in container which wasn't positioned in any way. I've copied overlay's absolute positioning to parent (.popup) and it works OK.
.popupwrapper {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
display: none;
z-index: 9100;
}
I think problem appears only when positioning of parent elements isn't obvious.
Glad if helped anyone. Regards
Seems to bug in Chrome the moment you add any markup on the element. Try removing the background from such element and give it a position:relative. Inside the element add a new div with the dimensions you need and add the background, just don't add any markup inside of it.
Example:
Current:
<div class="container" style="background-image:url(example.jpg);background-position:center;background-attachment:fixed;background-size:cover;">
<div class="example"></div>
</div>
Corrected:
<div class="container" style="position:relative;">
<div class="added-background" style="position:absolute;width:100%;height:100%;background-image:url(example.jpg);background-position:center;background-attachment:fixed;background-size:cover;">
<div class="example"></div>
</div>
Hope it helps!
Another workaround if you must have position: fixed/relative/absolute maybe because you have an absolutely positioned element inside (as was my case) is to create a wrapper div inside of the flickering div and move the position and background property to that.
e.g.
you had -
<div class="background-flickers' style="background:url('path-to-image'); position:relative">
<absolutely positioned element>
</div>
Possible workaround
<div class="no-more-flicker!">
<div class="wrapper" style="style="background:url('path-to-image'); position:relative">
<absolutely positioned element>
</div>
</div>
I don't have the flicker anymore, apparently the flicker bug does not descend to child containers.
i also had same issues in chrome
it's very simple no need to add any webkit & media tag just follow below steps
1.instead of background:url('path-to-image') set the image like below and set the position as fixed
2.
it will work in chrome as well as IE browser
The issue still persist.
its happening to me on google chrome when i have { background-attachment: fixed; transform: scale(1); transition: transform }
I need background-attachment fixed for parallax effect.
I am scaling my container on scroll.
when tranition and transformed is removed parallax works. Having said that, i can have either one scale effect or parallax effect and not both working on chrome.
Safari doesn't complain and works both like a charm

How to create sticky header bar for a website

I want to create a sticky header bar for a website just like the sticky header on this website (http://www.fizzysoftware.com/) if any on can can help me out with coding or any resource that helps me to create the same. Your reply would be of great help to me.
In your CSS, add
position: fixed;
to your header element. It's just that simple, really.
And next time, try to use right click on something you see on website and choose "Inspect element". I think that every modern browser has it now. Very useful function.
If you want to make it sticky when it's scroll down to a certain point then you can use this function:
$window = $(window);
$window.scroll(function() {
$scroll_position = $window.scrollTop();
if ($scroll_position > 300) { // if body is scrolled down by 300 pixels
$('.your-header').addClass('sticky');
// to get rid of jerk
header_height = $('.your-header').innerHeight();
$('body').css('padding-top' , header_height);
} else {
$('body').css('padding-top' , '0');
$('.your-header').removeClass('sticky');
}
});
And sticky class:
.sticky {
position: fixed;
z-index: 9999;
width: 100%;
}
You can use this plugin and it has some useful options
jQuery Sticky Header
CSS already gives you the answer. Try this out
.sticky {
position: -webkit-sticky;
position: sticky;
top: 0;
}
now add the class sticky to any menu sidebar or anything you want to stick to the top and it will automatically calculate the margin and stick to the top. Cheers.
If you want simplicity in a HTML and CSS option to create a Stiky NavBar you can use the following:
Just create a navbar like this one:
<nav class="zone blue sticky">
<ul class="main-nav">
<li>About</li>
<li>Products</li>
<li>Our Team</li>
<li class="push">Contact</li>
</ul>
</nav>
Remember to add the classes in this case I created a Zone (to separate my HTML in specific areas I want my CSS to be applied) blue (just a color for the nav) and sticky which is the one that gonna carry our sticky function. You can work on other attributes you want to add is up to you.
On the CSS add the following to create the sticky; first I am gonna start with the zone tag
.zone {
/*padding:30px 50px;*/
cursor:pointer;
color:#FFF;
font-size:2em;
border-radius:4px;
border:1px solid #bbb;
transition: all 0.3s linear;
}
now with the sticky tag
.sticky {
position: fixed;
top: 0;
width: 100%;
}
Position fixed meaning it will always be in the same position; and with top 0 I will always be at the top and a 100% width so it covers the whole screen.
And now the color to make our navbar blue
.blue {
background: #7abcff;
You can use this example to create a sticky navbar of yours and play around with the CSS properties to customize it to your liking.
Try This
Add this style to the corresponding
style="position: fixed; width: -webkit-fill-available"
OR
<style>
.className{
position: fixed;
width: -webkit-fill-available;
}
</style>