angular 2 play css animation when div/component is in viewport - html

I am building a landing page with angular and in my third div from top I have some animations. First div occupies 100vh viewspace, another say 50 and then I have following div (all these divs represent individual components):
<div id="about" class="app-about-us-div-container">
<div class="onboarding-flow mdl-grid">
<div class="mdl-cell mdl-cell--4-col">
<div class="circle circle-1">
<i class="onboarding-icon material-icons">local_phone</i>
</div>
<div class="onboarding-text">
<p>Tell us your problem domain and we will customize our solution to meet your specific needs</p>
</div>
</div>
<div class="mdl-cell mdl-cell--4-col">
<div class="circle circle-2">
<i class="onboarding-icon material-icons">group</i>
</div>
<div class="onboarding-text">
<p>Engage your project stakeholders, end users without any time hassle to build together a clear product vision</p>
</div>
</div>
<div class="mdl-cell mdl-cell--4-col">
<div class="circle circle-3">
<i class="onboarding-icon material-icons">trending_up</i>
</div>
<div class="onboarding-text">
<p>Benefit from our analytics to understand your users and their vision for the product. Build Personas to take best design decisions and streamline important product features </p>
</div>
</div>
</div>
</div>
It's css:
.app-about-us-div-container{
position: relative;
height: 70vh;
text-align: center;
background-color: #ECEFF1;
}
.app-about-us-div-container h4{
margin-top: 0%;
padding-top: 20px;
}
.onboarding-flow {
align-content: center;
padding-top: 2%;
}
.circle {
display: inline-block;
width: 150px;
height: 150px;
box-sizing: border-box;
-webkit-border-radius: 75px;
-moz-border-radius: 75px;
border-radius: 75px;
background: transparent;
text-align: center;
border: 3px solid #cccccc;
animation-name: pop;
animation-iteration-count: 1;
animation-duration: 0.3s;
animation-direction: normal;
animation-fill-mode: forwards;
animation-timing-function: ease-in-out;
color: #cccccc;
}
.circle-1 {
animation-delay: 1s;
}
.circle-2 {
animation-delay: 2s;
}
.circle-3 {
animation-delay: 3s;
}
.onboarding-icon {
align-self: center;
font-size: 65px;
position: relative;
top: calc(50% - 35px);
}
.onboarding-text {
position: relative;
padding-top: 2%;
width: 60%;
left: 20%;
}
.onboarding-text p {
font-size: 17px;
}
#keyframes pop {
0% {
color: #F44336;
transform: scale(1);
}
50% {
color: #ffffff;
border-color: #F44336;
background-color: #F44336;
transform: scale(1.2);
}
100% {
color: #ffffff;
border-color: #EF5350;
background-color: #EF5350;
transform: scale(1);
}
}
Now the problem is animations are played on pageload and till the user reaches to this div it's over. How can I make sure that these animations are played when this div is in viewport or at the top of the screen (I am not sure what could be the best option as the div above occupies 50vh so at one point both of them are visible 50 50)? Is anular animation of any help in this case?
It's component:
#Component({
selector: 'app-about-us',
templateUrl: './about-us.component.html',
styleUrls: ['./about-us.component.css']
})
export class AboutUsComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}

I used ng-in-viewport to achieve something similar to this. Follow the instructions available on the plugin's GitHub page:
1. Install the plugin
npm install --save ng-in-viewport intersection-observer
Note: intersection-observer is a polyfill used to support all major browsers
2. Usage Example
In your module:
import { InViewportModule } from 'ng-in-viewport';
import 'intersection-observer';
In your template:
<div in-viewport (inViewportAction)="action($event)" class="circle circle-1">
<i class="onboarding-icon material-icons">local_phone</i>
</div>
In your component:
action(event : any) {
//do something with the element
}
You could for example use Angular's Renderer to add a css class to the element:
import {Renderer2 } from '#angular/core';
...
constructor(private renderer: Renderer2) {}
action(event : any) {
if(event.value){ //if element is in viewport
this.renderer.addClass(event.target, "circle-1");
}
}

Related

How to animate an already existing skill bar

I already have a skill bar created on my page, but I was wondering if there was a way to animate it, so that when you scroll to that area the bar extends out from nothing to the full length of the bar. Here is my html for the bar:
<div id="skills_skill">
<div class="col-xs-12 col-md-4" id='skills_text'>
Example Skill
</div>
<div class="col-xs-12 col-md-8" id='skills_container'>
<div class="skills example">90%</div>
</div>
</div>
And here is the css:
#skills_text {
font-weight: bold;
border-right: 1px solid white;
}
.skills {
text-align: right;
padding-right: 20px;
line-height: 20px;
color: black;
border-radius: 20px;
}
.example {
width: 90%;
background-color: white;
}
I assume you use Bootstrap 4. I will use Bootstrap progress component for this example. This snippet code only for the progress bar animation. You should use javascript to keep track of your scroll position to trigger the animation. Please let me know if you need help
.progress-bar {
animation: progress 300ms ease-in-out;
animation-fill-mode: forwards;
}
#keyframes progress {
0% {
width: 0;
}
100% {
width: 100%;
}
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.2/css/bootstrap.min.css" rel="stylesheet"/>
<div class="progress">
<div class="progress-bar" role="progressbar" aria- valuenow="25" aria-valuemin="0" aria-valuemax="100"> </div>
</div>

backface-visibility is working only partly

I'm trying to make a card that flipping on hover. To hide the back part of a card I use backface-visibility: hidden. But it only hides background of the back part while all the elements are still visible on the front side in rotated variant.
I use Google Chrome.
Here's my html code
<div class="card">
<div class="card__side card__side--front">
<div class="card__picture card__picture--1"></div>
<div class="card__heading">
<span class="card__heading-span card__heading-span--1">
The sea explorer
</span>
</div>
<div class="card__details">
<ul class="card__list">
<li class="card__item">3 day tour</li>
<li class="card__item">Up to 30 people</li>
<li class="card__item">2 tour guides</li>
<li class="card__item">Sleep in cozy hotels</li>
<li class="card__item">Difficulty: easy</li>
</ul>
</div>
</div>
<div class="card__side card__side--back card__side--back-1">
<div class="card__cta">
<div class="card__price-box">
<p class="card__price--only">Only</p>
<p class="card__price--value">$297</p>
</div>
Book now
</div>
</div>
</div>
And here's my SASS code
.card {
position: relative;
height: 52rem;
perspective: 150rem;
&__side {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 52rem;
border-radius: 3px;
overflow: hidden;
box-shadow: 0 1.5rem 4rem rgba($color-black, .15);
transform-style: preserve-3d;
backface-visibility: hidden;
transition: all .8s ease;
&--front {
background-color: $color-white;
}
&--back {
transform: rotateY(180deg);
&-1 {
background-image:
linear-gradient(to right bottom,$color-secondary-light,$color-secondary-dark);
}
&-2 {}
&-3 {}
}
}
&:hover &__side--front {
transform: rotateY(-180deg);
}
&:hover &__side--back {
transform: rotateY(0);
}
// Front side styles
&__picture {
&--1 {}
&--2 {}
&--3 {}
}
&__heading {
}
&__heading-span {
&--1 {}
&--2 {}
&--3 {}
}
&__details {
}
&__list {
width: 80%;
margin: 0 auto;
list-style-type: none;
}
&__item {
&:not(:last-child) {
border-bottom: 1px solid $color-gray-light-2;
}
}
//Back side styles
&__cta {
#include absoluteCenter();
width: 90%;
text-align: center;
}
&__price-box {
margin-bottom: 6rem;
color: $color-black;
text-align: center;
}
&__price--only {
font-size: 1.4rem;
text-transform: uppercase;
}
&__price--value {
font-size: 6rem;
font-weight: 300;
}
}
And this is how the problem actually looks like in Chrome.
Adding transform-style: preserve-3d to .card instead of .card__side fixed the bug for me.

How to animate menu slide up using css animations?

I am working on a pure css based menu. I tried to create a slide up animation of the menu but couldn't get it to work. I looked at a lot of solutions online but none of them worked for my case.
Here's the laydown of my case.
The menu has a title and subitems (submenu). This menu will only be one level.
I need the height of the submenu to zap behind the menu title.
Since the number of sub items are dynamic I want to achieve this without using specific height.
transform: translateY seemed like a better option but the menu items are visible above the title.
I do not want the menu items to appear above the menu title and use translate or something similar.
I'm not sure if I'm on the right track or if I'm missing something elementary.
$(function() {
$('.accordion-tabs__header').click(function() {
$('.accordion-tabs__body').toggleClass('collapsed');
$('.accordion-tabs__body').toggleClass('expanded');
});
});
.accordion-tabs {
position: relative;
top: 2rem;
width: 60%;
}
.accordion-tabs__header {
transition-delay: 1s;
display: flex;
align-items: center;
padding: 1rem 0.5rem;
z-index: 10;
position: relative;
background-color: azure;
}
.accordion-tabs__header__title {
margin: 0;
padding: 0;
}
.accordion-tabs__body {
position: absolute;
width: 100%;
transition: 200ms transform ease-in-out;
}
.accordion-tabs__body.expanded {
z-index: 1;
transform: translateY(0%);
}
.accordion-tabs__body.collapsed {
z-index: 1;
transform: translateY(-100%);
}
.accordion-tabs__body .accordion-tabs__body__link {
display: flex;
align-items: center;
padding: 0.875rem;
background-color: antiquewhite;
}
.accordion-tabs__body .accordion-tabs__body__link a{
text-decoration: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='wrapper'>
<div class="accordion-tabs">
<div class="accordion-tabs__header">
<div class="accordion-tabs__header__title">Menu Title Looong</div>
</div>
<div class="accordion-tabs__body collapsed">
<div class="accordion-tabs__body__link"><a class="link" href="#">Item One</a></div>
<div class="accordion-tabs__body__link"><a class="link" href="#">Item One</a></div>
<div class="accordion-tabs__body__link"><a class="link" href="#">Item Three</a></div>
</div>
</div>
</div>
Here's the codepen to my code - https://codepen.io/flexdinesh/pen/VybwwE
I managed to achieve this with max-height.
Slide-up animation was a bit slow to trigger when I used this code in react. However I made it look okay with ease-out transition.
$(function() {
$('.accordion-tabs__header').click(function() {
$('.accordion-tabs__body').toggleClass('collapsed');
$('.accordion-tabs__body').toggleClass('expanded');
});
});
.accordion-tabs {
position: relative;
top: 2rem;
width: 60%;
}
.accordion-tabs__header {
transition-delay: 1s;
display: flex;
align-items: center;
padding: 1rem 0.5rem;
position: relative;
background-color: azure;
}
.accordion-tabs__header__title {
margin: 0;
padding: 0;
}
.accordion-tabs__header.expanded {
border-bottom: none;
}
.accordion-tabs__body {
overflow: hidden;
position: absolute;
width: 100%;
border-bottom-width: 2px;
border-bottom-style: solid;
}
.accordion-tabs__body.expanded {
max-height: 100vh;
transition: max-height 500ms ease-in;
}
.accordion-tabs__body.collapsed {
max-height: 0;
transition: max-height 200ms ease-out;
}
.accordion-tabs__body__link {
display: flex;
align-items: center;
padding: 0.875rem;
border-top-width: 1px;
border-top-style: solid;
background-color: antiquewhite;
}
.accordion-tabs__body__link a {
text-decoration: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='wrapper'>
<div class="accordion-tabs">
<div class="accordion-tabs__header">
<div class="accordion-tabs__header__title">Menu Title Looong</div>
</div>
<div class="accordion-tabs__body collapsed">
<div class="accordion-tabs__body__link"><a class="link" href="#">Item One</a></div>
<div class="accordion-tabs__body__link"><a class="link" href="#">Item One</a></div>
<div class="accordion-tabs__body__link"><a class="link" href="#">Item Three</a></div>
</div>
</div>
</div>
Here's the updated codepen that works -
https://codepen.io/flexdinesh/pen/VyWzKo

Background Only Applying to Half Page

I am setting the Background of My application using ngStyle
like this <div [ngStyle]="{'background-image': 'url(' + photo + ')','height':'100%','width':'100%','margin':'0px'}" >
But in One of my Components that gets loaded by router-outlet the data is less and only half page gets the background, in rest all other pages its fine.
How to solve this error.
The component Template where the data is less
<div *ngIf="visibleTournament">
<div class = "row">
<div *ngFor="let entry of competitionTeams | keys">
<div class="col-md-4" (mouseleave)= "entry.hideme = false">
<div>
<div (click) = "entry.hideme = !entry.hideme" >
<div class = "groupBox"><div class="placed"><h3><span class = "label label-warning">Group - {{entry.key}}</span></h3></div></div>
</div>
<div class="well box" [hidden] = "!entry.hideme">
<table class="table">
<thead class="thead-inverse">
<tr>
<th>#</th>
<th>Team</th>
<th>Played Games</th>
<th>Points</th>
<th>Goals</th>
<th>GA</th>
<th>GD</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let subValue of entry.value">
<th scope="row">{{subValue.rank}}</th>
<td><img class="img-thumbnail small" src="{{subValue.crestURI}}">{{subValue.team}}</td>
<td>{{subValue.playedGames}}</td>
<td>{{subValue.points}}</td>
<td>{{subValue.goals}}</td>
<td>{{subValue.goalsAgainst}}</td>
<td>{{subValue.goalDifference}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
CSS file of this component
.avatar{
width:30px;
height:30px;
margin-right: 10px;
background: rgba(0,0,0,0);
border: none;
}
.inline{
display: inline-block;
margin: 10px 20px;
}
.check{
min-width: 500px;
}
.selector{
cursor: pointer;
}
.placed{
margin: 0 auto;
}
.box{
/*position: absolute;*/
text-align: center;
background: #ccffda;
padding: 10px 20px;
max-width: 500px;
border: darkgray 1px solid;
z-index: 1;
}
.groupBox{
/*position: relative;*/
text-align: center;
background: rgba(0,0,0,0.3);
padding: 20px 20px;
margin: 2px;
border: darkgray 1px solid;
cursor: pointer;
}
th {
white-space: nowrap;
}
.col-md-4{
margin-bottom: 80px;
}
.fix{
position: absolute;
}
.group{
/*background: rgba(0,0,0,0.4);*/
}
table th {
font-weight: bolder;
/*color:#49fb35;*/
}
.small{
width:20px;
height:20px;
background: rgba(0,0,0,0);
border: none;
}
For Ref My app component
<div [ngStyle]="{'background-image': 'url(' + photo + ')','height':'100%','width':'100%','margin':'0px'}" >
<nav class="navbar navbar-inverse">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" routerLink = "home">Football Data</a>
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav">
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
<div class = "container">
<div class = "row">
<div class = "col-md-12">
<div *ngIf="loading">
<!-- show something fancy here, here with Angular 2 Material's loading bar or circle -->
<div class = "parent">
<div class="spinner">
<div class="rect1"></div>
<div class="rect2"></div>
<div class="rect3"></div>
<div class="rect4"></div>
<div class="rect5"></div>
</div>
</div>
<!--<progress-bar [value]="50" [max]="100"></progress-bar> // Simple Progess Bar-->
</div>
<router-outlet></router-outlet>
</div>
</div>
</div>
</div>
Appcomponent css
html, body{
height: 100%;
font-family: Arial, Helvetica, sans-serif
}
a.active {
background-color: gray;
}
h1 {
color: #00BCD4;
}
.parent{
position: fixed;
left:0;
right:0;
top: 0;
bottom: 0;
background: rgba(0,0,0,0.1);
display: flex; /* establish flex container */
flex-direction: column; /* make main-axis vertical */
justify-content: center; /* align items vertically, in this case */
align-items: center; /* align items horizontally, in this case */
}
.spinner {
margin: 100px auto;
width: 50px;
height: 40px;
text-align: center;
font-size: 10px;
}
.spinner > div {
background-color: black;
height: 100%;
width: 6px;
display: inline-block;
-webkit-animation: sk-stretchdelay 1.2s infinite ease-in-out;
animation: sk-stretchdelay 1.2s infinite ease-in-out;
}
.spinner .rect2 {
-webkit-animation-delay: -1.1s;
animation-delay: -1.1s;
}
.spinner .rect3 {
-webkit-animation-delay: -1.0s;
animation-delay: -1.0s;
}
.spinner .rect4 {
-webkit-animation-delay: -0.9s;
animation-delay: -0.9s;
}
.spinner .rect5 {
-webkit-animation-delay: -0.8s;
animation-delay: -0.8s;
}
#-webkit-keyframes sk-stretchdelay {
0%, 40%, 100% { -webkit-transform: scaleY(0.4) }
20% { -webkit-transform: scaleY(1.0) }
}
#keyframes sk-stretchdelay {
0%, 40%, 100% {
transform: scaleY(0.4);
-webkit-transform: scaleY(0.4);
} 20% {
transform: scaleY(1.0);
-webkit-transform: scaleY(1.0);
}
}
How the component Loads up in browser
I don't know what you think this does
<div [ngStyle]="{'background-image': 'url(' + photo + ')','height':'100%','width':'100%','margin':'0px'}" >
but here's the result in plain CSS:
{
background-image: url(photo);
height: 100%;
width: 100%;
margin: 0;
}
Now maybe you think that's supposed to make your background-image stretch to 100% width and height of the <div> but... it's really not.
If (photo) is smaller than the div, you must set your div's background-size property in order to make the image cover all background.
You should set it to cover.
Tip: Whenever you need help with CSS, if you skip the AngularJS part, and just ask: this is my resulting CSS, why isn't my picture full size? you drastically increase chances of getting a proper answer fast and it might even come from someone who doesn't know AngularJS (and who doesn't need to know it in order to help you).
If my answer doesn't solve your problem you need to create a minimal, complete and verifiable example, so we can inspect and see why your background-image doesn't apply. Whatever happens in your app, it still outputs HTML + CSS + JS. And that's what you need help with.

Button hover on a changing background

I am making a website for a friend but since I'm still a beginner at this I'm not sure how to proceed. I'm making a simple intro page with his name and an enter button. The enter button has a hover function that when you hover your mouse over it it changes color, meanwhile I have a background div loop that iterates through 5 different backgrounds. My button and its hover function work fine on the first background picture, but once it changes the hover function no longer works until it comes back to that very first picture.
The background changing is a css code I found here on stack while I made everything else.
Here's My Code with what I'm working with.
Any ideas why the button hover isn't working on all the backgrounds?
HTML
<body class="intro-body">
<div id="background-change">
<div class="background-image image1">
<h1 class="intro-title">Name Here</h1>
<p class="intro-button intro-button-hover">Enter</p>
</div>
<div class="background-image image2">
<h1 class="intro-title">Name Here</h1>
<p class="intro-button intro-button-hover">Enter</p>
</div>
<div class="background-image image3">
<h1 class="intro-title">Name Here</h1>
<p class="intro-button intro-button-hover">Enter</p>
</div>
<div class="background-image image4">
<h1 class="intro-title">Name Here</h1>
<p class="intro-button intro-button-hover">Enter</p>
</div>
<div class="background-image image5">
<h1 class="intro-title">Name Here</h1>
<p class="intro-button intro-button-hover">Enter</p>
</div>
</div>
</body>
CSS
.intro-body {
text-align: center;
background-repeat: no-repeat;
background-position: center;
}
.intro-title {
padding-top: 20vh;
padding-bottom: 5vh;
font-size: 650%;
text-transform: uppercase;
text-align: center;
color: white;
letter-spacing: 5px;
text-shadow: 2px 2px black;
}
.intro-button {
border: solid;
color: white;
padding: 20px 45px;
display: inline-block;
letter-spacing: 2px;
text-align: center;
text-transform: uppercase;
cursor: pointer;
}
p.intro-button-hover:hover {
background-color: white;
opacity: 0.85;
padding: 23px 48px;
letter-spacing: 2px;
text-align: center;
text-transform: uppercase;
color: black;
border: unset;
cursor: pointer;
}
.background-image {
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
}
.image1{
background: url("http://placekitten.com/1200/1200") no-repeat center fixed;
}
.image2{
background: url("http://placekitten.com/1200/1300") no-repeat center fixed;
}
.image3{
background: url("http://placekitten.com/1300/1200") no-repeat center fixed;
}
.image4{
background: url("http://placekitten.com/1300/1300") no-repeat center fixed;
}
.image5{
background: url("http://placekitten.com/1300/1400") no-repeat center fixed;
}
#keyframes backgroundchangeFadeInOut {
0% {
opacity:1;
}
17% {
opacity:1;
}
25% {
opacity:0;
}
92% {
opacity:0;
}
100% {
opacity:1;
}
}
#-webkit-keyframes backgroundchangeFadeInOut {
0% {
opacity:1;
}
17% {
opacity:1;
}
25% {
opacity:0;
}
92% {
opacity:0;
}
100% {
opacity:1;
}
}
#background-change div:nth-of-type(1) {
animation-delay: 20s;
-webkit-animation-delay: 20s;
}
#background-change div:nth-of-type(2) {
animation-delay: 15s;
-webkit-animation-delay: 15s;
}
#background-change div:nth-of-type(3) {
animation-delay: 10s;
-webkit-animation-delay: 10s;
}
#background-change div:nth-of-type(4) {
animation-delay: 5s;
-webkit-animation-delay: 5s;
}
#background-change div:nth-of-type(5) {
animation-delay: 0s;
-webkit-animation-delay: 0s;
}
#background-change div {
animation-name: backgroundchangeFadeInOut;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
animation-duration: 25s;
-webkit-animation-name: backgroundchangeFadeInOut;
-webkit-animation-timing-function: ease-in-out;
-webkit-animation-iteration-count: infinite;
-webkit-animation-duration: 25s;
}
Just update with the following code, I have just added internal js.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("p").mouseover(function(){
$("p").css("background-color", "white");
});
$("p").mouseout(function(){
$("p").css("background-color", "");
$("p").css("color", "black");
});
});
And remove the properties with '//' in the css:
p.intro-button-hover:hover {
// background-color: #fff;
//opacity: 0.4;
padding: 23px 48px;
letter-spacing: 2px;
text-align: center;
text-transform: uppercase;
//color: black;
border: unset;
cursor: pointer;
}
Quickly looking at this, the reason for it is that you actually have 5 different buttons fading in and out, which messes things up.
Do something like this (pseudocode)
<body class="intro-body">
<div id="callout">
<h1 class="intro-title">Name Here</h1>
<button class="intro-button intro-button-hover">Enter</button>
</div>
<div id="background-change">
<div class="background-image image1"></div>
<div class="background-image image2"></div>
<div class="background-image image3"></div>
<div class="background-image image4"></div>
<div class="background-image image5"></div>
</div>
</body>
Naturally position the callout section over the background image and you're good to go.
I have gone through your code and tried debugging the problem. The problem is mostly from your animation code. Try rewriting your animation code. I have tested it removing the animation code, to check if the hover is working properly or not, and it works fine. There is also a bug with your animation code which makes the Enter button disappear for a while after the first animation iteration and appear again after few seconds.
If possible try using JQuery, as it makes your job easier for using animations. For example, can simply use fadeIn(); and fadeOut(); functions for the animation you have been doing in your CSS animation code.